Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-3932Done

motir.co renders the public reading surface — the shared chrome, /explore, /docs and /legal in motir-marketing over the public API

motir.co is one origin, served by motir-marketing, and this story is where its reading surface actually gets built. /explore, /docs and /legal move out of motir-core and are rendered here — the first two against motir-core's public read API, the third from files in this repository.

⚠️ AMENDED 2026-08-30 — this story took over motir.co/legal

MOTIR-4005 (the /legal design) and MOTIR-4009 (the /legal render) were authored under MOTIR-3909 and re-filed here. Both ship in motir-marketing, which is this story's entire repository set, and both compose MOTIR-3880's chrome — which is this story's child.

Their old home wired three cross-parent leaf edges under plan-rules/fixtures/phase-skeleton.md's no-legal-lift limb, on the grounds that MOTIR-4009 sat upstream of MOTIR-3884 while MOTIR-4013 sat downstream of it, making a story-level edge a cycle in either direction. The exemption did not applyphase-skeleton.md offers RE-FILE as remedy (b) and it was never tested. With those two cards here the interleave is gone, every cross-story edge runs one way, and MOTIR-3909 blocked_by this story carries the whole ordering.

MOTIR-3909 keeps the motir-core side — the configured manifest, the three link surfaces, the deletion, the re-consent gate — and the marketing-side Vitest gate MOTIR-4011, which stays there because its other blocker is a motir-core card.

Why this is buildable — the re-measurement that settles it

