5.6 KiB
Repository Guidelines
Project Structure & Module Organization
Formbricks runs as a pnpm/turbo monorepo. apps/web is the Next.js product surface, with feature modules under app/ and modules/, assets in public/ and images/, and Playwright specs in apps/web/playwright/. apps/storybook renders reusable UI pieces for review. Shared logic lives in packages/*: database (Prisma schemas/migrations), surveys, js-core, types, plus linting and TypeScript presets (config-*). Deployment collateral is kept in docs/, docker/, and helm-chart/. Unit tests sit next to their source as *.test.ts or inside __tests__.
Build, Test & Development Commands
pnpm install— install workspace dependencies pinned bypnpm-lock.yaml.pnpm db:up/pnpm db:down— start/stop the Docker services backing the app.pnpm dev— run all app and worker dev servers in parallel via Turborepo.pnpm build— generate production builds for every package and app.pnpm lint— apply the shared ESLint rules across the workspace.pnpm test/pnpm test:coverage— execute Vitest suites with optional coverage.pnpm test:e2e— launch the Playwright browser regression suite.pnpm db:migrate:dev— apply Prisma migrations against the dev database.
Coding Style & Naming Conventions
TypeScript, React, and Prisma are the primary languages. Use the shared ESLint presets (@formbricks/eslint-config) and Prettier preset (110-char width, semicolons, double quotes, sorted import groups). Two-space indentation is standard; prefer PascalCase for React components and folders under modules/, camelCase for functions/variables, and SCREAMING_SNAKE_CASE only for constants. When adding mocks, place them inside __mocks__ so import ordering stays stable.
We are using SonarQube to identify code smells and security hotspots.
Architecture & Patterns
- Next.js app router lives in
apps/web/appwith route groups like(app)and(auth). Services live inapps/web/lib, feature modules inapps/web/modules. - Server actions wrap service calls and return
{ data }or{ error }consistently. - Context providers should guard against missing provider usage and use cleanup patterns that snapshot refs inside
useEffectto avoid React hooks warnings
Caching
- Use React
cache()for request-level dedupe andcache.withCache()or explicit Redis for expensive data. - Do not use Next.js
unstable_cache(). - Always use
createCacheKey.*utilities for cache keys.
i18n (Internationalization)
- All user-facing text must use the
t()function fromreact-i18next. - Key naming: use lowercase with dots for nesting (e.g.,
common.welcome). - Translations are in
apps/web/locales/. Default isen-US.json. - Lingo.dev is automatically translating strings from en-US into other languages on commit. Run
pnpm i18nto generate missing translations and validate keys.
Database & Prisma Performance
- Multi-tenancy: All data must be scoped by Organization or Environment.
- Soft Deletion: Check for
isActiveordeletedAtfields; use proper filtering. - Never use
skip/offsetwithprisma.response.count(); only usewhere. - Separate count and data queries and run in parallel (
Promise.all). - Prefer cursor pagination for large datasets.
- When filtering by
createdAt, include indexed fields (e.g.,surveyId+createdAt).
Testing Guidelines
Prefer Vitest with Testing Library for logic in .ts files, keeping specs colocated with the code they exercise (utility.test.ts). Do not write tests for .tsx files—React components are covered by Playwright E2E tests instead. Mock network and storage boundaries through helpers from @formbricks/*. Run pnpm test before opening a PR and pnpm test:coverage when touching critical flows; keep coverage from regressing. End-to-end scenarios belong in apps/web/playwright, using descriptive filenames (billing.spec.ts) and tagging slow suites with @slow when necessary.
Documentation (apps/docs)
- Add frontmatter with
title,description, andiconat the top of the MDX file. - Do not start with an H1; use Camel Case headings (only capitalize the feature name).
- Use Mintlify components for steps and callouts.
- If Enterprise-only, add the Enterprise note block described in docs.
Storybook
- Stories live in
stories.tsxin the component folder and import from"./index". - Use
@storybook/react-viteand organize argTypes intoBehavior,Appearance,Content. - Include Default, Disabled (if supported), WithIcon (if supported), all variants, and edge cases.
GitHub Actions
- Always set minimal
permissionsforGITHUB_TOKEN. - On
ubuntu-latest, addstep-security/harden-runneras the first step.
Quality Checklist
- Keep code DRY and small; remove dead code and unused imports.
- Follow React hooks rules, keep effects focused, and avoid unnecessary
useMemo/useCallback. - Prefer type inference, avoid
any, and use shared types from@formbricks/types. - Keep components focused, avoid deep nesting, and ensure basic accessibility.
Commit & Pull Request Guidelines
Commits follow a lightweight Conventional Commit format (fix:, chore:, feat:) and usually append the PR number, e.g. fix: update OpenAPI schema (#6617). Keep commits scoped and lint-clean. Pull requests should outline the problem, summarize the solution, and link to issues or product specs. Attach screenshots or gifs for UI-facing work, list any migrations or env changes, and paste the output of relevant commands (pnpm test, pnpm lint, pnpm db:migrate:dev) so reviewers can verify readiness.