Skip to content

Latest commit

 

History

History
170 lines (135 loc) · 11.8 KB

File metadata and controls

170 lines (135 loc) · 11.8 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Critical Rules

  • No AI attribution in commits: Never add Co-Authored-By: trailers (e.g. Co-Authored-By: Claude ...) to commit messages.

Commands

# Development
npm start              # Dev server with proxy (http://localhost:4200)
npm run emulator       # Firebase emulator with persistence
npm run emulator:debug # Firebase emulator with debug output

# Build
npm run build          # Default build
npm run build:prod     # Production build against the tracked demo Firebase config
npm run build:deploy   # Production build against firebase-config.build.json (used by deploy/CI)
npm run build:docker   # Docker-specific build

# Code quality
npm run lint           # ESLint check
npm run lint:fix       # Auto-fix lint issues
npm run prettier:fix   # Format code

# Testing
npm test               # Vitest + happy-dom (via Angular's @angular/build:unit-test builder); specs use Jasmine-style describe/it
npm run test:scripts   # node:test suite for scripts/ (*.test.mjs)

# Deployment (one CLI: scripts/localess.mjs; these are aliases)
npm run localess -- <command>   # CLI entry point (setup | sync | deploy | check)
npm run localess:setup # Provision Firebase infrastructure and record the project markers
npm run localess:sync           # Regenerate local project files from remote state
npm run localess:deploy         # Build and deploy to a Localess-managed project
npm run localess:check          # Report what a project is still missing (--fix repairs the safe ones)

# Firebase Functions (from /functions directory)
cd functions && npm run build   # Compile TypeScript functions
cd functions && npm run serve   # Run functions locally

Architecture Overview

Localess is a Translation & Content Management System (CMS) built with Angular 21+, NgRx Signals, and Firebase.

Tech Stack

  • Frontend: Angular 21 (standalone components, signals, OnPush)
  • State: NgRx Signals (@ngrx/signals)
  • Backend: Firebase (Firestore, Auth, Storage, Functions, Hosting)
  • UI: Spartan/Helm component library (libs/ui/); Angular Material remains only as residual providers in app.config.ts
  • Styling: Tailwind CSS 4 + SCSS
  • Rich Text: TipTap editor
  • Functions: Express.js on Firebase Functions (region configurable, default europe-west6)

Application Structure

src/app/
├── core/          # Singleton services: error handler, HTTP interceptors, title service
├── shared/        # Cross-feature code
│   ├── models/    # TypeScript interfaces for all domain types
│   ├── services/  # 20 Firebase-backed domain services
│   ├── stores/    # 4 NgRx Signal stores (UserStore, SpaceStore, AppSettingsStore, LocalSettingsStore)
│   ├── guards/    # dirty-form.guard.ts (unsaved-changes guard); permission guards live in features-routing.module.ts
│   └── components/# Shared dialogs, table, paginator, tree, filter-toolbar, locale-icon, logo, etc. (toasts via NotificationService/Sonner)
├── features/      # Lazy-loaded feature routes
│   ├── admin/     # Space & user administration
│   └── spaces/    # Main workspace: contents, translations, schemas, assets, tasks, dashboard
├── auth/          # Auth: login (Email, Google, Microsoft), reset
└── app.config.ts  # Root provider configuration (Firebase, HTTP, etc.)

functions/src/     # Firebase Cloud Functions backend
libs/ui/           # 44+ reusable Spartan/Helm UI components

State Management

Four NgRx Signal stores initialized at app startup:

  • UserStore: Auth state, role, granular permissions (derived from Firebase custom claims)
  • SpaceStore: Selected workspace, content hierarchy, schemas, documents
  • AppSettingsStore: Global UI settings
  • LocalSettingsStore: User preferences (persisted to localStorage)

Routing & Guards

  • Root redirects to /features, authenticated via authGuard()
  • Feature routes use granular permission checks passed as authGuardPipe functions in features-routing.module.ts (e.g., hasPermissionTranslationRead, hasPermissionSchemaRead)
  • All features are lazy-loaded

Firebase Services Pattern

