Skip to content

Latest commit

Β 

History

History
307 lines (247 loc) Β· 10.6 KB

File metadata and controls

307 lines (247 loc) Β· 10.6 KB

HMCTS Express Monorepo Template

Production-ready Node.js starter with cloud-native capabilities for building HMCTS digital services using Express.js, TypeScript and GOV.UK Design System.

πŸš€ Overview

This template provides everything you need to create accessible, secure, and scalable applications that meet GDS and HMCTS standards.

πŸ“‹ Using This Template

This monorepo will contain all your apps, libraries, and infrastructure for your HMCTS service.

Naming Convention

  • Team name: Your HMCTS service (e.g., CaTH, Divorce, Civil)
  • Product name: The specific product/service (e.g., Possessions, Money-Claims)
  • If the product encompasses the whole service, use "Service"

Examples:

  • Team: CaTH, Product: Service β†’ cath-service
  • Team: Civil, Product: Money-Claims β†’ civil-money-claims

Setup Steps

  1. Run the initialization script:
./.github/scripts/init.sh

The script will:

  • Prompt for your team name (e.g., CaTH)
  • Prompt for your product name (e.g., Service)
  • Replace all template values throughout the codebase
  • Rebuild the yarn lockfile
  • Run tests to verify everything works
  • Remove itself after completion
  1. Review and commit:
git add .
git commit -m "Initialize from template"
git push

✨ Key Features

Cloud Native Platform

  • Health Checks: Configurable health endpoints with readiness and liveness probes for Kubernetes deployments
  • Properties Volume: Secure configuration management through mounted volumes with automatic environment variable injection
  • Azure Integration: Built-in support for Azure Key Vault secrets management and properties volume mounting
  • Application Insights: Comprehensive monitoring with Azure Application Insights including custom metrics and distributed tracing

Express GOV.UK Starter for frontends

  • GOV.UK Design System: Fully integrated GOV.UK Frontend with Nunjucks templates and automatic asset compilation
  • Internationalization: Welsh language support with locale middleware and translation management system
  • Security Headers: Pre-configured Helmet.js with CSP, HSTS, and nonce-based script protection
  • Asset Pipeline: Vite-powered asset compilation with SCSS support and production optimization
  • Cookie Management: Built-in support for cookie consent
  • Session Handling: Session management using Redis or Postgres

Simple Router

A lightweight file-system router for Express applications, inspired by Next.js routing.

  • File-based Routing: Maps files in directories to Express routes automatically
  • Dynamic Parameters: Support for dynamic route segments using [param] syntax (e.g., /users/[id])
  • HTTP Method Exports: Export handlers for any HTTP method (GET, POST, PUT, DELETE, etc.)
  • Middleware Support: Single handlers or arrays of middleware for complex request pipelines
  • Multiple Mount Points: Mount different directories with different URL prefixes
  • Zero Dependencies: Lightweight implementation with no external dependencies

Monorepo Architecture

  • Single repository for multiple applications (e.g. multiple frontends sharing common code, APIs or libraries)
  • Workspace-based structure with Yarn workspaces
  • Shared libraries for common functionality
  • Testing with Vitest and Playwright
  • Helm charts for Kubernetes deployment
  • GitHub Actions CI/CD pipeline
  • Biome for fast linting and formatting

Project Structure

expressjs-monorepo-template/
β”œβ”€β”€ apps/                       # Deployable applications
β”‚   β”œβ”€β”€ api/                    # REST API server (Express 5.x)
β”‚   β”œβ”€β”€ crons/                  # Cron jobs
β”‚   β”œβ”€β”€ postgres/               # Migration runner + Prisma S
β”‚   └── web/                    # Web frontend (Express 5.x + Nunjucks)
β”œβ”€β”€ libs/                       # Modular packages (explicitly registered)
β”‚   β”œβ”€β”€ cloud-native-platform/  # Cloud Native Platform features
β”‚   β”œβ”€β”€ express-gov-uk-starter/ # GOV.UK Frontend integration
β”‚   β”œβ”€β”€ postgres-prisma/        # Database client (Prisma)
β”‚   β”œβ”€β”€ simple-router/          # Simple Router features
β”‚   β”œβ”€β”€ footer-pages/           # Module with example footer pages
β”‚   └── [your-module]/          # Your feature modules
β”‚       └── src/
β”‚           β”œβ”€β”€ pages/          # Page routes (imported in web app)
β”‚           β”œβ”€β”€ routes/         # API routes (imported in API app)
β”‚           β”œβ”€β”€ prisma/         # Prisma schema
β”‚           β”œβ”€β”€ locales/        # Translations (loaded by govuk-starter)
β”‚           └── assets/         # Module assets (compiled by vite)
β”œβ”€β”€ e2e-tests/                  # End-to-end tests (Playwright)
β”œβ”€β”€ docs/                       # Documentation and ADRs
β”œβ”€β”€ helm/                       # Helm charts for Kubernetes deployment
└── package.json                # Root configuration

🏁 Getting Started

Prerequisites

  • Node.js 22+
  • Yarn 4+
  • Docker (optional, for PostgreSQL)

