6.6 KiB
Local non-container development
This guide documents the local, non-container developer path for the EPPP workspace: how to install, build and run the project on your machine without Docker. The containerised path (Docker Compose baseline, container smoke tests) is tracked separately as story [E00-S02] Docker Compose baseline and is not covered here.
Status: this document tracks the E00-S01 workspace bootstrap state. Commands and expected outputs below were verified from a clean clone.
What you get at bootstrap
The workspace is a pnpm monorepo with three package groups:
| Group | Path | Purpose |
|---|---|---|
apps/ |
apps/server (@personal-blog/server) |
Public server application. Serves the application health endpoint (E00-S02-T03); the Fastify 5 application shell lands in a later story. |
packages/ |
packages/core (@personal-blog/core) |
Application core (site identity, content primitives). Bootstrap placeholder. |
packages/ |
packages/database-postgres (@personal-blog/database-postgres) |
PostgreSQL database adapter package. Single owner of the pg/Kysely driver imports (E00-S03-T02); the migration ledger (schema_migrations, E00-S03-T03) and the migration advisory lock (E00-S03-T04) are implemented here; the migration runner (failure diagnostics) lands in later stories. |
extensions/ |
extensions/example (@personal-blog/example-extension) |
Example extension exercising the extensions/ group. Bootstrap placeholder. |
A dependency-boundary rule (dependency-boundaries.json, enforced by
tests/architecture-import.test.mjs) keeps the groups from collapsing into an
accidental dependency graph: no packages/* package may import a concrete
extensions/* package.
Prerequisites
- Git — to clone the repository.
- Node.js 24.x — required. The root
package.jsonrestricts the Node engine to 24.x (engines.node), and the committedpnpm-workspace.yamlsetsengineStrict: true, sopnpm installon any other Node version is rejected (ERR_PNPM_UNSUPPORTED_ENGINE) instead of merely warned. Install Node 24.x vianvm,fnmor another version manager to match CI. - pnpm 11.23.0 — pinned via the
packageManagerfield in the rootpackage.json. The easiest way to get exactly this version is Corepack, which ships with Node.js (corepack enable).
No database, no runtime services and no Docker daemon are required at this stage.
Install
# 1. Clone the repository
git clone https://git.stevanovic.co.uk/Fabrika/PersonalBlog.git
cd PersonalBlog
# 2. Activate the pinned pnpm (11.23.0) via Corepack
corepack enable
# 3. Install dependencies against the committed lockfile (reproducible)
pnpm install --frozen-lockfile
- The install is frozen:
--frozen-lockfilerefuses to run ifpnpm-lock.yamlis out of date with the manifests, so every clone gets the exact same dependency tree. CI uses the same flag. - If you are adding or changing dependencies, run
pnpm install(without the flag) and commit the resultingpnpm-lock.yamlso the frozen install keeps working for everyone. node_modules/and the pnpm content-addressable store are git-ignored and never committed.
Build
# Compile every workspace package (apps, packages, extensions) into dist/
pnpm build
# Typecheck every workspace package (no emit)
pnpm typecheck
pnpm build runs tsc -p tsconfig.json in each package in topological order
and emits dist/ (JavaScript + type declarations + source maps) per package.
Expected result: apps/server/dist/, packages/core/dist/,
packages/database-postgres/dist/ and extensions/example/dist/ are
produced, all packages report Done, exit 0.
dist/ is git-ignored; rebuild whenever you change src/.
Run
# Run the compiled public server entrypoint
pnpm --filter @personal-blog/server start
This runs the start script of apps/server (node dist/index.js), i.e. the
compiled application entrypoint. Two things to know:
- The command must follow
pnpm build— thestartscript executes the compiled artifact indist/, it does not compile first. - Since [E00-S02-T03],
apps/serverserves the application health endpoint: starting it opens an HTTP server on port 3000 answeringGET /healthwith HTTP 200 and{"status":"ok"}, so the process stays up. The real Fastify 5 application shell — which turns this into the full serving API — lands in a later story; thestartcommand shape stays the same once it does.
To run the compiled output of any other workspace package directly:
node <package-dir>/dist/index.js # e.g. node packages/core/dist/index.js
Test
pnpm test
pnpm test runs the node:test suites under tests/ (currently
tests/architecture-import.test.mjs, 10 tests) with zero extra dependencies.
This is also the suite that enforces the dependency-boundary rule.
Smoke check from a clean clone
git clone https://git.stevanovic.co.uk/Fabrika/PersonalBlog.git && cd PersonalBlog
corepack enable
pnpm install --frozen-lockfile # exit 0, lockfile untouched
pnpm build # 4/4 packages emit dist/, exit 0
pnpm typecheck # 4/4 packages pass --noEmit, exit 0
pnpm test # 10/10 pass, exit 0
pnpm --filter @personal-blog/server start # serves GET /health on port 3000, stays up
Troubleshooting
| Symptom | Cause / fix |
|---|---|
pnpm: command not found |
Corepack shims not activated — run corepack enable, or prefix commands with corepack pnpm .... |
ERR_PNPM_OUTDATED_LOCKFILE |
pnpm-lock.yaml is out of date with the manifests. Run pnpm install (unfrozen) and commit the lockfile update. |
ERR_PNPM_UNSUPPORTED_ENGINE on install |
Your Node version is outside the supported 24.x engine line (engines.node in the root package.json, enforced by engineStrict: true in pnpm-workspace.yaml). Install Node 24.x (e.g. via nvm, fnm or another version manager). |
start exits immediately with no output |
The server crashed or exited at startup — check the process output. Since [E00-S02-T03] the entrypoint serves GET /health on port 3000 and stays up; a missing pnpm build (stale/absent dist/) is the usual cause (see Run). |
.env files |
.env/.env.* are git-ignored; a committed .env.example template lands with the environment story (E00-S04). |
Out of scope
- Root build/test/typecheck script wiring — covered by E00-S01-T05; only usage is documented here.
- Docker Compose baseline and container smoke tests — E00-S02.
- PostgreSQL adapter, migration runner and other runtime services — later E00 stories.