← back to Re Flyer Aggregator
flyers.agentabrams.com: static gallery of every aggregated CRE deal as an ownable flyer (type/price/market/parties/date/source + sort/density/type/market filters); party extraction from headlines; wired into 4x/day cron (TK-10708)
a2b0fa973b8af6a5e6363d62a1e2d9391ccfd608 · 2026-08-19 15:56:34 -0700 · Steve Abrams
Files touched
A public/flyers/flyers.jsonA public/flyers/index.htmlA scripts/build-flyers-site.mjsM scripts/dtt-cron.sh
Diff
commit a2b0fa973b8af6a5e6363d62a1e2d9391ccfd608
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Aug 19 15:56:34 2026 -0700
flyers.agentabrams.com: static gallery of every aggregated CRE deal as an ownable flyer (type/price/market/parties/date/source + sort/density/type/market filters); party extraction from headlines; wired into 4x/day cron (TK-10708)
---
public/flyers/flyers.json | 1 +
public/flyers/index.html | 68 ++++++++++++++++++++++++
scripts/build-flyers-site.mjs | 121 ++++++++++++++++++++++++++++++++++++++++++
scripts/dtt-cron.sh | 4 +-
4 files changed, 193 insertions(+), 1 deletion(-)
diff --git a/public/flyers/flyers.json b/public/flyers/flyers.json
new file mode 100644
index 0000000..f37b87e
--- /dev/null
+++ b/public/flyers/flyers.json
@@ -0,0 +1 @@
+[{"type":"Sale","price":1200000000,"price_label":"$1.2B","market":"SoCal","title":"Rexford to Sell $1.2B SoCal Portfolio to EQT","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/rexford-eqt-sale-california-industrial/","date":"Wed, 19 Aug 2026 20:30:46 +0000","buyer":"EQT","seller":"Rexford"},{"type":"Sale","price":1200000000,"price_label":"$1.2B","market":"National","title":"EQT Real Estate to Pay $1.2B for Industrial Portfolio","source":"CommercialSearch","link":"https://news.google.com/rss/articles/CBMilgFBVV95cUxONmRobUZwZTlJSkwtUWFOdzk2T0pCTUF4R1c1YmdyZFFsbWd0endKRGtsbzZpRU5sMFNXeTdpRXE0Rm1rZHdNY3NnRFNBZlcxbHo2OHZJa2lJTXczVG54RTJRcngwM1VDSmY3QlZmN3BxWEx6SFVNU2dBTDlqYWhyS1liWGNPLUFjRUdCUWdqb3NzNW5zTUE?oc=5","date":"Tue, 18 Aug 2026 20:04:28 GMT","buyer":"EQT Real Estate","seller":null},{"type":"Sale","price":450000000,"price_label":"$450M","market":"tri-state","title":"National Resources sells handful of properties in sprawling $450M deal","source":"TRD-NY","link":"https://therealdeal.com/new-york/tristate/2026/08/19/national-resources-sells-handful-of-properties-in-450m-deal/","date":"Wed, 19 Aug 2026 15:30:30 +0000","buyer":null,"seller":"National Resources"},{"type":"Sale","price":450000000,"price_label":"$450M","market":"Tri-State","title":"Lincoln Property Partnership Acquires $450M Mixed-Use Tri-State Portfolio","source":"ConnectCRE","link":"https://www.connectcre.com/stories/lincoln-property-partnership-acquires-450m-mixed-use-tri-state-portfolio/","date":"Wed, 19 Aug 2026 21:00:09 +0000","buyer":"Lincoln Property Partnership","seller":null},{"type":"Sale","price":435000000,"price_label":"$435M","market":"National","title":"Oxford Properties Buys One Marina Park Drive For $435M","source":"Bisnow","link":"https://news.google.com/rss/articles/CBMimwFBVV95cUxPWlRQS3psNkNPWTlXclYtUXhuLUthX09kOGpVMUVVRTFPcnprdERVZFE2N0Z0aVB5bGI1bmhwM0IyeURmQUhBVmtQR2dBUXpYT3RfbDJRNHYxbVpIN1p3cmFqVnJXUnFIQ0ZIcnFNbFcycUdUU3V2NTg4S29XQnliV0xVY05sT1g5THpHbml2TWM2ZnEySV80b29hWQ?oc=5","date":"Wed, 19 Aug 2026 16:41:28 GMT","buyer":"Oxford Properties","seller":null},{"type":"Loan","price":281000000,"price_label":"$281M","market":"National","title":"Millennium Partners Lands $281M Loan For Winthrop Center Tower","source":"Bisnow","link":"https://news.google.com/rss/articles/CBMi2gFBVV95cUxPOWJkUGp2cTU0eU9Lc002UkVOQld1Nm9lM1hnWEp3TEN0Q2tmLVdTTk5Xemo4dm9WeTZJQnNxS2xtZ0RyUHUwdV9TMnF3Mk5QbjQzYmhwTThnNWJ6ZTNldm5URDdPaXlvRlBoWXBRd1owZWR1UGNGVDR4MVpoRWEzMVpMaDc4cGI2NFpSNGlzdEJyMXBXN3pIWWdpeTZIQkZBSURNQ09HLUdieEhsUXlDckxYZlJDbjF6S3h5aVlMMGRqUV8wdTRBSE14V01ibU9hQk54ZE1ZREpqUQ?oc=5","date":"Mon, 17 Aug 2026 20:17:00 GMT","buyer":null,"seller":null},{"type":"Sale","price":167000000,"price_label":"$167M","market":"National","title":"Dov Hertz Offloads Major Staten Island Industrial Site for $167M","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/dov-hertz-sells-staten-island-industrial-south-avenue/","date":"Wed, 19 Aug 2026 21:05:43 +0000","buyer":null,"seller":"Dov Hertz"},{"type":"Sale","price":160000000,"price_label":"$160M","market":"Portland","title":"Exclusive: BGO Pays $160M for Portland Asset - Multi-Housing News","source":"MultiHousingNews","link":"https://news.google.com/rss/articles/CBMiggFBVV95cUxQTElKQnM1dEttVzF0MjQ0N3IzUzBWY0M3eHlhMWpScDlabk9aQm40eV9xa0dmaVlCaF96aWFLX2VEeGNkR2Y5UUE1QVdOeDAyWWFvdXJXTTByZ2tIOHZHY0o0U2M2dFhFQUdkNTYyeGNwZXpoX0pPUkRNTnhtTVQ0MlJB?oc=5","date":"Wed, 19 Aug 2026 09:31:55 GMT","buyer":null,"seller":null},{"type":"Loan","price":155000000,"price_label":"$155M","market":"Atlanta","title":"DeKalb County launching $155M bond program targeting housing access","source":"TRD-National","link":"https://therealdeal.com/national/atlanta/2026/08/19/dekalb-county-launching-155m-bond-for-housing-access/","date":"Wed, 19 Aug 2026 21:00:00 +0000","buyer":null,"seller":null},{"type":"Loan","price":125000000,"price_label":"$125M","market":"Miami","title":"Craig Robins, Raycliff land $125M construction loan for Miami Design District office-retail project","source":"TRD-Miami","link":"https://therealdeal.com/miami/2026/08/19/craig-robins-raycliff-capital-secure-loan-for-miami-project/","date":"Wed, 19 Aug 2026 19:30:00 +0000","buyer":null,"seller":null},{"type":"Development","price":125000000,"price_label":"$125M","market":"Miami","title":"Miami Design District Owners Land $125M to Build Mixed-Use Building","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/miami-design-district-snohetta-sweetbird-north/","date":"Wed, 19 Aug 2026 17:10:31 +0000","buyer":null,"seller":null},{"type":"Loan","price":112000000,"price_label":"$112M","market":"National","title":"Developer Iadisernia Lands Mezz Loan to Finish Hallandale, Fla., Condo Tower","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/oasis-cottonwood-giuseppe-iadisernia-hallandale-beach/","date":"Wed, 19 Aug 2026 21:45:27 +0000","buyer":null,"seller":null},{"type":"Lease","price":100000000,"price_label":"$100M","market":"Boston","title":"Buchanan Ingersoll Rooney Extends 115,335 SF Office Lease in Downtown Pittsburgh","source":"REBusinessOnline","link":"https://rebusinessonline.com/buchanan-ingersoll-rooney-extends-115335-sf-office-lease-in-downtown-pittsburgh/","date":"Wed, 19 Aug 2026 13:21:04 +0000","buyer":null,"seller":null},{"type":"Sale","price":78000000,"price_label":"$78M","market":"National","title":"Finmarc Buys NoVA Office Complex for $78M","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/finmarc-virginia-office-cim-group/","date":"Wed, 19 Aug 2026 17:50:02 +0000","buyer":"Finmarc","seller":null},{"type":"Sale","price":78000000,"price_label":"$78M","market":"National","title":"Breakthrough Properties Acquires 270,000 Square Foot Life Sciences Facility In Everett For $78M","source":"Traded","link":"https://news.google.com/rss/articles/CBMiekFVX3lxTE5oM3hKc3hMQ0ExWDJRd2E0ZHJlSDYxanExQzZjZUJGR3pEZ1hkZUtkcFE5WWx0d0tCWC13LVl2RXQ2M1o0OE1HcXpCRmFjYXFzZE1zX1dtQUlNOUlfR29Hb0xpY1hhcC1HcFY5cGpYbkNUX2ZDZlQxSlR3?oc=5","date":"Tue, 18 Aug 2026 10:03:53 GMT","buyer":"Breakthrough Properties","seller":null},{"type":"Loan","price":75000000,"price_label":"$75M","market":"National","title":"Developers Land $75M Loan for Redo and Buy of Whitestone Retail Center","source":"GlobeSt","link":"https://news.google.com/rss/articles/CBMiqAFBVV95cUxNUmhPUDZYMnhITzlvdUE0MnNwRGF2dWVvWVhNbkZtbFl4b0FLMlo1TlN2YnQ4djdidVZzV2tpNGZOWFI3eFBxWm9oNzZWNGFqTGxMSXU0OW5ndU4yYmcyQ1UzNHdiYy12YV9vMEJVOG1DdlV1alB4WDh2SUN6Y0ZwVFo0QkMzNXBFa0ZJbVFWdkJaVnV6T0FPZUVlVEZucmhzWTk0cDhwNUc?oc=5","date":"Tue, 18 Aug 2026 13:02:34 GMT","buyer":null,"seller":null},{"type":"Sale","price":72000000,"price_label":"$72M","market":"Denver","title":"Vantage Sells Denver Community for $72M - Multi-Housing News","source":"MultiHousingNews","link":"https://news.google.com/rss/articles/CBMifEFVX3lxTE5BaGpaWEtzR1Z6dFVZb2VPTkpRNTJtWXlrcW9OeXp3bzdWUE4yMGhPMDNheXR4Skw3MzBHWTBZVUVpNS1OZ3JVVTJvcHNwbEEtVGQ4N1VPelBfd1FlQ0lLV1NpdlVxdFRkeWltbGxJODVhT3RBTjdFMW5wZ0k?oc=5","date":"Tue, 18 Aug 2026 13:21:42 GMT","buyer":null,"seller":"Vantage"},{"type":"Sale","price":70500000,"price_label":"$70.5M","market":"Los Angeles","title":"Pacific Urban buys Miracle Mile apartments from Sares-Regis for $70.5M","source":"TRD-LA","link":"https://therealdeal.com/la/2026/08/18/pacific-urban-buys-miracle-mile-apartments/","date":"Tue, 18 Aug 2026 20:30:00 +0000","buyer":"Pacific Urban","seller":"Sares-Regis"},{"type":"Loan","price":67400000,"price_label":"$67.4M","market":"San Jose","title":"Four Corners Properties Secures $67.4 Million Bridge Loan For Forge North First Redevelopment In San Jose","source":"Traded","link":"https://news.google.com/rss/articles/CBMingFBVV95cUxNQkphQ280U0tVcWFxZ0s3WDB3YnN6T3l4dG9IZHUzbFpVdXpfV0RyRDVNMUlOVnVFbDBFZGxLblFWamxCY0kzbll3VW1zSFFzV3VTOVlBbmRCQVZaZy1WUkdnTEFENmF0Nk5lQ3VCU1pWR0F3TnB2NXNfWWwyUmZmR1NoTUE5NllEWXFYZEE0NHp0bzZqX0pxVVlVbHg0QQ?oc=5","date":"Mon, 17 Aug 2026 07:00:00 GMT","buyer":null,"seller":null},{"type":"Sale","price":67000000,"price_label":"$67M","market":"National","title":"Broad Creek JV Picks Up Sarasota Apartments for $67M - Multi-Housing News","source":"MultiHousingNews","link":"https://news.google.com/rss/articles/CBMijgFBVV95cUxOb0hLMTFoS2VrWXJmX3BhQnV1emFHeHNLLXBfWnFOMU13RmRsMGV6S3g3SnhmZ25heTNTcm1FeVNGcEVaR3dodXZFV1ZOZmhsd3dZQWp6YWxUUE1XMjQ2TU5mVEYtTWxTY0dYSXR5SEgyQ2xHbmgzN1NrbjFnQWJyTEJCZEdKamlMMzMxNWZn?oc=5","date":"Tue, 18 Aug 2026 15:09:36 GMT","buyer":"Broad Creek JV","seller":null},{"type":"Sale","price":62000000,"price_label":"$62M","market":"Miami","title":"El-Ad assembles second Coconut Grove dev site with $62M office building buy","source":"TRD-Miami","link":"https://therealdeal.com/miami/2026/08/19/el-ad-national-pays-62-million-for-miami-development-site/","date":"Wed, 19 Aug 2026 17:15:00 +0000","buyer":null,"seller":null},{"type":"Sale","price":60000000,"price_label":"$60M","market":"National","title":"WhiteFiber Agrees to Buy Two Industrial Facilities in North Carolina, Plans Data Center Conversions","source":"REBusinessOnline","link":"https://rebusinessonline.com/whitefiber-agrees-to-buy-two-industrial-facilities-in-north-carolina-plans-data-center-conversions/","date":"Wed, 19 Aug 2026 13:42:32 +0000","buyer":"WhiteFiber Agrees","seller":null},{"type":"Sale","price":60000000,"price_label":"$60M","market":"National","title":"Sam V. Tabar Of WhiteFiber Acquires Industrial Properties In Yadkinville For $60 Million","source":"Traded","link":"https://news.google.com/rss/articles/CBMi9gFBVV95cUxNYUU0cXZRUmhlRmRZeVd0WC1ST3VSQ3llMGUzbjJQZGNCTGRvaFNnNGFKSDNOOWtFRXlneG5mZlJFS09BcEJQZTNtRkpVeVN5RVF0bUxQYXJyQmFTZ0xXLW1jZ0cweU4zaXBlRDdyaF81NWVfa1lFT0t4SWZuRGRFRi0xeDJtVXRQZWdEaFI3NlpneUt5MVJQOHVTeXh0aG40REszb3NLblNUOC1VS0NZVFBScDlDVXctbF8wakRXWDJIaUQzV2VvYVJiTXRUUlcyaDFZaEc2WG5haUZBRE1pRVA4bVRwV09PUkVvcXZxZVNGQnFrUkE?oc=5","date":"Mon, 17 Aug 2026 07:00:00 GMT","buyer":"Sam V. Tabar Of WhiteFiber","seller":null},{"type":"Sale","price":47000000,"price_label":"$47M","market":"National","title":"Danvers Industrial Portfolio Trades For $47M","source":"Bisnow","link":"https://news.google.com/rss/articles/CBMiqwFBVV95cUxNeVhBRU1zRUd5YXc5dlZRQ2tqa2t4SzRxcUJjNTdxaGhNZFh0R2tpeEZNLUJOeHhQSGVYTTczWHRKczFfYmN6bHVLcWlZQUlWYkk4aWRKdDlOVU9xUG8wR05xNGY3Z0pSZ3pNcDQwNk40N2o0d19yOG9mRmpJbkdGaXhqRERJcjM4WnExdHZwbzdTYmtfUHppUDB6TTZ5LVdnckNlRDZEcnE0aWs?oc=5","date":"Tue, 18 Aug 2026 22:40:12 GMT","buyer":null,"seller":null},{"type":"Loan","price":40000000,"price_label":"$40M","market":"Beverly Hills","title":"$40M loan on Beverly Hills hotel in special servicing after Pomerancs miss maturity","source":"TRD-LA","link":"https://therealdeal.com/la/2026/08/19/pomerancs-brothers-miss-maturity-loan-in-special-servicing/","date":"Wed, 19 Aug 2026 19:44:06 +0000","buyer":null,"seller":null},{"type":"Loan","price":40000000,"price_label":"$40M","market":"National","title":"JB Matteson Acquires Vantage At Loveland Multifamily Community For $40 Million Loan By JLL","source":"Traded","link":"https://news.google.com/rss/articles/CBMifEFVX3lxTE1ucWdrRTg0SDVRNHBTaWpGRkNxMERNMXo1Y0FTTE13M2g1VHdBVEg4Qk5TUXVoU0Q1V2tRQV80OWU1R1VSazRud2FDd0R1QjJ5VlpPclVnaE9YbUc1enZ1Q3JXSFQwMU9ZTDU4MFpWRGZmb0VLMko3U1ZuNHg?oc=5","date":"Tue, 18 Aug 2026 09:52:44 GMT","buyer":"JB Matteson","seller":null},{"type":"Loan","price":27000000,"price_label":"$27M","market":"National","title":"Urban Standard Capital Provides $27M Land Loan for 440-Unit Vail, Colo., Complex","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/urban-standard-capital-27m-land-loan-vail-colo-complex/","date":"Wed, 19 Aug 2026 16:21:56 +0000","buyer":null,"seller":null},{"type":"Loan","price":25000000,"price_label":"$25M","market":"Chicago","title":"LNR moves to foreclose on Nakash family’s $25M Hotel Lincoln loan in Chicago","source":"TRD-Chicago","link":"https://therealdeal.com/chicago/2026/08/18/nakash-family-faces-25m-foreclosure-lawsuit-on-hotel-lincoln/","date":"Tue, 18 Aug 2026 17:30:00 +0000","buyer":null,"seller":null},{"type":"Sale","price":24900000,"price_label":"$24.9M","market":"National","title":"Sonja Hoel Perkins Of Perkins Fund Acquires Office Building From Michael Fallon For $24.9M","source":"Traded","link":"https://news.google.com/rss/articles/CBMisAFBVV95cUxQZE5QWmJxTlZURFJWUzhlVEFhdVpMSWpYS0FGaFRKMlRjMXRKQzc4TzZwSHBLd1BqYnp4UDBHUWlYS0UtYnh0N0JsM3ZoMzVIcktiRF9uaU12VlVOMjVFX3dKenVVWU51dHA0SGM5Y3pyMlVjX09QOTRLRWNoY0M4Q25fU3NvYkNuV3JZUVZvTVNseUhnLW9WMFlmVE1HVzNZMnowcG4wSk1uVTN4bllTZA?oc=5","date":"Tue, 18 Aug 2026 20:01:05 GMT","buyer":"Sonja Hoel Perkins Of Perkins Fund","seller":"Michael Fallon"},{"type":"Sale","price":22500000,"price_label":"$22.5M","market":"National","title":"C702 LLC Acquires Go Go Heights Apartments In Spokane From LC Gogo Heights LLC For $22.5M","source":"Traded","link":"https://news.google.com/rss/articles/CBMigwFBVV95cUxNNTlhazJtSldBQU5kbVZuU180OTVuVXRMekRsWnlMNHh0UzZZUXBmOWlEM2FhU2FqY2ZmVU8xV0tuWFR3NHYxbERZaV9yTUVwbWhNYmJUc19ySENwTlc2MkF0NEtVbEN6bHgzdFNiblI0LTlJREtaUGMwY05Qb0VjUEdmdw?oc=5","date":"Tue, 18 Aug 2026 10:30:20 GMT","buyer":"C702 LLC","seller":"LC Gogo Heights LLC"},{"type":"Sale","price":21000000,"price_label":"$21M","market":"National","title":"Zar Property Buys NoHo’s 31-35 Great Jones Street for $21M","source":"CommercialObserver","link":"https://commercialobserver.com/2026/08/zar-properties-sale-31-35-great-jones-street-noho/","date":"Wed, 19 Aug 2026 19:00:28 +0000","buyer":"Zar Property","seller":null},{"type":"Sale","price":17000000,"price_label":"$17M","market":"South Florida","title":"Javier Cervera’s firm buys $17M shopping center in small-business haven","source":"TRD-Miami","link":"https://therealdeal.com/miami/2026/08/19/cervera-re-ventures-acquires-twin-towers-shopping-center-in-hialeah-for-17m/","date":"Wed, 19 Aug 2026 13:00:00 +0000","buyer":"Javier Cervera’s firm","seller":null},{"type":"Lease","price":13300000,"price_label":"$13.3M","market":"Pasadena","title":"Meridian Acquires Pasadena Medical Office Building for $13.3M, Arranges Long-Term Lease With Huntington Health","source":"REBusinessOnline","link":"https://rebusinessonline.com/meridian-acquires-pasadena-medical-office-building-for-13-3m-arranges-long-term-huntington-health-lease/","date":"Wed, 19 Aug 2026 14:11:23 +0000","buyer":"Meridian","seller":null},{"type":"Sale","price":8000000,"price_label":"$8M","market":"NYC","title":"NYC’s top deals: Estate of George Soros’ first wife sells Lincoln Square condos for $8M","source":"TRD-NY","link":"https://therealdeal.com/new-york/2026/08/19/new-york-top-real-estate-deals-tuesday-aug-18-2026/","date":"Wed, 19 Aug 2026 12:30:00 +0000","buyer":null,"seller":null},{"type":"Sale","price":6500000,"price_label":"$6.5M","market":"Los Angeles","title":"LAFHBUILDS Acquires Land In Los Angeles From Judith Weinbeck For $6.5 Million","source":"Traded","link":"https://news.google.com/rss/articles/CBMiiAFBVV95cUxPTzVaYjBaUjNneU1xQzJ1TWxZbXdJLU9HSVktRExubFA0Q1pXRDVVZWlReWhzLUxRUGlodDJZYmxVSDYxY05aNURZaEJtNlhXNnRwM1VjXzQxZDRPWFE5YUdmWjJ6amw5ZWhNNnNaanpjTkpnTUMtaVk2djdIYTd0TnoyMjN3VFh2?oc=5","date":"Tue, 18 Aug 2026 02:21:31 GMT","buyer":"LAFHBUILDS","seller":"Judith Weinbeck"},{"type":"Loan","price":5700000,"price_label":"$5.7M","market":"Colorado","title":"ABMAR Investments Receives $5.7M Loan for Refinancing of Union Square Shopping Center in Colorado Springs","source":"REBusinessOnline","link":"https://rebusinessonline.com/abmar-investments-receives-5-7m-loan-for-refinancing-of-union-square-shopping-center-in-colorado-springs/","date":"Wed, 19 Aug 2026 13:58:20 +0000","buyer":null,"seller":null},{"type":"Sale","price":3700000,"price_label":"$3.7M","market":"Atlanta","title":"Prudent Growth Purchases Retail Strip Center in Montgomery for $3.7M","source":"REBusinessOnline","link":"https://rebusinessonline.com/prudent-growth-purchases-strip-retail-center-in-montgomery-for-3-7m/","date":"Wed, 19 Aug 2026 13:38:51 +0000","buyer":"Prudent Growth","seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"Creative Media & Community Trust Corp — acquisition","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/908311/000090831126000096/cmct-20260814.htm","date":"2026-08-14","buyer":null,"seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"DIVERSIFIED HEALTHCARE TRUST — acquisition","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/1075415/000107541526000029/dhc-20260803.htm","date":"2026-08-03","buyer":null,"seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"Wheeler Real Estate Investment Trust, Inc. — retail","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/1527541/000152754126000254/ex991earningsannouncementq.htm","date":"2026-08-06","buyer":null,"seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"OFFICE PROPERTIES INCOME TRUST — office","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/1456772/000145677226000034/opi-20260805.htm","date":"2026-08-05","buyer":null,"seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"Service Properties Trust — office","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/945394/000094539426000048/R1.htm","date":"2026-08-05","buyer":null,"seller":null},{"type":"Filing","price":null,"price_label":null,"market":"California","title":"KILROY REALTY CORP — life science","source":"SEC EDGAR","link":"https://www.sec.gov/Archives/edgar/data/1025996/000119312526344730/d64354dex991.htm","date":"2026-08-11","buyer":null,"seller":null}]
\ No newline at end of file
diff --git a/public/flyers/index.html b/public/flyers/index.html
new file mode 100644
index 0000000..8924e6c
--- /dev/null
+++ b/public/flyers/index.html
@@ -0,0 +1,68 @@
+<!doctype html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Flyers — Abrams | CRE deal flyers</title>
+<style>
+ :root{--cols:3;--navy:#0E2350;--blue:#16357A;--gold:#E8A81C;--ink:#141414;--gray:#6B7280}
+ *{box-sizing:border-box} body{margin:0;font-family:Inter,-apple-system,Helvetica,Arial,sans-serif;background:#f4f6fb;color:var(--ink)}
+ header{background:var(--navy);color:#fff;padding:22px 34px} header h1{margin:0;font-size:24px;letter-spacing:.5px}
+ header .s{color:var(--gold);font-size:13px;margin-top:4px}
+ .controls{position:sticky;top:0;z-index:5;background:#fff;border-bottom:1px solid #e6e9f2;padding:12px 34px;display:flex;gap:16px;align-items:center;flex-wrap:wrap;font-size:13px}
+ .controls label{color:var(--gray);margin-right:5px} select,input[type=range]{vertical-align:middle}
+ .stat{color:var(--gray);margin-left:auto}
+ .wrap{padding:22px 34px;display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:16px}
+ .flyer{background:#fff;border-radius:10px;box-shadow:0 2px 12px rgba(0,0,0,.07);padding:18px 20px;display:flex;flex-direction:column;min-height:190px}
+ .flyer .top{display:flex;justify-content:space-between;align-items:flex-start}
+ .chip{color:#fff;font-size:10px;font-weight:700;padding:3px 9px;border-radius:5px;letter-spacing:.5px}
+ .price{font-size:30px;font-weight:800;color:var(--blue);margin:8px 0 2px;letter-spacing:-.5px}
+ .ttl{font-family:'Playfair Display',Georgia,serif;font-size:16px;line-height:1.25;color:var(--navy);margin:2px 0 8px}
+ .meta{font-size:12px;color:var(--gray);line-height:1.7;margin-top:auto}
+ .meta b{color:var(--ink);font-weight:600}
+ .src{margin-top:10px;font-size:12px} .src a{color:#8A5A00;text-decoration:none;font-weight:600}
+ .mk{display:inline-block;background:#eef0f6;color:#445;border-radius:4px;padding:1px 7px;font-size:11px}
+ @media(max-width:700px){.wrap{grid-template-columns:1fr}}
+</style></head><body>
+<header><h1>Flyers · Abrams</h1><div class="s">Commercial real-estate deal flyers — one place · updated from 19 CRE news sources</div></header>
+<div class="controls">
+ <div><label>Type</label><select id="ftype"><option value="">All</option><option>Sale</option><option>Loan</option><option>Lease</option><option>Development</option></select></div>
+ <div><label>Market</label><select id="fmk"><option value="">All</option></select></div>
+ <div><label>Sort</label><select id="sort"><option value="price">Price ↓</option><option value="date">Newest</option><option value="type">Type</option></select></div>
+ <div><label>Density</label><input type="range" id="dens" min="1" max="5" step="1" value="3"></div>
+ <div class="stat" id="stat"></div>
+</div>
+<div class="wrap" id="grid"></div>
+<script>
+const TC={"Sale":"#0E7C4A","Loan":"#8A5A00","Lease":"#16357A","Development":"#6d28d9","Filing":"#6B7280"};
+const money=n=>n?'$'+(+n).toLocaleString('en-US'):'';
+const tc=s=>(s||'').toLowerCase().replace(/\b\w/g,c=>c.toUpperCase());
+let DEALS=[];
+function card(d){const c=TC[d.type]||'#6B7280';
+ return `<div class="flyer">
+ <div class="top"><span class="chip" style="background:${c}">${(d.type||'CRE').toUpperCase()}</span><span class="mk">${d.market||'US'}</span></div>
+ <div class="price">${d.price_label||money(d.price)||'—'}</div>
+ <div class="ttl">${(d.title||'').replace(/</g,'<')}</div>
+ <div class="meta">
+ ${d.buyer?'<div><b>Buyer:</b> '+d.buyer+'</div>':''}
+ ${d.seller?'<div><b>Seller:</b> '+d.seller+'</div>':''}
+ ${d.date?'<div><b>Reported:</b> '+new Date(d.date).toLocaleDateString()+'</div>':''}
+ </div>
+ <div class="src"><a href="${d.link}" target="_blank" rel="noopener noreferrer">${d.source} ↗</a></div>
+ </div>`;}
+function markets(){return [...new Set(DEALS.map(d=>d.market).filter(Boolean))].sort();}
+function render(){let a=[...DEALS];
+ const ft=ftype.value,fk=fmk.value;
+ if(ft)a=a.filter(d=>d.type===ft); if(fk)a=a.filter(d=>d.market===fk);
+ const s=sort.value;
+ a.sort(s==='date'?(x,y)=>(y.date||'').localeCompare(x.date||''):s==='type'?(x,y)=>(x.type||'').localeCompare(y.type||''):(x,y)=>(y.price||0)-(x.price||0));
+ grid.innerHTML=a.map(card).join(''); stat.textContent=a.length+' flyers';
+ localStorage.flyType=ft;localStorage.flyMk=fk;localStorage.flySort=s;}
+function dens(){document.documentElement.style.setProperty('--cols',document.getElementById('dens').value);localStorage.flyDens=document.getElementById('dens').value;}
+['ftype','fmk','sort'].forEach(id=>document.getElementById(id).onchange=render);
+document.getElementById('dens').oninput=dens;
+fetch('flyers.json').then(r=>r.json()).then(j=>{DEALS=j;
+ fmk.innerHTML='<option value="">All</option>'+markets().map(m=>'<option>'+m+'</option>').join('');
+ if(localStorage.flyType)ftype.value=localStorage.flyType;
+ if(localStorage.flyMk)fmk.value=localStorage.flyMk;
+ if(localStorage.flySort)sort.value=localStorage.flySort;
+ if(localStorage.flyDens)document.getElementById('dens').value=localStorage.flyDens;
+ dens();render();});
+</script></body></html>
\ No newline at end of file
diff --git a/scripts/build-flyers-site.mjs b/scripts/build-flyers-site.mjs
new file mode 100644
index 0000000..3b4ca20
--- /dev/null
+++ b/scripts/build-flyers-site.mjs
@@ -0,0 +1,121 @@
+#!/usr/bin/env node
+// TK-10708 Build flyers.agentabrams.com — one place to view every aggregated CRE deal as
+// a branded flyer with its info extracted. STATIC site (no server/DB exposed). We generate
+// our OWN flyer per deal from the deal data we hold (no third-party PDF hosting = no
+// copyright exposure). Each flyer prints to PDF. Public deploy is Steve-gated.
+//
+// Usage: node scripts/build-flyers-site.mjs -> public/flyers/index.html + data embedded
+
+import { readdirSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+
+const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
+const OUT = join(ROOT, 'out');
+const SITE = join(ROOT, 'public', 'flyers');
+mkdirSync(SITE, { recursive: true });
+
+// --- gather every aggregated deal across all runs (one place for all) ---
+const recs = [];
+for (const f of readdirSync(OUT)) {
+ if (/^crenews-new-deals-.*\.json$/.test(f)) {
+ for (const d of JSON.parse(readFileSync(join(OUT, f), 'utf8')))
+ recs.push({ type: d.type || 'CRE', price: d.price, price_label: d.label, market: d.location || d.feed_region, title: d.title, source: d.feed, link: d.link, date: d.date });
+ } else if (/^edgar-new-deals-.*\.json$/.test(f)) {
+ for (const d of JSON.parse(readFileSync(join(OUT, f), 'utf8')))
+ recs.push({ type: d.kind === 'closed_deal' ? 'Sale' : 'Filing', price: d.price, price_label: d.price_label, market: d.location || d.region, title: `${(d.filer||'').split('(')[0].trim()} — ${d.property_type||'acquisition'}`, source: 'SEC EDGAR', link: d.filing_url, date: d.file_date });
+ }
+}
+// dedup by (price + normalized title)
+const seen = new Set(), deals = [];
+for (const r of recs) {
+ const k = `${r.price}|${(r.title||'').toLowerCase().replace(/[^a-z0-9]+/g,' ').trim().slice(0,40)}`;
+ if (seen.has(k) || !r.title) continue; seen.add(k); deals.push(r);
+}
+// extract parties (buyer / seller) from the headline verb pattern — "the info" per flyer.
+const NAME = "[A-Z][\\w.&'’ -]{2,45}?";
+for (const d of deals) {
+ const t = d.title;
+ // buyer: "X buys/acquires/to pay ..." OR a sale headline ending "... to X"
+ let b = t.match(new RegExp(`^(${NAME})\\s+(?:to\\s+)?(?:buys?|acquires?|purchases?|to pay|pays?|snaps up|picks up|nabs?|grabs?)\\b`, 'i'));
+ if (!b) b = t.match(new RegExp(`\\b(?:sells?|sold|offloads?|unloads?)\\b.*?\\bto\\s+(${NAME})(?:\\s+for\\b|,|\\.|$)`, 'i'));
+ d.buyer = b ? b[1].trim() : null;
+ // seller: "X sells/to sell/offloads ..." OR "... from X"
+ let s = t.match(new RegExp(`^(${NAME})\\s+(?:to\\s+)?(?:sells?|sold|offloads?|unloads?|dispose)`, 'i'));
+ if (!s) s = t.match(new RegExp(`\\bfrom\\s+(${NAME})(?:\\s+for\\b|,|\\.|$)`, 'i'));
+ d.seller = s ? s[1].trim() : null;
+}
+deals.sort((a, b) => (b.price || 0) - (a.price || 0));
+writeFileSync(join(SITE, 'flyers.json'), JSON.stringify(deals, null, 0));
+
+const TC = { Sale: '#0E7C4A', Loan: '#8A5A00', Lease: '#16357A', Development: '#6d28d9', Filing: '#6B7280' };
+const html = `<!doctype html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Flyers — Abrams | CRE deal flyers</title>
+<style>
+ :root{--cols:3;--navy:#0E2350;--blue:#16357A;--gold:#E8A81C;--ink:#141414;--gray:#6B7280}
+ *{box-sizing:border-box} body{margin:0;font-family:Inter,-apple-system,Helvetica,Arial,sans-serif;background:#f4f6fb;color:var(--ink)}
+ header{background:var(--navy);color:#fff;padding:22px 34px} header h1{margin:0;font-size:24px;letter-spacing:.5px}
+ header .s{color:var(--gold);font-size:13px;margin-top:4px}
+ .controls{position:sticky;top:0;z-index:5;background:#fff;border-bottom:1px solid #e6e9f2;padding:12px 34px;display:flex;gap:16px;align-items:center;flex-wrap:wrap;font-size:13px}
+ .controls label{color:var(--gray);margin-right:5px} select,input[type=range]{vertical-align:middle}
+ .stat{color:var(--gray);margin-left:auto}
+ .wrap{padding:22px 34px;display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:16px}
+ .flyer{background:#fff;border-radius:10px;box-shadow:0 2px 12px rgba(0,0,0,.07);padding:18px 20px;display:flex;flex-direction:column;min-height:190px}
+ .flyer .top{display:flex;justify-content:space-between;align-items:flex-start}
+ .chip{color:#fff;font-size:10px;font-weight:700;padding:3px 9px;border-radius:5px;letter-spacing:.5px}
+ .price{font-size:30px;font-weight:800;color:var(--blue);margin:8px 0 2px;letter-spacing:-.5px}
+ .ttl{font-family:'Playfair Display',Georgia,serif;font-size:16px;line-height:1.25;color:var(--navy);margin:2px 0 8px}
+ .meta{font-size:12px;color:var(--gray);line-height:1.7;margin-top:auto}
+ .meta b{color:var(--ink);font-weight:600}
+ .src{margin-top:10px;font-size:12px} .src a{color:#8A5A00;text-decoration:none;font-weight:600}
+ .mk{display:inline-block;background:#eef0f6;color:#445;border-radius:4px;padding:1px 7px;font-size:11px}
+ @media(max-width:700px){.wrap{grid-template-columns:1fr}}
+</style></head><body>
+<header><h1>Flyers · Abrams</h1><div class="s">Commercial real-estate deal flyers — one place · updated from 19 CRE news sources</div></header>
+<div class="controls">
+ <div><label>Type</label><select id="ftype"><option value="">All</option><option>Sale</option><option>Loan</option><option>Lease</option><option>Development</option></select></div>
+ <div><label>Market</label><select id="fmk"><option value="">All</option></select></div>
+ <div><label>Sort</label><select id="sort"><option value="price">Price ↓</option><option value="date">Newest</option><option value="type">Type</option></select></div>
+ <div><label>Density</label><input type="range" id="dens" min="1" max="5" step="1" value="3"></div>
+ <div class="stat" id="stat"></div>
+</div>
+<div class="wrap" id="grid"></div>
+<script>
+const TC=${JSON.stringify(TC)};
+const money=n=>n?'$'+(+n).toLocaleString('en-US'):'';
+const tc=s=>(s||'').toLowerCase().replace(/\\b\\w/g,c=>c.toUpperCase());
+let DEALS=[];
+function card(d){const c=TC[d.type]||'#6B7280';
+ return \`<div class="flyer">
+ <div class="top"><span class="chip" style="background:\${c}">\${(d.type||'CRE').toUpperCase()}</span><span class="mk">\${d.market||'US'}</span></div>
+ <div class="price">\${d.price_label||money(d.price)||'—'}</div>
+ <div class="ttl">\${(d.title||'').replace(/</g,'<')}</div>
+ <div class="meta">
+ \${d.buyer?'<div><b>Buyer:</b> '+d.buyer+'</div>':''}
+ \${d.seller?'<div><b>Seller:</b> '+d.seller+'</div>':''}
+ \${d.date?'<div><b>Reported:</b> '+new Date(d.date).toLocaleDateString()+'</div>':''}
+ </div>
+ <div class="src"><a href="\${d.link}" target="_blank" rel="noopener noreferrer">\${d.source} ↗</a></div>
+ </div>\`;}
+function markets(){return [...new Set(DEALS.map(d=>d.market).filter(Boolean))].sort();}
+function render(){let a=[...DEALS];
+ const ft=ftype.value,fk=fmk.value;
+ if(ft)a=a.filter(d=>d.type===ft); if(fk)a=a.filter(d=>d.market===fk);
+ const s=sort.value;
+ a.sort(s==='date'?(x,y)=>(y.date||'').localeCompare(x.date||''):s==='type'?(x,y)=>(x.type||'').localeCompare(y.type||''):(x,y)=>(y.price||0)-(x.price||0));
+ grid.innerHTML=a.map(card).join(''); stat.textContent=a.length+' flyers';
+ localStorage.flyType=ft;localStorage.flyMk=fk;localStorage.flySort=s;}
+function dens(){document.documentElement.style.setProperty('--cols',document.getElementById('dens').value);localStorage.flyDens=document.getElementById('dens').value;}
+['ftype','fmk','sort'].forEach(id=>document.getElementById(id).onchange=render);
+document.getElementById('dens').oninput=dens;
+fetch('flyers.json').then(r=>r.json()).then(j=>{DEALS=j;
+ fmk.innerHTML='<option value="">All</option>'+markets().map(m=>'<option>'+m+'</option>').join('');
+ if(localStorage.flyType)ftype.value=localStorage.flyType;
+ if(localStorage.flyMk)fmk.value=localStorage.flyMk;
+ if(localStorage.flySort)sort.value=localStorage.flySort;
+ if(localStorage.flyDens)document.getElementById('dens').value=localStorage.flyDens;
+ dens();render();});
+</script></body></html>`;
+writeFileSync(join(SITE, 'index.html'), html);
+console.log(`Wrote public/flyers/index.html + flyers.json — ${deals.length} flyers (${new Set(deals.map(d=>d.market)).size} markets, types: ${[...new Set(deals.map(d=>d.type))].join('/')})`);
diff --git a/scripts/dtt-cron.sh b/scripts/dtt-cron.sh
index 8569128..c18af04 100755
--- a/scripts/dtt-cron.sh
+++ b/scripts/dtt-cron.sh
@@ -10,6 +10,8 @@ node scripts/cre-news-monitor.mjs >> "$LOG" 2>&1
node scripts/edgar-cre-monitor.mjs --days 14 >> "$LOG" 2>&1
# 3) DTT sales import (free assessor source; frozen until a fresh feed is added)
node scripts/ingest-la-sales.mjs >> "$LOG" 2>&1
-# 4) Email the morning's NEW closed deals to Steve via George (only if there are any)
+# 4) Rebuild flyers.agentabrams.com static site from the aggregated deals
+node scripts/build-flyers-site.mjs >> "$LOG" 2>&1
+# 5) Email the morning's NEW closed deals to Steve via George (only if there are any)
bash scripts/email-digest.sh >> "$LOG" 2>&1
echo "--- exit $? ---" >> "$LOG"
← e0ea756 more free direct RSS (lean off proxy): REJournals + Multifam
·
back to Re Flyer Aggregator
·
California RE feeds + alt pull method: facebookexternalhit U 83ef493 →