Publishing from the browser — posts move to the database
The second Hall shipment closes a small, meaningful loop. Until yesterday, publishing a post to the ship feed meant editing a TypeScript file, running the migration or adding to a typed array, and pushing a commit. Every entry was code. That works for the first post; it doesn't scale past ten.
What shipped
Posts now live in a hall_posts table in Postgres. A new operator area at /inside/admin/posts has a list view, a new-post editor, and an edit view. The editor accepts markdown, a hero image or video (uploaded directly from the browser), and the receipts block — AI session stats, commit URL, demo URL, tagged product.
Visibility toggles are there too: public (title + hero visible without login), members (full body requires sign-in), patrons (reserved for future Patron-only posts). The visibility rule is enforced server-side on every render.
Operator authorization is the simplest working thing: ADMIN_EMAILS env var, comma-separated list of operator emails. Edit the list, redeploy, done. When we onboard a second operator for a specific product, it graduates to a per-member role table — not now.
The receipts
This post you're reading is the first one written through the browser instead of committed to code. Same format as the seed post, same card component, loaded from the database. That's the demonstration.
What’s next
Next Hall shipment was proposals + voting, covered in the post above. After that: comments and reactions under posts, treasury dashboard when Stripe is live, and email digest to members.