motir-core becomes an application plus a public read API — the project-subject route, and the contract a second repository depends on
Opened by Zhu Yue ·
motir-core becomes an application plus a public read API, and nothing else public. Every page it currently serves under app/(public)/ moves to motir.co; what stays here is the contract those pages are rebuilt against, and the authenticated application.
⚠️ RE-SCOPED 2026-08-29 (third cut) — read this before touching any child
This story has now pointed three ways in one day. It was "the landing comes home" (port marketing INTO motir-core — rejected: GPL-3.0), then "motir.co answers for the public reading surface" (compose the apex from two origins — superseded). It is now the motir-core side of a clean split: motir-marketing serves motir.co and every public page; motir-core serves app.motir.co and the API.
⚠️ ITS CHILD SET IS STALE AND THIS RE-PLAN DOES NOT TOUCH IT. That is deliberate — archiving a child is only safe in the pass that also authors what replaces it and sweeps the edges pointing at it, which an epic-level pass cannot do. motir plan MOTIR-3876 is owed before any child is run, and it must dispose of at least:
- MOTIR-3924 — VOID. A host branch in
motir-corefor a hostname it no longer answers. - MOTIR-3925 — VOID. The shared chrome built in
motir-core, for pages that leave. The chrome is built inmotir-marketinginstead. - MOTIR-3880 — the chrome DESIGN survives and is still needed; it belongs with the story that renders it.
- MOTIR-3884 — the 301s survive but cannot fire until the replacements are live, so they belong after the rendering story, not here.
- MOTIR-3879 — the ADR, whose own re-scope is plan
cmterykg000hjhvn8yhp81komand needs a third pass for this arrangement. - MOTIR-3881, MOTIR-3885, MOTIR-3886 — re-scope to this story's actual scope.
- MOTIR-3726 —
Implemented, unaffected.app.motir.costill needs its ownrobots.txt.
What this story delivers, once re-planned
- The project-subject route.
app/api/public/p/[identifier]/route.tsdoes not exist — the page's own subject (name, overview, tags, workspace, hero) has no public endpoint, while every one of its LISTS does. This is the single hard gap the re-measurement found, and it is one route. /api/public/*promoted to a real contract. A second repository is about to depend on it, so it needs a version, a deprecation policy, published documentation and contract tests.docs/decisions/public-api-conventions.mdgoverns/api/v1and the published OpenAPI document is v1 REST only; this surface is outside both. That is the decision this story takes deliberately rather than backing into.- The ADR — MOTIR-3879, recording the arrangement and what a self-hosted build serves.
- The origin seam —
publicSiteOrigin()stops delegating toMOTIR_BASE_URL, because the public origin is now a host this application does not serve at all. - Both story-level test gates, over the contract rather than over pages.
Boundary
- It does not render anything public. The chrome,
/exploreand/docsare the rendering story's;/legalis MOTIR-3909's;/p/*is MOTIR-3877's. - It does not DELETE the existing public pages, and it does not issue the 301s. Both are only safe once
motir.coserves the replacements, so they sit after the rendering stories — the abandoned path is a deliverable, but it is not this story's. - It does not gate anything. Whether the API exists at all on a self-hosted build is MOTIR-3908's.
Verification recipe
curl https://app.motir.co/api/public/p/<identifier>returns the project's own subject — the endpoint that did not exist.- The published contract document lists every
/api/public/*route with its version and stability, and a contract test fails when a response shape drifts from it. app.motir.co/robots.txtand the authenticated application are unchanged.
Acceptance criteria
- Every child is
done; the repository set ismotir-corealone. app/api/public/p/[identifier]/route.tsexists, is anonymous, and returns the page's subject./api/public/*carries a version, a stability statement and a deprecation policy, is documented where a second repository's authors will find it, and has contract tests that fail on a shape change.- Exactly one module reads each origin variable, asserted in the shape
tests/hosting/appUrlSeam.test.tsalready uses. - Nothing a visitor sees changes when this story deploys. It adds an endpoint and a contract; it removes no page and redirects nothing.
- ≥90% coverage on every file the story's PRs touch.
Context refs
motir-core/app/api/public/— the ten routes, and the one that is missingmotir-core/docs/decisions/public-api-conventions.md— the convention this surface must joinmotir-core/lib/baseUrl.ts·lib/publicProjects/urls.ts·tests/hosting/appUrlSeam.test.ts- MOTIR-3877 — carries the corrected rung-2 measurement of the public API
- MOTIR-3879 — the ADR
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.