10 · A path from the current code
10 · A path from the current code
The design ignores the current layout on purpose. This page is the shortest honest route from here to there, in steps that each leave the app shippable. It is a sketch, not a plan; each step would get its own issue and ADR.
- Extract
domainandcontractsas packages. Movemodel/and the pure parts ofutils/intopackages/domain; move the zod schemas from server actions and routes intopackages/contracts. Finish #965 in the process. The Next app keeps working; the boundary becomes physical. - Introduce the change log and the jobs loop inside the Next app. Add the
changestable andtx.record()to the repositories; move reminders and email dispatch onto the loop (this is #1005 done the target way). No UI change. - Stand up the API in the same process. Mount a Hono app under
/api/v1in a custom server (or as route handlers) that calls the same repositories; declare contracts, generateopenapi.jsonandapi-client. Server actions start delegating to use cases so both paths share one implementation. - Ship the feed and the snapshot. SSE endpoint over the change log; a
replicapackage in the Next app that the schedule page reads from. Live updates arrive for everyone while the rest of the UI is unchanged. - Move screens to the SPA one family at a time. Start with the schedule (biggest win: replica, filters, agenda, kiosk), then proposals and voting, people and meetings, settings, admin. Each moved screen deletes its server actions. A route in Next redirects to the SPA route until all are moved.
- Identity and roles. Persons, participations, login sessions, assurance, join links; migrate protected guests to verified credentials; replace the admin password with a site-admin role and the bootstrap link.
- Retire Next. The server serves the SPA’s static files;
nextleavespackage.json; the Dockerfile shrinks.
Steps 1 and 2 are valuable even if nothing else happens. Steps 3 to 5 are where the attendee-visible wins land, and they can be paced by event calendar: the feed and the schedule screen before the next event, the rest after.