Context
Today the whole application lives in a single package with three top-level source trees (src/server, src/client, src/shared) resolved through TS path aliases (@server, @client, @shared in tsconfig.json and vite.config.ts). That worked while the engine, the HTTP layer, the Cloudflare runtime glue and the dashboard grew together, but the boundaries are only conventions, nothing stops the review engine from importing a Hono Context, or a DB module from reaching into route code.
Concretely:
- The review engine (src/server/core/review, src/server/core/model-output, src/server/core/rules, src/server/prompts) is genuinely reusable logic, but isn't consumable independently of the Worker.
- GitHub is hardwired rather than adapted to:
api.github.com / @server/core/github is referenced directly from src/server/core/job-recovery.ts, src/server/routes/api/jobs.ts, src/server/routes/api/repos.ts and src/server/routes/auth.ts.
- Cloudflare bindings (APP_KV, HYPERDRIVE, Workflows, Queues) are threaded through business logic via
AppBindings (src/server/env.ts), so core code can't run or be tested off-platform.
- The UI has a clean primitive layer (src/client/components/ui, src/client/components/shared, src/client/components/motion) that isn't separable from the app's feature components and pages.
Goal
Split the repo into npm workspace packages with explicit, enforced dependency directions, so each piece can be built, tested, versioned and reused on its own, and so self-hosters can swap environment-specific parts (storage, runtime, identity, git provider) without forking the engine.
Target dependency direction
@codra/schema (types + zod contracts, zero runtime deps)
^
@codra/core (review engine, pure; ports only, no Hono/Cloudflare/GitHub)
^ ^ ^
@codra/models @codra/provider-github @codra/db
^
@codra/api (mountable Hono router; depends on ports, not bindings)
^
apps/worker (Cloudflare entrypoint: wires bindings to ports)
@codra/ui (design system + primitives; depends only on @codra/schema)
^
apps/dashboard (pages + feature components)
Target folder/file structure
codra/
├── package.json
├── tsconfig.base.json
├── eslint.config.js
├── vitest.workspace.ts
├── db/ -> moves into packages/db
├── scripts/ -> split, see notes below
│
├── packages/
│ ├── schema/ -> from src/shared/*
│ ├── core/ -> from src/server/core/{review,model-output,rules,diff}, prompts
│ ├── db/ -> from src/server/db/*, db/migrations
│ ├── models/ -> from src/server/models/*, model-* services
│ ├── provider-github/ -> from src/server/core/github/*, services/github.ts
│ ├── api/ -> from src/server/{app.ts,routes/*,middleware/*}
│ └── ui/ -> from src/client/{components/ui,shared,motion}, lib, app.css
│
├── apps/
│ ├── worker/ -> Cloudflare entrypoint, only Workers-aware app
│ └── dashboard/ -> from src/client/{pages,components/features}, main.tsx
│
├── test/
│ ├── mocks/
│ └── e2e/
│
└── .github/workflows/
Notes on parts that are not a clean 1:1 move:
scripts/ splits by owner: migrate*.mjs moves to packages/db/scripts; setup-cloudflare.js and its helpers move to apps/worker/scripts; comment-density.mjs, outdated-rate.ts and test.mjs stay at the root.
src/server/core/http.ts and logger.ts each split in two: the transport-agnostic half moves to packages/core, the Hono-Context-touching half moves to packages/api.
jobs-table.tsx, page-header-actions.tsx and chart-primitives.tsx split: the generic primitive moves to packages/ui, the domain-aware wrapper stays in apps/dashboard.
wrangler.jsonc and worker-configuration.d.ts move wholesale into apps/worker, since that is the only place Cloudflare-specific config should exist.
Full per-package file listings are in each sub-issue below, this is the top-level shape only.
Non-goals
- No behavior changes anywhere in this effort, every step is a move/refactor with the existing suite green.
- No new features, no prompt/gate/scoring changes, no visual redesign.
- No additional git-provider implementation beyond the GitHub adapter.
- No big-bang rewrite, land packages incrementally, keeping
main deployable at every step.
Suggested ordering
Workspace scaffolding, then @codra/schema, then @codra/core, then @codra/provider-github, the platform port/apps/worker, @codra/db and @codra/models in parallel, then @codra/api, then the session/identity port. @codra/ui is independent and can be done any time, including first if you want an early win.
Context
Today the whole application lives in a single package with three top-level source trees (src/server, src/client, src/shared) resolved through TS path aliases (
@server,@client,@sharedin tsconfig.json and vite.config.ts). That worked while the engine, the HTTP layer, the Cloudflare runtime glue and the dashboard grew together, but the boundaries are only conventions, nothing stops the review engine from importing a HonoContext, or a DB module from reaching into route code.Concretely:
api.github.com/@server/core/githubis referenced directly from src/server/core/job-recovery.ts, src/server/routes/api/jobs.ts, src/server/routes/api/repos.ts and src/server/routes/auth.ts.AppBindings(src/server/env.ts), so core code can't run or be tested off-platform.Goal
Split the repo into npm workspace packages with explicit, enforced dependency directions, so each piece can be built, tested, versioned and reused on its own, and so self-hosters can swap environment-specific parts (storage, runtime, identity, git provider) without forking the engine.
Target dependency direction
Target folder/file structure
Notes on parts that are not a clean 1:1 move:
scripts/splits by owner:migrate*.mjsmoves topackages/db/scripts;setup-cloudflare.jsand its helpers move toapps/worker/scripts;comment-density.mjs,outdated-rate.tsandtest.mjsstay at the root.src/server/core/http.tsandlogger.tseach split in two: the transport-agnostic half moves topackages/core, the Hono-Context-touching half moves topackages/api.jobs-table.tsx,page-header-actions.tsxandchart-primitives.tsxsplit: the generic primitive moves topackages/ui, the domain-aware wrapper stays inapps/dashboard.wrangler.jsoncandworker-configuration.d.tsmove wholesale intoapps/worker, since that is the only place Cloudflare-specific config should exist.Full per-package file listings are in each sub-issue below, this is the top-level shape only.
Non-goals
maindeployable at every step.Suggested ordering
Workspace scaffolding, then @codra/schema, then @codra/core, then @codra/provider-github, the platform port/apps/worker, @codra/db and @codra/models in parallel, then @codra/api, then the session/identity port. @codra/ui is independent and can be done any time, including first if you want an early win.