Skip to content

EthenEthenEthen

Moving Ethen Designer Into Its Own App

Designer was in the wrong owner. The correction moved it into its own Next.js app and re-proved the moved code — without performing public activation.

Designer was in the wrong owner. The correction moved it into its own Next.js app and re-proved the moved code — without performing public activation.

The Ethen Designer standalone app now lives at apps/designer. That sentence sounds simple, but it records an ownership correction, not a cosmetic reorganization. Before the correction, Designer behaved like a route inside Creative or surrounding workspace shells. After the correction, recorded on branch ethen/v5 at HEAD f3a7fb22b, Designer is a first-class standalone Next.js app: package @ethen/designer, started with pnpm --dir apps/designer dev, reviewed locally on port 3014.

This article explains what changed, why the old ownership was wrong, what the scoped recertification established, and what it explicitly left out. The short version: the move fixed the canonical owner, preserved working contracts, re-ran the relevant test batteries against the moved code, and checked the running local app. It did not perform public activation, did not re-run the golden series, and did not authorize new paid-allowance scope.

Why ownership mattered

In the September 20 product/platform split, one rule governs every boundary decision: one capability can appear on multiple surfaces, but it should have one canonical product owner and one shared backend or state. That document is final architecture direction, dated 2026-09-20. It is design authority, not deployment proof. It says where Designer belongs; it does not prove that every migration has shipped.

Under that direction, the ownership map is explicit. Designer belongs to the Designer App. Chat may carry a limited Designer experience for quick generation — “Design this page,” “Redesign this UI,” “Make this card better,” “Generate a dashboard,” “Turn this screenshot into a UI” — but the full design and build workspace belongs elsewhere:

  • Projects
  • Pages
  • Canvas and workspace
  • Components
  • Assets
  • Design systems
  • Code
  • Preview
  • Deploy
  • Domains
  • Version history

The boundary the direction document draws is deliberately short:

  • Chat Designer: quick design generation
  • Designer App: full design and build workspace

The same pattern applies across the specialized apps. Studio, Research, Designer, and Founder are separate target products. Founder is its own Next.js product for autonomous goal-to-outcome jobs. Computer stays Platform-only. Desktop owns Local Models. Code intentionally spans lightweight Chat, cloud Platform, and local Desktop. The point is not to multiply implementations. It is to stop competing copies of the same capability from drifting apart.

Designer violated that rule while it lived as a Creative route or under workspace-shell dominance. A route inherits its host’s lifecycle, layout, navigation, and deployment assumptions. A shell-dominated workspace makes the shell the de facto owner even when the domain code nominally belongs elsewhere. Either arrangement makes it easy for imports, state, and release scope to blur. The correction checkpoint records the fix in binary terms: CANONICAL_DESIGNER_APP=apps/designer, STANDALONE_NEXT_APP=YES, OLD_CREATIVE_APP_OWNERSHIP=NO, OLD_WORKSPACE_SHELL_DOMINANCE=NO, DIRECT_DESIGN_LAB_IMPORT=NO.

That last flag matters for future maintenance. The checkpoint’s memory notes lock the rule that followed the move: no cross-app implementation imports, enforced by test. Designer can be linked to from other surfaces. It cannot be absorbed back into them through private imports.

What “standalone” concretely means here

Standalone in this checkpoint has a precise, checkable meaning. It does not mean “Designer runs in production for the public.” Public activation is recorded as NOT_PERFORMED. It means Designer builds, typechecks, lints, tests, and serves as its own Next.js app from its own directory, with its own home page, workspace view, API routes, and shell files.

The canonical commands and coordinates are:

  • Package: @ethen/designer
  • Directory: apps/designer
  • Dev command: pnpm --dir apps/designer dev
  • Local review URL: http://localhost:3014
  • Branch and HEAD at certification: ethen/v5, f3a7fb22b, with a dirty worktree preserved

The checkpoint also records F10_PRODUCTION_PARITY=PASS and REAL_CONTRACTS_PRESERVED=YES. Those flags describe the fidelity of the move: the production-relevant F-10 behavior survived relocation, and real contracts were not replaced with convenient fakes to make the new app pass.

What moved byte-identically

The move strategy was conservative: move byte-identically with git mv, repoint mechanically, and rewrite only shells. The checkpoint lists the byte-identical set:

  • An 82-file domain library
  • The component tree, with nothing held back — including the mock-coupled canvas set that had to move once the Creative typecheck required it
  • 24 API routes
  • The home page source that was then rewritten for standalone use

