Public: anyone can read this; the crew can change it.
Print a 'Just listed' / 'Just sold' neighbor postcard for a listing, four to a page, in the agent's brand #104
Check · Review · Land · Live done — Landed and live in production.
`/listings/:id/postcard` now prints four identical postcards on a US Letter sheet, with dashed cut lines between them. I ran the postcard, hostile, a11y, speed, design, walkthrough and scan tests, and they pass. The new code and CSS passed `bun scripts/lint-design.ts`. I did not run the whole suite. I did not run the type check: the repo has no `tsconfig.json`, so `bun x tsc --noEmit` only prints…
shipped production is serving it deploy 957b843
/listings/:id/postcard now prints four identical postcards on a US Letter sheet, with dashed cut lines between them. I ran the postcard, hostile, a11y, speed, design, walkthrough and scan tests, and they pass. The new code and CSS passed bun scripts/lint-design.ts. I did not run the whole suite. I did not run the type check: the repo has no tsconfig.json, so bun x tsc --noEmit only prints help. I haven't printed the sheet or looked at it in a browser.
What a card holds
- Layout: each card is 4.25 × 5.5 in, in fixed inches with the existing
@pagemargin of 0. That is the print-drift risk the issue named. - Content: it carries the hero photo with its alt text, the address, price, beds/baths/sqft and the agent's brokerage, license, phone, headshot and palette.
- Band: it says "Just sold" for a Sold listing. For an active listing with an open house it says "Open house: Saturday, March 6, 11 am–1:30 pm"; otherwise "Just listed". Other statuses (under contract, withdrawn, expired) get their plain status label.
- Words and link: the first one or two sentences of the approved MLS description print on the card, with the open-house line taken out. The property page URL and QR code ride along, since the QR code from #98 had already landed.
Draft handling
- Draft mark: until the MLS description is approved, every card wears "Draft — not approved". It prints none of the description's words, and the QR block says the page isn't public yet.
- Which approval: the mark follows the MLS description's approval, not the flyer's. The postcard's words come from the MLS description, so that is the approval that matters.
Wiring
- Link: the listing page has a "Postcards" button beside "Print flyer".
- Access: the route reads the listing through the same
getListingcall the flyer uses, so no permission cell changed.
Tests and docs
- Tests:
src/postcard.test.tscovers the four cards, the draft mark, the approved words, the Open house and Just sold bands, and a 404 for an unknown listing. The postcard is added to the hostile-listing and a11y path lists. - Docs: the new
postcard-*CSS classes are named indocs/design/areas/postcard.md, and the README's "For the agent" section says how to print it. - Not done: I did not add the postcard to the terminal or the JSON API.
Look at the print preview in a browser, and check that the sold and open-house bands fit.
🤖 Generated with Claude Code
Clean. The route reads through getListing like the flyer, so no contract cell changed. Every field is escaped and the hostile and a11y lists include the postcard. The Draft mark follows the MLS approval and no words print before it. Postcard, hostile and a11y tests pass, lint-design is clean, and the preview shows four cards.
/listings/:id/postcardnow prints four identical postcards on a US Letter sheet, with dashed cut lines between them. I ran the postcard, hostile, a11y, speed, design, walkthrough and scan tests, and they pass. The new code and CSS passedbun scripts/lint-design.ts. I did not run the whole suite. I did not run the type check: the repo has notsconfig.json, sobun x tsc --noEmitonly prints help. I haven't printed the sheet or looked at it in a browser.What a card holds
@pagemargin of 0. That is the print-drift risk the issue named.Draft handling
Wiring
getListingcall the flyer uses, so no permission cell changed.Tests and docs
src/postcard.test.tscovers the four cards, the draft mark, the approved words, the Open house and Just sold bands, and a 404 for an unknown listing. The postcard is added to the hostile-listing and a11y path lists.postcard-*CSS classes are named indocs/design/areas/postcard.md, and the README's "For the agent" section says how to print it.Look at the print preview in a browser, and check that the sold and open-house bands fit.
🤖 Generated with Claude Code
Closes #88