Quick Setup

# Install dependencies
yarn install

# Run development server
yarn dev

Services

Service URL Description
Web Application http://localhost:3000 Main web interface with GOV.UK styling
API Server http://localhost:3001 REST API backend
Prisma Studio http://localhost:5555 Database management UI

πŸ“¦ Development

Available Commands

# Development
yarn dev                        # Start all services concurrently

# Testing
yarn test                       # Run all tests across workspaces
yarn test:e2e                   # Playwright E2E tests
yarn test:coverage              # Generate coverage report

# Code Quality
yarn lint:fix                    # Run Biome linter
yarn format                     # Format code with Biome

# Database Operations
yarn db:migrate                 # Apply migrations  
yarn db:migrate:dev             # Auto apply migrations, add new migrations if necessary
yarn db:generate                # Generate the Prisma client
yarn db:studio                  # Open Prisma Studio
yarn db:drop                    # Drop all tables and reset the database

Creating a New Feature Module

  1. Create module structure:
mkdir -p libs/my-feature/src/pages      # Page controllers and templates
mkdir -p libs/my-feature/src/locales    # Translation files (optional)
mkdir -p libs/my-feature/src/assets/css # Module styles (optional)
mkdir -p libs/my-feature/src/assets/js  # Module scripts (optional)
cd libs/my-feature
  1. Initialize package.json:
{
  "name": "@hmcts/my-feature",
  "version": "1.0.0",
  "type": "module",
  "exports": {
    ".": {
      "production": "./dist/index.js",
      "default": "./src/index.ts"
    },
    "./config": {
      "production": "./dist/config.js",
      "default": "./src/config.ts"
    }
  },
  "scripts": {
    "build": "tsc && yarn build:nunjucks",
    "build:nunjucks": "mkdir -p dist/pages && cd src/pages && find . -name '*.njk' -exec sh -c 'mkdir -p ../../dist/pages/$(dirname {}) && cp {} ../../dist/pages/{}' \\;",
    "dev": "tsc --watch",
    "test": "vitest run",
    "test:watch": "vitest watch",
    "format": "biome format --write .",
    "lint": "biome check .",
    "lint:fix": "biome check --write ."
  },
  "peerDependencies": {
    "express": "^5.1.0"
  }
}

Note: The build:nunjucks script is required if your module contains Nunjucks templates.

  1. Create tsconfig.json:
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["**/*.test.ts", "**/*.spec.ts", "dist", "node_modules", "src/assets/"]
}
  1. Register module in root tsconfig.json:
{
  "compilerOptions": {
    "paths": {
      // ... existing paths ...
      "@hmcts/my-feature": ["libs/my-feature/src"]
    }
  }
}
  1. Create src/config.ts for module configuration:
import path from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Module configuration for app registration
export const pageRoutes = { path: path.join(__dirname, "pages") };
export const apiRoutes = { path: path.join(__dirname, "routes") };
export const prismaSchemas = path.join(__dirname, "../prisma");
export const assets = path.join(__dirname, "assets/");

Create src/index.ts for business logic exports:

// Business logic exports only
export * from "./my-feature/service.js";
export * from "./my-feature/validation.js";

IMPORTANT: Config exports (pageRoutes, apiRoutes, prismaSchemas, assets) must be in a separate config.ts file to avoid circular dependencies during Prisma client generation. Apps import config using the /config path (e.g., @hmcts/my-feature/config).

  1. Register module in applications:
// apps/web/src/app.ts
import { pageRoutes as myFeaturePages } from "@hmcts/my-feature/config";

app.use(await createGovukFrontend(app, [myFeaturePages.path], { /* options */ }));
app.use(await createSimpleRouter(myFeaturePages));

// apps/web/vite.config.ts
import { assets as myFeatureAssets } from "@hmcts/my-feature/config";
const baseConfig = createBaseViteConfig([
  path.join(__dirname, "src"),
  myFeatureAssets
]);

// apps/api/src/app.ts
import { apiRoutes as myFeatureRoutes } from "@hmcts/my-feature/config";
app.use(await createSimpleRouter(myFeatureRoutes));

// libs/postgres-prisma/src/schema-discovery.ts
import { prismaSchemas as myFeatureSchemas } from "@hmcts/my-feature/config";
const schemaPaths = [myFeatureSchemas, /* other schemas */];
  • Add dependency to relevant app package.json files: "@hmcts/my-feature": "workspace:*"

πŸ§ͺ Testing Strategy

Type Tool Location Purpose
Unit Tests Vitest Co-located *.test.ts Business logic validation
E2E Tests Playwright e2e-tests/ User journey validation
Accessibility Tests Axe-core + Playwright e2e-tests/ WCAG 2.1 AA compliance
# Run specific test suites
yarn test                   # Unit tests
yarn test:e2e               # E2E tests
yarn test:coverage          # Coverage report

Security

The GitHub Action pipelines contain a number of security checks, including:

  • Dependency Scanning: Automatically scans for vulnerabilities in dependencies
  • SonarQube: SAST analysis for code quality and security
  • Claude Security Scans: Claude AI-powered security scans for code vulnerabilities

License

MIT