Skip to content

Repository files navigation

kwtech-software

Turborepo monorepo, pnpm workspaces. Toolchain and conventions follow ../masterdb-mgt-tool; the full plan lives in docs/PLAN.md, and the reasoning behind it in docs/DESIGN-NOTES.md. Building a feature? Start with CLAUDE.md: the working guide and checklist, which Claude Code also loads on its own.

Requirements

  • Node >= 22
  • pnpm >= 11 — corepack enable picks it up from the packageManager field. .npmrc sets engine-strict=true, so an older pnpm fails the install rather than producing a subtly different one.
  • Docker — pnpm dev runs the local Postgres in a container.
  • On Windows, WSL2.

New computer? Follow docs/SETUP.md, from git clone to signed in, with the database, seeding, optional services and troubleshooting.

Layout

apps/
  web-server/         NestJS — REST today, GraphQL + WS in Phase 3   :8080
  web-app/            Next.js — web frontend                         :8081
packages/
  web-ui/                 React + Tailwind 4 + AG Grid Community
  module-kit/             the module contract every app composes
  module-auth/            sign-in, sessions, MFA, password reset
  module-permissions/     organizations, workspaces, roles, features, plans, limits
  module-chat/            conversations and messages
  module-queuing-window/  walk-in queue: windows, lines, a live TV board
  module-notification/    system notifications: bell, toasts, an inbox

No module imports another; only the apps depend on them. The map, and the ports modules use instead, are in docs/DEPENDENCIES.md, enforced by pnpm check:boundaries.

Feature modules ship as one package with a dependency-free core plus adapters behind subpath exports — @kwtech/module-permissions, .../server, .../react. Apps list their modules once and compose the rest:

export const WEB_MODULES = [permissionsWebModule, usersWebModule];
export const ROUTES = composeRoutes(WEB_MODULES);

See packages/module-kit/README.md for the contract and docs/PLAN.md §9 before adding a module.

Getting started

pnpm install
pnpm env:new local   # envs/local/, with fresh secrets
# fill in SEED_USER_* (your sign-in) in envs/local/web-server.env — BEFORE the first start
pnpm dev             # database created, migrated, filled and seeded; both apps running

Every step, and what each one does, is in docs/SETUP.md.

Environments: local, staging, production

Each environment is a profile: envs/<name>/web-server.env and envs/<name>/web-app.env, gitignored. The active one is symlinked to apps/web-server/.env.local and apps/web-app/.env.local (both apps use the same file name), so switching is one command and every tool (Nest, Next, Prisma, the seeders) follows it.

pnpm env:show            # active profile, its database and API (no secrets printed)
pnpm env:new staging     # create a profile from the templates, with fresh secrets
pnpm env:use staging     # switch both apps
pnpm db:deploy           # …now runs against staging
pnpm env:use local       # back
pnpm env:check           # templates hold no secrets; profiles lack no variable
  • Development defaults to local. pnpm dev activates it and creates it the first time. A non-local profile prints a warning banner on every pnpm dev.
  • APP_ENV in each profile says what it is, and the guards trust it: db:migrate and db:snapshot run only on local, and db:restore never touches production.
  • Deployed hosts don't use profile files. Set the same variables in the host (Vercel, the container host), including APP_ENV. A production build refuses to boot without it.
  • .env.example files are templates committed to a public repo. A value for any *_PASSWORD, *_SECRET, *_KEY or *_EMAIL fails the commit.
  • Keep each profile in a password manager too. That's how a new machine gets them.

On another machine, including one with an old apps/web-server/.env: git pull && pnpm install && pnpm env:show moves the old files into envs/local/ without losing anything, and pnpm env:check lists what's new. The full steps for each case are in envs/README.md → Setting up another machine.

pnpm dev starts everything — every package in watch mode plus both apps:

API http://localhost:8080/api/v1
API docs (Swagger) http://localhost:8080/api/v1/docs
Web http://localhost:8081
Sign in http://localhost:8081/auth/signin

Editing a packages/* file rebuilds it and the running apps pick the change up; there is no separate build step while developing.

That is one tsc --watch per package, which is heavy on a machine with little memory. When the work is in one or two packages, pnpm dev:focus module-task (add more names, or --api / --web) runs the apps and watches only those. Every other package is still built once at the start, but an edit to one of them does not show up until you name it too or go back to pnpm dev.

Commands

pnpm dev              # everything: package watchers + both apps
pnpm dev:api          # just the API, and the packages it needs
pnpm dev:web          # just the frontend, and the packages it needs
pnpm dev:focus module-task   # both apps, watching ONLY the packages named (lighter)

pnpm build            # everything, in dependency order
pnpm start            # run the built apps
pnpm typecheck
pnpm test
pnpm lint             # biome — one tool, no eslint, no prettier
pnpm check:fix        # lint + format, writing fixes

Database (all scoped to apps/web-server, which owns the schema — PLAN §12.2):

pnpm --filter @kwtech/web-server db:compose    # copy module prisma fragments in
pnpm --filter @kwtech/web-server db:generate   # compose + generate the client
pnpm --filter @kwtech/web-server db:migrate    # compose + migrate dev
pnpm --filter @kwtech/web-server db:seed       # idempotent first user
pnpm --filter @kwtech/web-server db:snapshot   # dev data → seed-data/snapshot.json
pnpm --filter @kwtech/web-server db:restore    # seed-data/snapshot.json → empty database
pnpm --filter @kwtech/web-server db:studio

Postgres is expected where DATABASE_URL points, localhost:5432 by default. pnpm dev and pnpm dev:api run scripts/dev-db.mjs first: if nothing answers on that port it starts a kwtech-postgres Docker container (creating it the first time, with its data in the kwtech-pgdata volume), and on a brand-new volume applies the migrations and seeds. A native Postgres already on the port is used as-is.

pnpm db:up            # start (or create) the container without starting the apps
pnpm db:down          # stop it; the data stays in the volume

Shared dev data. apps/web-server/seed-data/snapshot.json is a committed copy of a dev database's rows, so a second machine starts where the first left off. A brand-new container restores it automatically; against a native Postgres, or to catch up with a newer snapshot, run it yourself:

pnpm db:snapshot          # this database → snapshot.json (commit it)
pnpm db:restore           # snapshot.json → an empty, migrated database, then db:seed
pnpm db:restore --force   # the same, emptying the database first

The repository is public, so the snapshot carries no credentials: no password hashes, MFA secrets, sessions or reset tokens. After a restore the SEED_USER_* and SEED_DEMO_USER_* accounts sign in with the passwords in your .env; any other account uses forgot-password, whose link is printed in the API console while SMTP_URL is unset. Everything else in it — names, emails, chat messages — is readable by anyone, so keep real customer data out of dev.

Docker Engine inside WSL2, once (/etc/wsl.conf needs systemd=true):

sudo apt update && sudo apt install -y docker.io
sudo usermod -aG docker $USER && sudo systemctl enable --now docker
# then open a new terminal so the group membership applies

Conventions

  • Biome is the only linter/formatter — no ESLint, no Prettier.
  • Packages extend the root tsconfig.base.json directly; there is no typescript-config package.
  • Shared dependency versions go in the pnpm catalog: in pnpm-workspace.yaml.
  • turbo.json and biome.jsonc are JSONC — comment anything non-obvious.
  • Conventional commits, enforced by lefthook + commitlint.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages