Contributing

This guide covers development workflow, code conventions, and contribution guidelines for FT Configs UI.

Getting Started

  1. Clone the repository and install dependencies with npm install — the repository README describes the local development setup.

  2. Verify the project builds: npm run lint && npm run typecheck && npm run test.

  3. Read the Architecture page to understand the codebase structure.

Development Workflow

  1. Create a feature branch from main.

  2. Install dependencies: npm install.

  3. Run the dev server: npm run dev (Vite, http://localhost:9002).

  4. Make your changes following the conventions below.

  5. Run quality gates before pushing:

    npm run lint
    npm run typecheck
    npm run test
    npm run build    # verifies the production Vite build (outputs to dist/)
  6. Raise a Pull Request with a clear description.

  7. For UI changes, include manual QA notes and screenshots.

Code Conventions

General

  • TypeScript only, functional React components.

  • Two-space indentation, single quotes, trailing commas.

  • @/ path alias for all imports (maps to ./src/*).

  • Tailwind CSS + shadcn/ui primitives for styling.

  • No any types — use proper type annotations.

File Organization

  • Routes (src/routes/**) — TanStack Router file-based routes. Route files are thin bridges — they call createFileRoute(…​) and render a feature component, passing isReadOnly and other props.

  • Feature components (src/components/<feature>/) — All UI logic for a feature.

  • API layer (src/api/<feature>/) — Typed API service functions grouped by module (e.g. src/api/acs/, src/api/angular/, src/api/provision-portal/, src/api/settings/).

  • Shared libs (src/lib/) — axios.ts, api-url.ts, runtime-config.ts, validation.ts, permissions.ts, error-utils.ts, etc.

  • Tests — Colocated as .test.ts / .test.tsx alongside the code they test.

Import Order

Group imports in this order:

  1. React and framework packages (react, @tanstack/react-router, @tanstack/react-query)

  2. Third-party libraries

  3. Internal @/ imports (components, hooks, lib, api)

  4. Relative imports

  5. Type-only imports (import type { …​ })

Naming

  • Components: PascalCase (e.g., FccEntryCard)

  • Hooks: useCamelCase (e.g., useErrorHandler)

  • Files: kebab-case (e.g., fcc-entry-card.tsx)

  • API functions: camelCase (e.g., getSnapshot)

i18n

All user-visible text must come from locale dictionaries, never hardcoded.

  • Dictionaries: locales/en.json and locales/ru.json

  • Access via useI18n() hook: t('key.path')

  • Always add keys to both locale files when creating UI text

  • Follow existing key naming conventions (e.g., moduleName.section.label)

Feature Module Pattern

When adding a new configuration module, split the code across three locations:

src/routes/_protected/<feature>.tsx       # Route file: createFileRoute(), renders <FeatureView isReadOnly={...} />
src/api/<feature>/
├── api.ts                                # Typed API service functions (use apiService from @/lib/axios)
└── api.test.ts                           # Unit tests for the API layer
src/components/<feature>/
└── FeatureView.tsx                       # Main feature component with all UI logic
  1. Define the API functions in src/api/<feature>/api.ts using apiService from @/lib/axios.

  2. Implement the feature component in src/components/<feature>/.

  3. Create the route in src/routes/_protected/<feature>.tsx — keep it thin: createFileRoute(…​) + render the feature component, passing isReadOnly from useAuth().

  4. Add locale keys for all UI text to both locales/en.json and locales/ru.json.

  5. If the module supports import/export, reuse GenericImportExport from src/components/common/ and configure it via a *-import-export-config.tsx file — do not reinvent the dry-run → apply flow.

Read CLAUDE.md and Architecture for the full module anatomy and the provider hierarchy.

Validation

  • Use React Hook Form + Zod for all forms.

  • Schema factories accept t() for localized messages: createMySchema(t).

  • Access via useLocalizedSchema() hook.

  • Field validators support isEditing mode for conditional uniqueness.

Error Handling

  • Use useErrorHandler().handleError(error, options) for all API error handling.

  • Never swallow errors silently — always show user feedback via toast.

  • Use extractUnifiedError(error, t) for consistent error classification.

Testing

  • Run tests with npm run test (Vitest).

  • Colocate test files as *.test.ts next to source files.

  • Test utility functions, validation schemas, and hooks.

  • See Testing Strategy for patterns and examples.

Pull Request Guidelines

  • Keep PRs focused — one feature or fix per PR.

  • Include a clear description of what changed and why.

  • For UI changes, add screenshots or screen recordings.

  • Ensure all quality gates pass (lint, typecheck, test).

  • Update locale files if any user-facing text was added or changed.

  • Update documentation if behaviour or architecture changed.