Local Development

This guide covers setting up FT Configs UI for local development.

Prerequisites

Required Software

Software Purpose Version

Node.js

JavaScript runtime

20.x (matches Docker build image)

npm

Package manager (bundled with Node.js)

10+

Git

Version control

2.x+

Use nvm to manage Node.js versions:

nvm install 20
nvm use 20

Required Backend

FT Configs UI requires a running ft-configs-service backend for all API operations (authentication, CRUD, import/export).

Ensure you have access to one of:

Clone and Install

git clone <repository-url> ft-configs-ui
cd ft-configs-ui

npm install

Run Development Server

npm run dev

The dev server starts on http://localhost:9002 with Vite HMR (Hot Module Replacement) via @vitejs/plugin-react. Port 9002 is set through vite --port 9002 in the dev npm script.

In development you also get @tanstack/router-devtools and @tanstack/react-query-devtools attached to the app for route and query introspection.

Backend Base URL

By default, the application uses the relative path /configs-service for API requests. The base URL is resolved at runtime by src/lib/api-url.ts in this order:

  1. window.RUNTIME_CONFIG.API_URL — populated by /runtime-config.js. In development, public/runtime-config.js ships a stub value (/configs-service) used by index.html.

  2. Fallback to the literal /configs-service when the runtime config is missing (e.g. during tests).

In development, the Vite dev server proxies that relative path to a real backend. From vite.config.ts:

To target a different backend URL during local development, edit public/runtime-config.js and/or the server.proxy entry in vite.config.ts.

Source Purpose Priority

window.RUNTIME_CONFIG.API_URL

Runtime backend URL loaded from /runtime-config.js

1 (highest)

Hard-coded fallback /configs-service

Used only when the runtime config is missing

2

Vite server.proxy rewrite

Dev-only proxy that forwards /configs-service to http://localhost:8082

3 (lowest)

Production Build (local)

npm run build
npm run preview

npm run build produces the static bundle in dist/. npm run preview serves that bundle locally through the Vite preview server for smoke-testing the production build.

Quality Gates

Run before committing or raising a PR:

# Lint (ESLint)
npm run lint

# Type checking (TypeScript)
npm run typecheck

# Unit tests (Vitest)
npm run test

# All gates at once
npm run lint && npm run typecheck && npm run test
npm run typecheck and npm run lint are the authoritative correctness gates — run them before pushing. Vitest does not currently collect coverage.

Running a Single Test

# Run a specific test file
npx vitest run src/lib/provision-portal-params.test.ts

# Run tests in watch mode
npx vitest src/lib/

Project Structure Overview

ft-configs-ui/
├── src/
│   ├── routes/                 # TanStack Router file-based routes
│   │   ├── __root.tsx          # Root route, Suspense + Outlet
│   │   ├── index.tsx           # HomePage
│   │   ├── _auth.tsx           # Public layout (login, register, change-password)
│   │   └── _protected.tsx      # Authenticated layout + auth guard
│   │       ├── acs/            # ACS configuration modules
│   │       ├── angular/        # Angular Console modules
│   │       ├── provision-portal/ # Provision Portal modules
│   │       ├── northbound.tsx  # Northbound API config
│   │       ├── service-api.tsx # Service API config
│   │       └── settings/       # Profile + admin (_admin.tsx guard)
│   ├── components/             # Feature components and shared UI
│   │   ├── ui/                 # shadcn/ui primitives
│   │   └── common/             # Reusable feature components (GenericImportExport, ...)
│   ├── api/                    # Centralised API layer (acs/, angular/, provision-portal/, settings/, ...)
│   ├── contexts/               # React contexts (auth, i18n)
│   ├── providers/              # QueryProvider, AdminRolesProvider
│   ├── hooks/                  # Custom React hooks
│   ├── lib/                    # axios, api-url, runtime-config, permissions, validation, error-utils
│   └── main.tsx                # App entry point
├── public/                     # Static assets, including dev runtime-config.js stub
│   └── runtime-config.js       # Dev stub for window.__RUNTIME_CONFIG__
├── locales/                    # i18n dictionaries (en.json, ru.json)
├── docs/                       # Antora documentation
├── docker/
│   ├── Dockerfile              # Full multi-stage build (Node builder → nginx runner)
│   ├── Dockerfile.simple       # CI image that consumes a pre-built dist/
│   ├── compose.yml      # Reference compose config
│   └── ops/
│       ├── entrypoint.sh       # Generates runtime-config.js, picks nginx template
│       ├── nginx.conf.template          # HTTPS + HTTP template
│       └── nginx-http-only.conf.template # HTTP-only template
├── index.html                  # App shell, loads /runtime-config.js before the bundle
├── vite.config.ts              # Vite + TanStack Router plugin + dev proxy
├── vitest.config.ts            # Test runner configuration
└── package.json                # Dependencies and scripts

Available npm Scripts

Script Description

npm run dev

Start Vite dev server with HMR on port 9002

npm run build

Production build; emits static assets to dist/

npm run preview

Preview the built dist/ through the Vite preview server

npm run lint

ESLint check (eslint 9 + typescript-eslint + React Hooks plugin)

npm run typecheck

TypeScript type checking (tsc --noEmit)

npm run test

Run Vitest unit tests

npm run knip

Check for unused exports and dependencies

Troubleshooting

npm install fails with permission errors

# Clear npm cache and retry
npm cache clean --force
rm -rf node_modules package-lock.json
npm install

Dev server starts but login fails

  • Verify ft-configs-service is running and accessible.

  • Check browser DevTools → Network tab for failed requests.

  • Ensure the backend CORS allow-list includes http://localhost:9002. The Vite dev proxy sets a custom Origin: http://localhost:9002 header on proxied requests so that the backend sees the UI’s dev origin.

Port 9002 already in use

# Find and kill the process
lsof -i :9002
kill <PID>

# Or run dev on a different port
npx vite --port 3001