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-4242In Review

The Members room's three public-page links still point at the app host — retarget view, edit and the copied share URL through one public-host accessor

Found by MOTIR-4205's asset (design/projects/public-page.mock.html, Panel A frames ② ③; design/projects/design-notes.md § Public page — the room in project settingsThe entrance), 2026-09-02. Carved out of MOTIR-4171 by the split its sizing re-check produced: these three sites have no dependency on the room and are one small PR.

The defect

app/(authed)/settings/project/members/_components/ProjectMembersSettings.tsx still builds every public-page address from the APPLICATION host, and app/(public)/p/ was deleted by MOTIR-3951:

  1. View public page (BuildInPublicManageRow, ~:700) — href="/p/<key>" and the mono path beside the Building in public badge read /p/<key>. 404 on app.motir.co.
  2. Edit on the public page → (PublicShareSection, ~:757) — href="/p/<key>?edit=1". 404, and the room it should open is Settings › Project › Public page.
  3. The share field + Copy (PublicShareSection, copyLink) — the copied value is window.location.origin + /p/<key>, i.e. https://app.motir.co/p/<key>, which a customer pastes into a tweet and which 404s. MOTIR-4171's own criterion counted two links and its test sweeps hrefs; this one is a copied string and neither could see it.

All three reproduced at the reporter's own base b2d7798b2, which is byte-identical to origin/main on this file (git log b2d7798b2..origin/main -- <the file> → empty), so nothing drifted between the filing and the fix.

⚠️ CORRECTED 2026-09-03 by the run — the sentence below was FALSE, and it is kept because a premise nobody re-measures is repaired by nobody. git grep -n "motir\.co" origin/main -- lib app/\(authed\) at b2d7798b2 finds no public-host accessor — only the API-docs example origins. That command is a correct measurement of the wrong set: lib/publicProjects/urls.ts exported publicSiteOrigin(), publicProjectPath() and publicProjectUrl() at that very commit, and it is the accessor. It never matched because it never SPELLS the host — it reads MOTIR_PUBLIC_SITE_URL and falls back to resolveBaseUrlTrimmed(), which is the whole point of it existing. git grep -n "export function public" b2d7798b2 -- lib is the predicate the claim was about, and it returns all three. lib/baseUrl.ts:9-10 names the module outright in its own header.

What to do

⚠️ AMENDED 2026-09-03 (see the amendment section below). Add ONE accessor for the public project page (e.g. publicProjectPageUrl(identifier) beside resolveBaseUrl in lib/baseUrl.ts, or under lib/publicProjects/), reading MOTIR_PUBLIC_SITE_URL with the production fallback https://motir.co, returning https://motir.co/p/<key>. The card's own hedge — "Check lib/baseUrl.ts first — if MOTIR-3881 already exports a public-site accessor, use it rather than adding a second" — is the branch that applies: USE publicProjectUrl(), add nothing. Its fallback is resolveBaseUrlTrimmed() and NOT https://motir.co, deliberately and load-bearingly (below).

  • Route all three sites through it: (1) the href AND the displayed path (motir.co/p/<key>, host shown, scheme dropped — Panel A frame ③); (3) the share field's displayed value and the copied value (https://motir.co/p/<key>, full URL — the thing a person pastes). The value is server-resolvable now, so the after-mount useState dance that existed only to read window.location.origin goes with it.
  • Retarget (2) to /settings/project/public — an in-app link, ArrowRight kept — with the three changed strings from the notes' copy catalog in en and zh: public.heroOverviewSubheadingThe tagline, tags and README visitors see on your public page.; public.editOnPublicPageEdit the public page; public.heroOverviewNoteOpens Settings › Public page. You can write it before the project is public. (zh in the notes.)
  • Ordering, stated: this card may merge before the room is mounted (the sibling task). In that window the edit link is a 404 INSIDE the application instead of a 404 on the wrong host, admin-only, for the life of one sprint. Accepted; do not gate this card on the mount.

