Coding Rules
Naming Conventions
| Target | Convention | Example |
|---|---|---|
| TS variables and functions | camelCase | handleTableChange |
| React components | PascalCase | QuestionResponseChart |
| Component location | components/<category>/<Name>/index.tsx + index.scss |
components/SurveyCharts/QuestionResponseGrid/index.tsx |
| Page location | pages/<Name>/index.tsx + index.scss |
pages/Sample2/index.tsx |
| CSS classes | BEM | sample2-page__title / step-card__select |
| TS constants | UPPER_SNAKE_CASE | CATALOG_NAME / QUESTION_TYPE_FILTER |
| Python variables and functions | snake_case | fetch_all_questions |
| Pydantic models | PascalCase | QuestionDataResponse |
| API paths and query params | snake_case | /api/catalogs/{catalog_name}/.../all_questions?question_type= |
Formatter & Linter
# Format
npm run format # check only: npm run format:check
# Lint
npm run lint # auto-fix: npm run lint:fix
Config files: nodejs-fastapi-hello-world-app/.prettierrc.json, nodejs-fastapi-hello-world-app/eslint.config.js
Prettier is configured with no semicolons, single quotes, printWidth: 100, and trailingComma: es5. The repository-root .husky/pre-commit runs format:check and lint, so violations block the commit.
No formatter or linter is set up on the Python side.
PR & Review Guidelines
- Keep one PR to one purpose
- Write an explanation in the PR body so reviewers can follow it
- Self-review before requesting a review
- A PR that changes the frontend must include the
npm run buildoutput (backend/static/); otherwise production will not reflect it - A PR that changes the API must include the regenerated output of
npm run generate:client
Branch strategy
| Branch | Environment |
|---|---|
main |
dev |
stg |
stg |
prd |
prd |
Anti-patterns
- Hand-editing generated files โ
frontend/src/api/generated/**andfrontend/src/api/openapi.yamlare generated. To change them, edit the underlying Pydantic model orresponse_modeland runnpm run generate:client. - Interpolating identifiers into SQL โ catalog / schema / table must always go through
backend/sql/utils.fully_qualified_name(an^[A-Za-z0-9_]+$allowlist plus backticks). - Concatenating values into SQL โ always pass values through
?placeholders. - Putting business logic in routes โ keep
routes/thin: call the synchronous SQL layer viaasyncio.to_threadand map exceptions asValueError โ 400/RuntimeError โ 503/ everything else โ 500. - Hand-writing API clients โ use the orval-generated hooks.
- Overusing the
anytype โ use the generated types as they are. - Running
backend/generate_models_from_databricks.pyand walking away โ the script overwritesbackend/models/__init__.pywith only the generated models, so theapi/data_sqlimports must be restored by hand afterwards.