BetterTicket is a public ticketing web application. The first product slice supports anonymous ticket creation through a React frontend and Fastify API, with tickets stored in PostgreSQL. Authentication and technician workflows are not implemented yet.
| Location | Purpose |
|---|---|
apps/web |
React/Vite ticket-creation frontend and component tests. |
apps/api |
Fastify API, Drizzle schema/migrations, and API/database tests. |
docker/ and compose.yml |
Pinned Docker toolchain and local PostgreSQL/S3-compatible services. |
scripts/smoke.sh |
Disposable infrastructure smoke test. |
.github/workflows/ |
Pull-request checks and scheduled CodeQL analysis. |
.agents/skills/ |
Repository-specific Codex skills. |
docs/ |
Product specs, implementation plans, and architecture decisions. |
infrastructure_plan.md |
Approved infrastructure decisions and deferred product decisions. |
-
Install Git, Docker Desktop (or Docker Engine with Compose), and a current evergreen browser. Node.js and pnpm run inside Docker; they are not host prerequisites.
-
Clone the repository and create local-only service settings:
cp .env.example .env
The example values are safe local development credentials. Keep real service credentials in the untracked
.envfile or a provider secret manager. -
Build the pinned Node 24.21.0/pnpm 10.34.5 toolchain and install the lockfile:
docker compose --profile tools build toolchain docker compose --profile tools run --rm toolchain pnpm install --frozen-lockfile
-
Run local PostgreSQL and S3-compatible object storage. Ports bind only to
localhost:docker compose up --detach postgres object-storage
-
Apply the versioned PostgreSQL migrations, then start the frontend and API in the pinned toolchain. Vite serves the application at
http://localhost:5173and proxies/apito Fastify on port 3000:docker compose --profile tools run --rm toolchain pnpm db:migrate docker compose --profile tools run --rm --service-ports toolchain pnpm dev
-
Run the quality checks in the toolchain container, then the host Docker smoke test. PostgreSQL must be running because the API suite includes a real persistence test:
docker compose --profile tools run --rm toolchain pnpm format:check docker compose --profile tools run --rm toolchain pnpm lint docker compose --profile tools run --rm toolchain pnpm typecheck docker compose --profile tools run --rm toolchain pnpm test docker compose --profile tools run --rm toolchain pnpm coverage docker compose --profile tools run --rm toolchain pnpm build bash scripts/smoke.sh -
Stop the long-lived local services when finished:
docker compose down
To discard their local data as well, use
docker compose down --volumes.
Anonymous visitors can submit a title, issue description, setup details, and optional additional information. POST /api/tickets validates the request, rejects unknown fields, and stores the ticket with a generated UUID, OPEN status, and timestamps. See the feature spec and ADR-001 for scope and rationale.
The pnpm workspace contains React/Vite and Fastify packages. Drizzle schema files are the database source of truth, and generated SQL migrations are committed under apps/api/drizzle.
Pull requests run locked installation, formatting, linting, type checking, migrations against PostgreSQL, unit/component/integration tests, coverage, application builds, Compose validation, the infrastructure smoke test, and Gitleaks. CodeQL runs weekly and on manual dispatch. Dependabot tracks npm, Docker, and GitHub Actions updates. Playwright, Trivy scanning, deployment, and release workflows remain deferred.
Docker image tags are deliberately pinned. Dependabot proposes updates; review and test them before merging.
Before enabling a release workflow, select the static host, API container host, registry, PostgreSQL provider, object-storage provider, and release owner. Then configure protected staging and production environments and the named secrets/variables listed in infrastructure_plan.md—including API_CONTAINER_REGISTRY_TOKEN, API_DEPLOY_TOKEN, FRONTEND_DEPLOY_TOKEN, DATABASE_URL, object-storage settings, and AUTH_SECRET. No release workflow is present yet because these providers have not been selected.
- If Docker cannot connect, start Docker Desktop and rerun
docker compose config --quiet. - If ports 5432 or 8333 are occupied, stop the conflicting local service or change the loopback mapping in
compose.yml. - If Docker reports a bind-mount permission issue, grant Docker Desktop access to this repository and rerun the command.
- If tests report that the
ticketsrelation does not exist, rundocker compose --profile tools run --rm toolchain pnpm db:migrate. - If ports 3000 or 5173 are occupied, stop the conflicting application before running the development command.
- If a locked install fails after changing dependencies, regenerate
pnpm-lock.yamlfrom the toolchain withdocker compose --profile tools run --rm toolchain pnpm install, review the diff, then rerun with--frozen-lockfile.