Domain services (in shared/services/) wrap Firestore CRUD operations. The Functions region is configurable (default europe-west6) and recorded on the GCP project as the localess-region label. The public REST API is exposed via the publicv1 Firebase Function rewrite at /api/v1/**.

Angular Code Conventions

These apply to all Angular code in this project (from .github/copilot-instructions.md):

  • Standalone components: Do NOT add standalone: true in @Component/@Directive/@Pipe decorators (it's the default)
  • Change detection: Always set changeDetection: ChangeDetectionStrategy.OnPush
  • Signals: Use signal() for local state, computed() for derived state; use update()/set(), never mutate()
  • Inputs/Outputs: Use input() and output() functions, not @Input()/@Output() decorators
  • Injection: Use inject() function, not constructor injection
  • Control flow: Use @if, @for, @switch — not *ngIf, *ngFor, *ngSwitch
  • CSS bindings: Use [class] bindings — not ngClass; use [style] bindings — not ngStyle
  • Host bindings: Put in the host object of @Component/@Directive — not @HostBinding/@HostListener
  • Forms: Reactive forms only (no template-driven)
  • Services: providedIn: 'root' for singletons
  • Images: Use NgOptimizedImage for static images
  • TypeScript: Strict mode, avoid any (use unknown), prefer type inference

Git Commits

Never create git commits unless the user explicitly asks. Do not commit after making changes, after a migration, or at the end of a task. Only commit when the user says "commit" or "push".

After Making Changes

After every code change, always run the following in order:

  1. npm run build — verify the project compiles without errors
  2. npm run lint:fix — auto-fix lint and prettier issues

Environment & Emulator Setup

Four Angular build configurations: development, production, docker, deploy. Firebase emulators support Firestore, Auth, Storage, and Functions locally. The proxy config (proxy.conf.cjs) forwards API calls during development.

There is no in-app setup wizard. To get an admin in the local emulator, create a user in the Auth emulator UI (http://localhost:4000) and set its custom claims to {"role":"admin"}. This is a one-time step per checkout — npm run emulator runs with --import=./firebase-export --export-on-exit=./firebase-export, so the account persists across restarts. Against a real project, use npm run localess:check -- --project <id> --fix instead.

Project Knowledge Base

Detailed documentation lives in docs/. Read the relevant file when working on the corresponding area:

Topic File Read when working on
Domain concepts (Space, Content, Schema, Translation, Asset), how localised values are stored docs/concepts.md Any new feature, onboarding, anything reading/writing a localised field
CDN caching, cv param, redirect logic, TTLs docs/cdn-caching.md functions/src/v1/cdn.ts, public API
V1 API — all endpoints, routers, middleware, token permissions docs/v1-functions-api.md Any work in functions/src/v1/
Publish flow & cache invalidation docs/publish-flow.md Content/translation publish, tasks
Webhooks — events, payload, HMAC signing, logging docs/webhooks.md functions/src/webhooks.ts, webhook-utils.ts, webhook UI
API token auth & permissions docs/auth-tokens.md Middleware, token management, public API
Firebase billing & cost optimization docs/billing.md Functions, Storage, cost analysis
Frontend architecture, routing, libs/ui docs/frontend-architecture.md Any Angular feature work
NgRx Signal stores, state patterns docs/frontend-state.md Adding/editing stores or components
User roles, route guards, UI permissions docs/frontend-permissions.md Auth, guards, user management
Spartan UI migration (checkbox, select, notifications) docs/spartan-ui-migration.md Migrating Material → Spartan, dialogs, forms
Shared components (ll-table, ll-paginator, ll-tree, ll-filter-toolbar) — index, required doc structure docs/components/README.md Anything in src/app/shared/components/; read before adding or changing one
Frontend testing — Vitest setup (test.isolate: true), centralized Firebase mocking pattern and why it stays centralized docs/testing.md Any new/edited *.spec.ts, src/test-setup.ts
Deployment & self-hosting
Deployment overview, prerequisites, automated vs manual docs/deployment/overview.md Any deployment/self-hosting question
Phase 1 — Firebase provisioning (npm run localess:setup) docs/deployment/firebase-setup.md scripts/localess.mjs, scripts/localess/, firebase.json auth block
Phase 2 — npm run localess:deploy, .env.<project-id>, LOCALESS_* build-time config docs/deployment/first-deploy.md Deploys, scripts/localess/commands/, scripts/localess/config.mjs, scripts/localess/generate.mjs, scripts/localess/defines.mjs, region wiring, login provider flags
Phase 3 — Pushing updates, targeted deploys, rollback docs/deployment/updates.md Redeploys, --only targets, upgrade steps
Health check (npm run localess:check), --fix, invoker bindings docs/deployment/check.md scripts/localess/checks.mjs, scripts/localess/commands/check.mjs, diagnosing a broken install
Feature modules — Admin
Admin overview (users, spaces, settings) docs/features/admin/overview.md Any admin feature
Admin → Users docs/features/admin/admin-users.md features/admin/users/
Admin → Spaces docs/features/admin/admin-spaces.md features/admin/spaces/
Admin → Settings docs/features/admin/admin-settings.md features/admin/settings/
Feature modules — Spaces
Spaces overview docs/features/spaces/overview.md Any space feature
Dashboard docs/features/spaces/dashboard.md features/spaces/dashboard/
Translations docs/features/spaces/translations.md features/spaces/translations/
Contents docs/features/spaces/contents.md features/spaces/contents/
Assets docs/features/spaces/assets.md features/spaces/assets/
Schemas docs/features/spaces/schemas.md features/spaces/schemas/
Tasks docs/features/spaces/tasks.md features/spaces/tasks/
Space Settings docs/features/spaces/settings.md features/spaces/settings/
Open API docs/features/spaces/open-api.md features/spaces/developers/open-api/
Feature modules — Me
Me / User profile docs/features/me.md features/me/