Skip to main content

Developer Onboarding

Quick-start guide for new Ledgerline contributors.

Prerequisites

ToolVersionNotes
Node.js20+node -v to verify
pnpm9+corepack enable && corepack prepare pnpm@latest --activate
DockerLatestRequired for local MongoDB and Valkey

Setup

git clone <repo-url> && cd ledgerline
pnpm install
pnpm dev:infra # starts Mongo + Valkey via Docker Compose
pnpm dev # starts the API with tsx watch (hot reload)

The API listens on http://localhost:<PORT> (default 3000). AdminJS mounts at /admin, the data API at /api.

Render cache config note

In production, cache config can come from VALKEY_URL, REDIS_URL, or REDIS_HOST + REDIS_PORT.

For Render deploys, use the Key Value internal connection details. In production, if a configured cache URL still points to localhost, startup prefers REDIS_HOST/REDIS_PORT when available so the API does not try 127.0.0.1:6379. When both dotenv defaults and platform env vars exist, platform values are used for cache connection settings. If external cache is unreachable at boot, API startup now falls back to in-memory cache so the service can come up for recovery operations.

AdminJS frontend bundles are served with explicit path fallbacks during boot to avoid pnpm/Render path-resolution issues for app.bundle.js, global.bundle.js, and related assets. AdminJS theme bundling also requires @adminjs/themes to be installed in app dependencies; missing it causes startup failure with Cannot find module '@adminjs/themes'.

Admin sidebar resources are grouped into four collapsible sections (Users & Identity, Commerce, Configuration, Monitoring) via src/types/admin.navigation.ts. Per-user theming works by populating req.session.adminUser.theme before AdminJS routes handle the request. System themes define universal layout tokens (sidebar, container, sectionBg, text) and seedSystemThemes updates existing system theme overrides on each deploy. The top-right user dropdown (overridden LoggedIn component) shows the user's display name and links to the User Settings page. The User Settings page uses theme-aware contrast (grey100 for text, sectionBg for inner boxes, filterBg for nested UI) for readability across light and dark themes. The LoggedIn override injects ThemeAwareGlobals (createGlobalStyle) that forces html, body, #app, input, textarea, select to use theme.colors.text and input::placeholder to use theme.colors.grey60, overriding AdminJS's hardcoded dark text color in the layout template. Every custom text element also sets an explicit theme-aware color token (grey100/grey80) to prevent CSS cascade issues. Custom AdminJS components (UserSettingsPage, LoggedIn override) are pre-built at build time via scripts/build-admin-components.mjs and shipped with the deploy. In development, admin.watch() bundles and watches for changes.

Key Commands

CommandPurpose
pnpm devStart dev server with hot reload
pnpm dev:infraStart local Mongo + Valkey containers
pnpm dev:downStop local infra containers
pnpm typecheckRun TypeScript type checking
pnpm lintRun ESLint
pnpm testRun unit tests (Vitest)
pnpm run e2eRun end-to-end API tests
pnpm check:contracts-coverageVerify dependency contract test coverage
pnpm check:cyclesDetect circular imports (Madge)
pnpm formatAuto-format with Prettier + ESLint fix
pnpm semgrepSecurity/correctness scan (optional, requires Semgrep CLI)
pnpm release:dryPreview semantic-release next version/notes without publishing

| pnpm stripe-mock --scenario=<name> | Run Stripe mock harness (local webhook simulator, port 4001) | | pnpm taxjar-mock | Run TaxJar mock harness (local tax API simulator, port 4004) | | pnpm easypost-mock --scenario=<name> | Run EasyPost mock harness (label + tracker webhook simulator, port 4003) |

Recommended pre-push order: pnpm typecheckpnpm lintpnpm testpnpm run e2epnpm check:contracts-coveragepnpm check:cycles

Architecture Overview

Ledgerline uses hexagonal (ports/adapters) architecture:

  • Types (src/types/) — pure shared contracts, no runtime logic.
  • Ports (src/ports/) — app-facing capability interfaces (logging, DB, cache, auth).
  • Adapters (src/adapters/) — concrete infrastructure implementations (Pino, Mongoose, Sentry).
  • App code (src/data/, src/endpoints/) — domain services, validators, endpoints.
  • Bootstrap (src/bootstrap/) — wires adapters into ports, mounts transport surfaces.
  • Init (src/init/) — composition roots that build the full app context.
  • Registries (src/registries/) — per-entrypoint module wiring (endpoints, admin, commands, events).

Key rule: app code imports ports, never adapters. Only bootstrap/init may import adapters.

Where to Find Things

WhatWhere
Architecture rules & layering tabledocs/ARCHITECTURE.md
Contribution conventions & toolingdocs/CONTRIBUTING.md
Auth flow documentationdocs/AUTH.md
Config / environment variablesdocs/CONFIG.md
Agent/AI operating guidancedocs/AGENTS.md
Feature module sourcesrc/data/<feature>/
API reference docsdocs/api/
Feature reference docsdocs/reference/
Feature documentationsrc/data/<feature>/<feature>.documentation.md
Release process + changelogdocs/releases/README.md
Docs automation rule mappingdocs/ai-ecosystem/documentation-types-and-rules.md

Feature Module Structure

Each feature in src/data/<feature>/ follows a consistent layout:

<feature>.model.ts # Mongoose schema/model
<feature>.validators.ts # Zod schemas and DTO validation
<feature>.repository.ts # Repository port (interface)
<feature>.repository.mongoose.ts # Repository adapter (Mongoose)
<feature>.service.ts # Business logic
<feature>.endpoint.ts # Express route handler
<feature>.admin.ts # AdminJS resource config
<feature>.command.ts # Discord/CLI command handler
<feature>.events.ts # Event bus handlers
<feature>.spec.ts # Unit tests (co-located)
<feature>.documentation.md # Feature documentation

Next Steps

  1. Read docs/ARCHITECTURE.md for the full layering rules.
  2. Read docs/CONTRIBUTING.md for commit conventions and review expectations.
  3. Read docs/releases/README.md for semantic-release and versioning flow.
  4. Pick a feature module (e.g. src/data/customer/) and trace the flow from endpoint → service → repository.
  5. Run the test suite to confirm your environment is working.

Pre-commit docs automation flow

Before each commit, Husky runs pnpm docs:pre-commit-update first:

  1. It inspects staged files and maps them to affected doc types using scripts/docs/documentation-types.rules.json.
  2. It auto-runs generators where available (e.g. AI Ecosystem reference).
  3. For AI-backed doc types, it either:
    • calls DOC_UPDATE_CMD automatically, or
    • writes scripts/docs/.pre-commit-doc-prompt.md and blocks commit until docs are updated/staged.