Byte-identical movement matters because it preserves lineage and reviewability. A reviewer can distinguish “this file moved” from “this file changed behavior.” The checkpoint’s memory notes prefer lineage remap over history rewrite for the same reason. Corrections append; they do not pretend the earlier structure never existed.

One deletion accompanied the move: an orphaned monolith session-surface copy with zero importers. History was preserved. Deleting a zero-importer copy is not a behavior change; it removes a trap for future readers who might otherwise edit dead code thinking it was live.

Environment handling followed the same minimal-touch approach. Registry lifecycle code was untouched. Environment files reached the new app through gitignored symlinks to root files rather than duplicated or forked configuration. That avoids a second source of truth for environment values during local development.

What was rewritten for standalone life

Shells cannot move byte-identically because they encode the host’s assumptions. The checkpoint lists the rewritten set, and each item reflects the shift from “route inside someone else’s app” to “app with its own lifecycle.”

The home page was rewritten around the F-10 shell while preserving the lifecycle gate. The project workspace view was rewritten to carry its full surface: panels, refine, versions, export, deploy-ledger refusal, and quota and connect honesty. Layout, error, loading, and not-found files were rewritten because every standalone Next.js app needs its own. F10Composer, the template content port, and DesignerHomeClient were rewritten or ported for the same reason.

Landing composer, badge, and registry imports were replaced with F-10-native equivalents. That replacement is characteristic of a shell rewrite: the outward behavior stays aligned with the F-10 contract, but the import graph no longer reaches back into the old host’s landing implementation.

The old root monolith route did not keep a second Designer. It became a dev-redirect and handoff-link compatibility page. The monolith session workspace consumes the canonical Designer through repointed imports as a compatibility path. That is the intended direction for compatibility: old locations point at the new canonical owner rather than keeping a parallel copy alive.

How the old architecture claim is preserved

The checkpoint invalidates the prior 07 and 08 architecture claims and appends that invalidation with history preserved. This article preserves that sequence rather than smoothing it over.

The historical context is: an earlier architecture description placed Designer where the correction later found it should not be. The correction checkpoint supersedes that placement for the local standalone scope it covers. It does not rewrite the earlier documents to pretend they always said apps/designer. Appending the invalidation keeps the audit trail readable: what was claimed, what replaced it, what scope the replacement proved, and what remained unproven.

That discipline also explains the checkpoint’s warning that HTTP 200 does not equal UI reachable. A route can return success while the user-facing workspace remains broken, mislaid, or unreachable. The recertification therefore checked the running app in a browser-like surface, not just route status codes.

What recertification re-proved

FINAL_CERTIFICATION=PASS in this checkpoint is scoped. It means the listed checks passed for the moved standalone app at the recorded HEAD. It does not mean Designer is publicly launched, publicly reachable, or paid-entitlement ready.

The static checks were:

  • apps/designer typecheck clean
  • Creative typecheck clean after the move
  • Root tsc with zero new errors
  • ESLint clean, with moved-file warnings noted as pre-existing rather than introduced by the move

The test batteries were re-proven on the moved code rather than inherited from before the move. The checkpoint records:

  • Bridge: 25 of 25
  • Local: 8 of 8
  • Managed: 6 of 6
  • Gateway: 10 of 10
  • Release: 7 of 7
  • Transport: 5 of 5
  • 06 suites: 8 of 8 plus 8 of 8
  • 07, 08, 09, and 11 suites: passed
  • Neighbour suites: 72 or more passed

The live local checks ran against port 3014 and covered home markers, tab switching, zero overflow from 390 to 1440 pixels wide, zero axe accessibility violations on the checked surfaces, overlay focus trapping, unknown-document honesty, and API auth gating. The environment hygiene checks recorded zero sandboxes and zero Supabase residue in the sense the checkpoint uses those terms: no leftover sandbox coupling and no stray Supabase residue in the moved tree.

Two data-hygiene repairs accompanied the pass. Placeholder QA envelopes were repaired to unmeasured in both trees and regression-locked, so a placeholder can no longer masquerade as a measured result. That fix matters because the checkpoint’s residual list still contains variant subscores and declared mocks, with no standing rule yet for how those should be handled. The checkpoint flags that as follow-up work rather than pretending the QA-envelope fix closed every measurement gap.

What recertification explicitly did not do

