Skip to content

decision: dashboard/widgets, blog, and subscription surface - G28, G29, G39 #61

Description

@Adron

Summary

Three product areas where the right first step is an owner decision, not code. Each is real surface on the web; none is obviously right for a native macOS client. Filing them together so the decisions are made once.


1. Dashboard / Front wall + widgets

/help/getting-started puts the Dashboard second in prominence, right after Home:

Dashboard (click the chart icon) shows only your own messages in a table view. It also includes Data Management (links to Exports and Settings) and your profile summary.

Its tiles: Scheduled posts, Exports, Settings, Profile Information, and a Lists tree (of lists and list folders). There is also a configurable front wall, plus widgets — Location, Weather, markets, news, transit, transit stops, bike-share — and a full-screen Clock page.

⚠️ New finding, 2026-09-07: this is backend-blocked for a Bearer client, not merely a design question. Every route is x-auth-type: session:

GET/PUT /api/user/dashboard-layout    session
GET/PUT /api/user/front-wall-layout   session
GET /api/widgets/{markets,news,transit,transit/stops,bike-share}   session

(GET /api/weather and GET /api/location are public.)

So even if the answer is "build it", the saved-layout half cannot be built until the routes accept Bearer.

The design question stands regardless: a native app arguably wants its own arrangement rather than mirroring the web's saved layout. Note that most of the Dashboard's content already exists natively — Scheduled posts, Exports, Settings, and a lists tree all ship; what is missing is the aggregation and the own-messages table view. A native "Dashboard" could be assembled from existing pieces with no new API surface at all, which is a materially cheaper option than the layout-syncing one.

Options:

  1. Do nothing. The constituent features are already reachable from the sidebar.
  2. Native dashboard, no layout sync (cheapest useful option) — a summary scene assembled from what already ships, plus an own-messages table. No new routes, not blocked.
  3. Full parity including saved layouts and widgets. Blocked on the session-only routes above.

2. Blog

/help/blog documents a Blog feature, and the web footer links /blog. The public API surface is only subscribe / confirm / unsubscribe (POST /api/blog/subscribe, GET /api/blog/subscribe/confirm, GET/POST /api/blog/unsubscribe — all public, all Bearer-safe). Authoring lives entirely behind /api/admin/blog*, which is admin-only and out of scope for a general client.

Options:

  1. Do nothing. The blog is a website; a link out is enough.
  2. Reader only — render posts natively. ⚠️ Note there is no public read route in the spec (only subscribe/unsubscribe), so a native reader would need either a new public endpoint or HTML scraping. Scraping is not acceptable; confirm a read route exists before choosing this.
  3. Reader + subscribe management, using the three public routes.

Native authoring is admin-gated and almost certainly out of scope.


3. Subscription status surface

The web has /subscription (current tier, Manage, Cancel — all via Stripe). This repo's standing decision is the opposite for native: "billing is managed in the web app by owner decision", and there is no in-app-purchase surface.

Meanwhile LiveEntitlements already reads customerStatus (live probe 2026-09-07 returns "customerStatus":"subscriber"), and SettingsRootView's header comment still lists "Subscription" as planned — so the code is ambiguous about which way this went.

Options:

  1. Do nothing and delete the stale comment.
  2. Recommended — read-only status in Settings ▸ Account showing the current tier, plus a "Manage subscription in your browser" button. No Stripe contact from the app, no payment UI ever native. This is what the entitlement-gating work wants anyway: when a Free user hits an Upgrade prompt, it needs somewhere to send them.
  3. Full native billing. Reverses the standing decision and raises sandboxing and App Review questions. Not recommended.

What "done" looks like for this issue

  • A decision recorded for each of the three, in docs/decisions/.
  • For anything chosen, a follow-up implementation issue filed and linked here.
  • For anything declined, the stale code comments and doc references cleaned up so a future sweep does not re-file it.

Notes

work-consolidation.md tracks these as G28, G29, and G39. The dashboard's session-only constraint is new information from the 2026-09-07 sweep and materially changes option 3's cost.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-decisionOwner decision required before any codeparityWeb-parity gap with the InterlinedList web app

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions