Corrected after finding the code. This issue originally read as a greenfield build. It is not: The Open Times is this repo (Postline was renamed), and most of what the checklist asked for already ships. Rewritten to cover the gaps instead, so nobody rebuilds working features.
What already exists
Models: Publication, PublicationTier, PublicationSubscriber, PublicationSend, PublicationRecommendation, BlogPost, PostComment, DiscoverEntry.
BlogPost already carries title, slug, body, excerpt, status, access and previewChars — so paywalled posts with a free preview are modelled.
Actions under app/Actions/OpenTimes/:
| Area | Actions |
|---|---|
| Publication | PublicationGetAction, PublicationSaveAction |
| Subscribers | SubscribeAction, SubscriberConfirmAction, SubscriberUnsubscribeAction, SubscribersListAction, ImportSubscribersAction |
| Paid | CheckoutAction, StripeWebhookAction, TierSaveAction, TiersListAction, TierArchiveAction |
| Email sends | SendQueueAction, SendsListAction |
| Comments | CommentPostAction, CommentsThreadAction, CommentModerateAction, CommentQueueAction |
| Discovery | DiscoverFeedAction, DiscoverReadAction, DiscoverEntryStatusAction |
| Import | ImportPostsAction |
| Public reading | PublicPostAction |
Views: publication.stx, read.stx, discover.stx, inbox.stx, blog.stx. The marketing site already sells /features/publications, /features/newsletter, /features/paid-subscriptions, /features/discover, /features/comments, /features/import.
Double-opt-in is wired (/subscribe, /subscribe/confirm, /subscribe/unsubscribe, rate limited in routes/api.ts:112-114).
So the newsletter-competing half of the original checklist is built.
What is actually missing
- Short-form as a first-class post type.
BlogPosthas nokind/formatdiscriminator — every entry is a long-form post with a title and slug. Chris asked for short form too, and a news front page needs short items (a link with commentary, a quote, a correction) that are posts in their own right, not stubs with empty titles. This is the one real schema gap. - An edited front page.
DiscoverEntrydrives discovery, but there is no lead item / secondary ordering / pinning for the publication's own front page. - Open and click stats on sends.
PublicationSendrecords the send; confirm whether opens/clicks are tracked, or decide explicitly not to. - Sections or desks, so short items group into something followable.
- Corrections recorded rather than silently edited, with the updated timestamp shown.
What to verify rather than build
- Run one post end to end: write → paywall preview → publish → email send → a subscriber reads it at a public URL → comment → appears in Discover
ImportPostsAction/ImportSubscribersActionagainst a real Substack exportCheckoutAction+StripeWebhookActionagainst Stripe test mode: subscribe, upgrade tier, cancel, and confirmaccessgating actually gates
Timing
Chris asked for the app finished and usable this week, publishing from next week. Given how much is already built, the honest version of this issue is a verification pass plus the short-form gap — not a build.