The limits section is as important as the pass flags. It names four boundaries.

First, public activation was not performed. The checkpoint records PUBLIC_ACTIVATION=NOT_PERFORMED and states that new scope — public activation and paid allowances — needs its own authorization. The next safe action after this checkpoint was “done,” with owner review at http://localhost:3014. Local review is not public availability. No launch, availability, or access claim follows from this checkpoint.

Second, the golden series was not re-run. The recorded rationale is that subject bytes and spine behavior were unchanged, while lane suites were re-proven live. That is a rationale for why the golden series was judged unnecessary in this scope, not inheritance of an old pass. A future change to subject bytes or spine behavior would need its own evidence.

Third, local file-store scoping is per app working directory, with durable Supabase authority shared. That is a documented storage boundary: local file state follows the app’s current working directory, while durable authority remains shared. Readers should not infer a single unified local store across apps from the fact that durable authority is shared.

Fourth, the monolith session workspace path remains compatibility. It consumes canonical Designer code through repointed imports. Compatibility consumption is not a second canonical owner. It is a migration bridge that points at apps/designer.

The residual QA items reinforce the same point. Variant subscores and declared mocks remain open. There is no standing rule yet for them, and the checkpoint asks for a follow-up pass. A scoped PASS with named residuals is more useful than an unqualified pass that hides them.

A concrete before-and-after example

Consider a developer fixing a bug in the project workspace’s version panel.

Before the correction, the fix lived somewhere under Creative or a workspace shell’s ownership. The reviewer had to answer host questions before reaching the domain question: which shell layout applies, whether the change affects Creative’s other routes, whether the lifecycle gate belongs to the host or the workspace, and whether the API route being called is Designer’s or the monolith’s. The file path alone did not answer “who owns this.”

After the correction, the file lives under apps/designer. The reviewer starts the app with pnpm --dir apps/designer dev, opens http://localhost:3014, and exercises the workspace view directly. Typecheck, lint, and the lane batteries run against the app that owns the code. If the old monolith route is involved, it is a redirect or handoff link, not a competing implementation. If another app needs Designer behavior, it links to Designer rather than importing Designer’s implementation files — a boundary now locked by test.

That is the practical meaning of “one capability, one canonical owner.” It shortens the ownership question from an investigation to a path prefix.

Where Chat fits after the move

The move does not remove lightweight design generation from Chat. The September 20 direction keeps it there deliberately. Chat remains the fast, general-purpose conversational surface with limited versions of deeper workflows: limited Deep Research, limited Studio, lightweight Designer, lightweight Code. It does not contain the full Research workspace, full Studio catalog, full Computer product, or full autonomous Founder system.

The Designer-specific boundary after the move is therefore:

  • Need a quick page, card, dashboard, or screenshot-to-UI draft inside a conversation? That is Chat Designer.
  • Need projects, pages, components, assets, design systems, code, preview, deploy, domains, and version history in one workspace? That is the Designer App at apps/designer.

That boundary also clarifies what the checkpoint did not need to prove. It did not need to prove Chat’s lightweight Designer path, because that path lives under Chat’s ownership. It needed to prove that the full workspace path had a single standalone owner and that the moved code still behaved under its real contracts.

What to check before making bigger claims

Anyone tempted to turn this checkpoint into a launch announcement should stop at the checkpoint’s own limits. A standalone local app with passing typechecks, passing lane batteries, and passing live localhost checks is a meaningful engineering milestone. It is not public activation, paid-entitlement readiness, production deployment evidence, or proof that Studio, Research, and Founder have completed analogous moves. Target separation in an architecture document is never proof that a migration shipped.

The honest next-evidence list follows directly from the checkpoint:

  • A separate, authorized public-activation scope with its own checks before any availability claim
  • A separate paid-allowances authorization before any pricing or entitlement claim
  • A golden-series decision tied to the bytes and behavior actually changing in that future scope
  • A standing rule and follow-up pass for variant subscores and declared mocks
  • Continued enforcement of no cross-app implementation imports so the new owner does not silently blur again

The September 20 direction and the standalone correction checkpoint answer different questions. The direction answers “where should Designer live?” The checkpoint answers “did the local move to apps/designer preserve behavior under the checks we re-ran?” Keeping those questions separate is what makes the Ethen Designer standalone app claim trustworthy: a corrected owner, a scoped local proof, named limits, and history preserved.

The correction is done. The next scope needs its own authorization.