Context
Codra's backend currently runs exclusively on Cloudflare Workers (apps/worker). Cloudflare Workers use a proprietary ExportedHandler model with environment bindings (env.KV, env.QUEUE) and have strict CPU time limits (10ms). To support self-hosting on dedicated servers (e.g., VPS, Railway, Render) without these constraints, we need a standard Node.js deployment target. This target will run the exact same core API router (@codraoss/api) and business logic (@codraoss/core), but will serve it using standard Node.js web server primitives (via Hono's Node adapter).
Task
- Workspace Setup:
- Create a new directory at
apps/node.
- Initialize a
package.json with the name @codraoss/node-server. Mark it as private.
- Create a
tsconfig.json that extends the monorepo's base config (../../tsconfig.base.json).
- Configure a build tool (e.g.,
tsup) matching how packages/api or apps/worker is built. Add dev, build, and start scripts.
- Dependencies:
- Install
@hono/node-server, hono, and dotenv.
- Link the internal monorepo packages:
@codraoss/api, @codraoss/core, @codraoss/db, and @codraoss/schema.
- Environment & Context Typings:
- Create
apps/node/src/env.ts. Define a NodeAppBindings interface that mirrors the properties of AppBindings from the worker, but replaces Cloudflare-specific types with standard Node equivalents (which we will build in subsequent issues).
- HTTP Server Initialization:
- Create
apps/node/src/index.ts.
- Import
createApiRouter from @codraoss/api. This function returns the core Hono application.
- Use
serve from @hono/node-server to mount the Hono app, configuring it to listen on process.env.PORT (defaulting to 3000).
- Database Context Wrapping:
- In Cloudflare, requests are wrapped in
runWithDb(env, () => ...) (from @codraoss/db/client) so that postgres.js connections and AsyncLocalStorage transaction states are propagated cleanly. You must replicate this in the Node entry point. Ensure the DATABASE_URL environment variable is loaded (using dotenv) and passed correctly to initialize the Postgres client before the server starts accepting requests.
- Stub Dependencies:
- For now, pass empty/mock objects for the KV store, Queue, and Orchestrator into the API context so the TypeScript compiler passes and the router can successfully boot.
Acceptance Criteria
- Running
npm run dev in apps/node successfully compiles the TypeScript code and starts a Node web server on port 3000.
- Sending a
GET request to a public API endpoint or healthcheck returns a successful HTTP 200 JSON response from the Hono router.
- The
postgres.js database client successfully connects to a local Postgres instance using a standard connection string (e.g., postgres://user:pass@localhost:5432/codra).
- The codebase passes strict TypeScript compilation (
tsc --noEmit).
Relevant Files/Paths
apps/node/package.json
apps/node/tsconfig.json
apps/node/src/env.ts (New)
apps/node/src/index.ts (New)
Context
Codra's backend currently runs exclusively on Cloudflare Workers (
apps/worker). Cloudflare Workers use a proprietaryExportedHandlermodel with environment bindings (env.KV,env.QUEUE) and have strict CPU time limits (10ms). To support self-hosting on dedicated servers (e.g., VPS, Railway, Render) without these constraints, we need a standard Node.js deployment target. This target will run the exact same core API router (@codraoss/api) and business logic (@codraoss/core), but will serve it using standard Node.js web server primitives (via Hono's Node adapter).Task
apps/node.package.jsonwith the name@codraoss/node-server. Mark it as private.tsconfig.jsonthat extends the monorepo's base config (../../tsconfig.base.json).tsup) matching howpackages/apiorapps/workeris built. Adddev,build, andstartscripts.@hono/node-server,hono, anddotenv.@codraoss/api,@codraoss/core,@codraoss/db, and@codraoss/schema.apps/node/src/env.ts. Define aNodeAppBindingsinterface that mirrors the properties ofAppBindingsfrom the worker, but replaces Cloudflare-specific types with standard Node equivalents (which we will build in subsequent issues).apps/node/src/index.ts.createApiRouterfrom@codraoss/api. This function returns the core Hono application.servefrom@hono/node-serverto mount the Hono app, configuring it to listen onprocess.env.PORT(defaulting to 3000).runWithDb(env, () => ...)(from@codraoss/db/client) so thatpostgres.jsconnections andAsyncLocalStoragetransaction states are propagated cleanly. You must replicate this in the Node entry point. Ensure theDATABASE_URLenvironment variable is loaded (usingdotenv) and passed correctly to initialize the Postgres client before the server starts accepting requests.Acceptance Criteria
npm run devinapps/nodesuccessfully compiles the TypeScript code and starts a Node web server on port 3000.GETrequest to a public API endpoint or healthcheck returns a successful HTTP 200 JSON response from the Hono router.postgres.jsdatabase client successfully connects to a local Postgres instance using a standard connection string (e.g.,postgres://user:pass@localhost:5432/codra).tsc --noEmit).Relevant Files/Paths
apps/node/package.jsonapps/node/tsconfig.jsonapps/node/src/env.ts(New)apps/node/src/index.ts(New)