Acceptance criteria

  • One public-host accessor exists and is the only place motir.co (or MOTIR_PUBLIC_SITE_URL) is resolved for a project page; a unit test covers the fallback and the env override. AMENDED: it EXISTS — lib/publicProjects/urls.ts, since MOTIR-3881 — and tests/hosting/appUrlSeam.test.ts already pins it as that variable's ONLY reader by tree grep. The criterion is discharged by not adding a second; the run adds the two missing arms to that module's own unit file.
  • BuildInPublicManageRow's View public page href and its displayed path come from the accessor (https://motir.co/p/<key> / motir.co/p/<key>). AMENDED: come from the accessor — the literal is what the accessor answers once MOTIR_PUBLIC_SITE_URL is set (the cutover, MOTIR-3910), and https://app.motir.co/p/<key> until then. See the amendment.
  • PublicShareSection's share field shows, and its Copy writes, the accessor's full URL — asserted on the copied value, not only on markup. (unchanged; the copied-value assertion is the point of the card)
  • The Hero & overview link's href is /settings/project/public, and the three changed strings land in en.json and zh.json (the catalog parity gate). (unchanged)
  • A test asserts no href under app/(authed)/ points at /p/, and that no rendered or copied value in ProjectMembersSettings.tsx carries the application origin + /p/. (unchanged)
  • The two cards match design/projects/public-page.mock.html Panel A frames ② ③ — the same shipped card markup with the new targets and copy. (unchanged)
  • Its own tests ship with it; no full-suite and no --coverage run locally. (unchanged)

⚠️ Amendment — 2026-09-03, the run, on the record

The accessor exists, and its FALLBACK must not be changed. publicSiteOrigin() falls back to the APPLICATION origin while MOTIR_PUBLIC_SITE_URL is unset, and that is an ordering guarantee rather than a convenience — lib/publicProjects/urls.ts's own header says so, tests/hosting/appUrlSeam.test.ts asserts it by name ("the ordering guarantee, not a convenience"), and four other consumers read it:

consumerwhat a https://motir.co fallback would do
proxy.ts:76if (publicSiteOrigin() === resolveBaseUrlTrimmed()) return null is the don't redirect yet guard — it would start 308-ing /p/* off this host before MOTIR-3910's cutover
lib/publicProjects/cors.ts:61the anonymous API's allow-list would name a host that does not call it yet
lib/publicProjects/returnTarget.ts:94the hand-off return target would stop matching the origin that actually sends people
the changelog feed + publicFollowDigestServiceevery emitted absolute URL would name a host that serves nothing

So the card asked for a value that is right about the DESTINATION and wrong about the CLOCK. Routing the three sites through the accessor makes them right at the cutover with no second code change, which is what the accessor is for; hard-coding the host would have made three sites right today and five wrong.

Sizing re-check (the design merged 2026-09-03T01:46Z, twelve minutes AFTER this card was created — the calendar check fires). The asset ADDS nothing to this card: its GIVES/TAKES row names "the three retargets and a public-host accessor", and the accessor turns out to be zero work. 2 SP / 35 min stands; it is if anything generous.

Filed as a planning bug under MOTIR-1465 — the premise, not the card. Everything else the card says was reproduced exactly as written.

Context refs

  • motir-core/app/(authed)/settings/project/members/_components/ProjectMembersSettings.tsx ~:690–:790 — the three sites
  • motir-core/lib/publicProjects/urls.tsthe accessor: publicSiteOrigin() / publicProjectPath() / publicProjectUrl() (MOTIR-3881). lib/baseUrl.ts is its neighbour and names it in the header
  • motir-core/tests/hosting/appUrlSeam.test.ts — the single-reader grep and the two fallback arms
  • motir-core/design/projects/public-page.mock.html Panel A + design/projects/design-notes.md § The entrance — three doors and the copy catalog
  • motir-core/docs/decisions/public-surface-hosts.md AMENDMENT 4 row 7 — why the edit door is in the application
  • MOTIR-4171 — the room; MOTIR-4205 — the design this was found by