MOTIR-3877 recorded that a second renderer cannot use app/api/public/*. Re-measured on origin/main 2026-08-29, that objection is materially weaker than written, and the full correction is on that card:

  • /api/public/explore and /api/public/categories make ZERO getSession() calls. explore/route.ts's own comment: "NOT session-gated: a logged-out visitor / crawler reads it … deliberately no getSession() call." They are exactly the contract this story consumes.
  • Of the ten routes, one is session-gated — follow, a POST/DELETE account relationship — and it is not one this story needs.
  • The earlier "six routes call getSession()" and a later "eight" were both artefacts of counting comment MENTIONS rather than calls.

So /explore is a fetch away. /docs is different and is discussed below.

Scope

  1. The shared public chrome, built. MOTIR-3880 draws one header, nav and footer for every surface on the brand host; this story renders it here, over @motir/design-system. With every public surface on one origin the chrome is finally one implementation rather than two, which is the arrangement that design was drawn for.
  2. /explore and /explore/topic/*, against /api/public/explore + /api/public/categories — the square, its ranked tabs, the topic landing pages, the empty and error states, and the crawl surface (robots.txt, sitemap.xml, canonicals, the entity JSON-LD whose SearchAction finally targets a search this host serves).
  3. /docs. ⚠️ This is the card that needs a decision before it is built, and the story must not paper over it: the eight doc pages are GENERATED from motir-core's own registries — lib/apiDocs/reference reads the OpenAPI spec file, lib/apiDocs/mcp reads the tool catalogue. Rendering them here means consuming those registries across a repository boundary, which is the mirror-rot tests/navigation/proxy-matcher.test.ts exists to catch. Decide HOW before writing the pages — a published artifact motir-core emits and this repo installs is the shape that does not rot; a copied spec is the shape that does.
  4. /legal and /legal/<slug> — the seven documents, ported byte-for-byte from motir-core and rendered under the same chrome. Unlike 2 and 3 these are files on disk in this repository, not an API read: no database, no network hop, no motir-core call at run time. MOTIR-4005 draws them; MOTIR-4009 builds them, along with the Markdown renderer and front-matter parser this repository does not yet have.

Boundary — where this story ENDS

  • It does not touch /p/*. Public project pages are MOTIR-3877's; they land on the same host, under the same chrome, and that story is blocked_by this one for the chrome and by MOTIR-3876 for the contract.
  • It does not touch the motir-core side of the legal move. The configured legal-document manifest, the three link surfaces on app.motir.co, the re-consent gate over the manifest and the deletion of content/legal/ are all MOTIR-3909's, and that story is blocked_by this one.
  • It does not delete anything from motir-core. Retiring the abandoned pages and issuing the 301s off app.motir.co happens only once this story serves the replacements. MOTIR-3951 removes app/(public) bar legal/; MOTIR-4013, over in MOTIR-3909, removes legal/.
  • It does not repoint DNS. motir.co already resolves to this application.
  • It does not make anything cloud-only. motir-marketing is moooon's own site; it is not shipped to self-hosters, so the gate has nothing to do here.

Verification recipe

  1. https://motir.co — the landing, unchanged.
  2. Explore from the header — /explore renders on the same host, under the same chrome, with real project cards.
  3. A ranked tab, then a topic page from the footer's crawl links; back.
  4. Docs — renders on this host, and its content matches what motir-core currently publishes.
  5. Legal from the footer — /legal lists all seven documents; open one and it renders under the same chrome, with its version line; an unknown slug is a 404.
  6. robots.txt and sitemap.xml on this host list these surfaces and nothing that lives elsewhere.
  7. /explore with no public projects — the empty state, not a crash; and with the API unreachable — the error state, not a blank page. /legal is unaffected by an API outage, because it reads no API.

Acceptance criteria

  • Every child is done; the repository set is motir-marketing alone.
  • /explore, /explore/topic/*, /docs, /legal and /legal/<slug> render on motir.co under one chrome, matching MOTIR-3880's asset — layout, states and the primitives it names — and /legal additionally matching MOTIR-4005's.
  • Every read of PROJECT DATA goes through motir-core's public API. No database client, no Prisma import and no direct connection string appears in this repository — asserted by a test, because the cheap wrong answer here is a second database reader. The legal documents are the one surface that reads neither: they are files in this repository.
  • The /docs mechanism is decided and recorded before the pages are written, and whatever is chosen carries a guard that fails when this repository's copy drifts from motir-core's registries. A copied spec with no guard is not an acceptable outcome.
  • The seven legal documents are byte-identical to motir-core's, with per-file checksums from both sides, and every .md in content/legal/ is reachable as a route.
  • The empty, loading and error states are implemented for every API-backed surface, and the error state is asserted — the API is now a network hop, so failure is a real state rather than a theoretical one.
  • No link in the chrome resolves to a 404; the entity JSON-LD's SearchAction targets a search THIS host serves.
  • AA contrast holds in both themes for everything the chrome introduces.

Context refs

  • motir-core/app/api/public/explore/route.ts · categories/route.ts — the anonymous contract this story consumes
  • motir-core/app/(public)/explore/ — the surface being reproduced; read it for behaviour, do not port its data layer
  • motir-core/app/(public)/legal/ · content/legal/ · lib/legal/documents.ts — the legal surface being reproduced, and the parser that ports across
  • motir-core/lib/apiDocs/{reference,mcp,surfaces}.ts — what /docs is generated from, and the reason its mechanism is a decision
  • motir-marketing/app/_components/SiteHeader / SiteFooter, the chrome this replaces
  • MOTIR-3876 — the versioned contract this story consumes; blocked_by
  • MOTIR-3880 — the chrome asset this builds to
  • MOTIR-3909 — the motir-core side of the legal move; blocked_by this story

Advisory dispositions

  • likely-missing-edgeMOTIR-3880 (the chrome design, named in this story's acceptance criteria): genuinely consumed, and NO edge is owed — it is this story's own child. The note that used to stand here recorded 3880 as mis-filed under MOTIR-3876 and owed a re-file; that re-file has happened and 3880 is a subtask of this story. A story→own-child blocked_by would be cross-level, which gate 7 forbids; the parent relationship is what carries it.
  • referenceMOTIR-3877 (advisory): not consumed. It is named in this story's BOUNDARY, which exists to say /p/* is somebody else's.
  • referenceMOTIR-3909 (advisory): the direction is OUT, not in. That story is blocked_by this one; this story names it to say the motir-core half of the legal move is not here.