Coding & Design Guidelines
These guidelines keep every service aligned. Keep changes focused. Mention any deviation in your pull request. Raise follow-up issues when you discover gaps.
Contributor checklist
- Run the formatter and linter for the area you touched. Examples:
npm run -w webapp format,npm run lint:server. - Smoke-test the critical scripts.
npm run -w webapp buildmust pass. If you changed migrations, runnpm run db:generate-erd-docs. - Update Chromatic snapshots when you change UI components.
- Regenerate clients and documentation when you change an API contract.
- Rerun the quality gates that match your changes:
npm run lint,npm run generate:api, or./mvnw -pl server/application-server test. - Document what you verified in the pull request template. Link failing checks to tickets if you must defer.
Webapp (/webapp)
Platform overview
- React 19.1 with Vite 6 and
@vitejs/plugin-react. babel-plugin-react-compilerruns first invite.config.js. Leave it there so the compiler stays active.- Routing uses TanStack Router file routes in
src/routes/**with the generatedrouteTree.gen.ts. - TanStack Query v5 is initialised in
src/integrations/tanstack-query/root-provider.tsx. OpenAPI helpers live insrc/api/@tanstack/react-query.gen.ts. - Global state lives in Zustand stores under
src/stores/**. - Tailwind CSS 4 powers styling. Tokens sit in
src/styles.css. shadcn/ui primitives live insrc/components/ui/**. - Storybook 8, Chromatic, Vitest, and Biome cover tooling.
Building features
- Create routes with
createFileRoute. Route modules handle auth gating (seesrc/routes/_authenticated.tsx), loader logic, and orchestration. - Keep presentational components in
src/components/**. They should take props, stay pure, and avoid side effects. - Fetch data by spreading generated
...Options()helpers intouseQueryoruseMutation. The helpers provide typing, query keys, and retry defaults.useDocumentArtifact.tsshows the pattern. - Invalidate caches with the generated
...QueryKey()helpers or the same keys passed touseQuery. Use optimistic updates only when the UI must respond instantly, such as mentor chat streaming. - Subscribe to Zustand stores with selectors (
useDocumentsStore((state) => state.documents[id])). Keep store actions pure. - Respect React Compiler requirements. No conditional hooks. No prop mutation. Check React DevTools for the
Memo ✨badge or inspect builds forreact/compiler-runtimewhen you need assurance. Use'use no memo'only while debugging. - Stay inside the Tailwind token scale. Reach for shadcn/ui primitives before adding new component libraries. Use
@applysparingly and only for wrapper primitives you reuse widely. - Co-locate
*.stories.tsxfiles. Show default, loading, empty, and error states with realistic data. Runnpm run chromatic:ciwhenever stories change. - Push heavy routes behind
React.lazyand Suspense. Virtualise long lists with@tanstack/react-virtual. Defer analytics work to effects that run after paint.
Quality gates
- Install dependencies with
npm installat the repo root so optional binaries resolve. - Run
npm run -w webapp checkandnpm run -w webapp buildbefore opening a pull request. - Execute Vitest suites with
npm run -w webapp test. Add unit tests beside the feature you touched. - Keep Storybook stories in sync with design. Launch
npm run -w webapp storybookwhen pairing with design reviews. - Validate bundle impact by checking the Vite build stats when you add large libraries.
Spring Boot application server (/server/application-server)
Structure
- Feature packages live under
gitprovider/,leaderboard/,mentor/,notification/,syncing/, andworkspace/. Shared wiring sits inconfig/andcore/. - Controllers return DTOs located near the controller.
LeaderboardEntryDTOis the reference example. - Repositories return
Optional<T>instead ofnull. - Services use field injection with
@Autowired, as inLeaderboardService. If a service depends on many collaborators, split the responsibility. - Set up loggers with
LoggerFactory.getLogger. Use structured log messages. - Annotate the smallest unit of write work with
@Transactional.
Coding habits
- Use Java 21 features where they simplify code. Records, pattern matching, and sealed hierarchies improve readability.
- Keep controllers thin. Push orchestration into services and prefer constructor helpers over static util classes.
- Expose dedicated DTO mappers in the package instead of sprinkling conversion logic across layers.
- Treat
Optionalas a signal for missing data. Avoid returningnullfrom repository methods.
Safe workflows
- Configuration overrides stay in
application-*.yml. Do not commitapplication-local.yml. - Share long-lived infrastructure in tests. Lean on Testcontainers and GitHub fixtures where possible.
- After updating Liquibase migrations, regenerate the REST client with
npm run generate:apiand rerunnpm run db:generate-erd-docs. - Run the modular test suites with
./mvnw verify. The build uses ArchUnit checks to enforce package boundaries. - Prefer integration tests that extend
AbstractSpringIntegrationTestwhen you touch persistence logic.
Intelligence service (/server/intelligence-service)
- LangGraph orchestration resides in
app/mentor/run.py. Nodes live inapp/mentor/nodes/**. Shared state types live inapp/mentor/state.py. - Regenerate SQLAlchemy models by running
npm run db:generate-models:intelligence-service. Never editapp/db/models_gen.pyby hand. - Keep FastAPI routers thin. Push business logic into services or nodes. Define request and response models in
app/models/**. - Load configuration via
app/settings.py. Secrets belong in.env, which you create from.env.example. - Manage dependencies with Poetry. Run
poetry install --no-rootonce and reuse the virtual environment viapoetry shell. - Format with
poetry run black .and lint withpoetry run flake8 .. Runpoetry run mypybefore pushing when you add new types. - Add or update service tests with
pytestunderapp/tests/**. Usehttpx.AsyncClientto exercise FastAPI routers.
Webhook ingest service (/server/webhook-ingest)
- The service listens for GitHub events and publishes to NATS JetStream.
- Configure secrets through environment variables defined in
.env.example. - Format and lint with Poetry (
poetry run black .,poetry run flake8 .).
Docs site (/docs)
- Docusaurus 3 powers the documentation. Install dependencies with
npm installand runnpm run startto preview. - Keep front matter fields (
id,title,sidebar_position) unique. Updatesidebars.*.tswhen adding new pages. - Use MDX components from
docs/src/components/**to keep styling consistent. - Run
npm run buildbefore committing structural changes to confirm the static export succeeds.
Database and migrations
- Liquibase changesets live in
server/application-server/src/main/resources/config/liquibase. - Prefer
renameColumnormodifyDataTypewhen evolving schemas so data survives deployments. - Add indexes before backfilling large tables. Profile long migrations locally.
- After schema updates, regenerate the ERD, refresh the FastAPI models, and run backend tests that touch the affected tables.
Observability and security
- Sentry is configured in both the webapp and the application server. Capture exceptions with context tags instead of console logs.
- PostHog records product analytics. Gate new events behind environment checks so tests stay deterministic.
- Store shared secrets in LastPass and load them via
.envor the respectiveapplication-*.ymlfiles. Never commit real secrets. - Rotate API keys when you onboard new external services. Document the process in the runbooks under
docs/admin. - Sanitise logged user data. Log IDs rather than emails.
Performance reminders
- Batch network calls and paginate large results.
- Cache expensive computations when you reuse them. TanStack Query handles client caching. Use memoised services or projections on the backend.
- Measure before tuning. Add logging or metrics when you touch critical latency paths.
- Profile React work with the DevTools profiler and Chrome Performance panel. Profile Java code with JFR and async-profiler.
When unsure
Record trade-offs in your pull request. Ask for a second review on risky work. Suggest improvements to this page when you find a better pattern.