
Technical specification
Built like infrastructure, not like a brochure
An edge-rendered, content-modelled, zero-lock-in platform with federated identity, a hardened supply chain and measurable service objectives — specified in full so it can be assessed, audited and inherited.
01
Reference architecture
Composable, layered and independently replaceable. No component is a single point of lock-in.
VISITOR / LOCAL AUTHORITY OFFICER
│ TLS 1.3 · HSTS preload · IPv6
▼
┌──────────────────────────────────────────────────────────────┐
│ EDGE · global CDN + WAF + bot management + rate limiting │
│ · strict CSP, COOP/COEP, Permissions-Policy injected │
└──────────────┬───────────────────────────────┬───────────────┘
│ cached HTML/ISR │ /api/*
▼ ▼
┌───────────────────────────┐ ┌────────────────────────────┐
│ PRESENTATION │ │ APPLICATION │
│ React 19 · TanStack Start │ │ typed server functions │
│ SSR + streaming + islands │ │ zod-validated boundaries │
│ design tokens (OKLCH) │ │ per-route authz middleware │
└────────┬──────────────────┘ └──────┬─────────────────────┘
│ CMS adapter interface │
▼ ▼
┌───────────────────────────┐ ┌────────────────────────────┐
│ CONTENT headless CMS │ │ IDENTITY Microsoft Entra │
│ versioned schema, preview │ │ OIDC · MFA · Conditional │
│ webhook → incremental │ │ Access · SCIM · RBAC │
│ revalidation │ └────────────────────────────┘
└────────┬──────────────────┘
▼
┌───────────────────────────┐ ┌────────────────────────────┐
│ SEARCH faceted index │ │ DATA Postgres (EU) · │
│ PUBLIC index ┃ PORTAL │ │ row-level security · │
│ physically separated │ │ PITR backups · audit log │
└───────────────────────────┘ └────────────────────────────┘
OBSERVABILITY RUM · Core Web Vitals · structured logs ·
traces · uptime · error budgets · alerting- Rendering
- Server-side rendered at the edge with streaming; static generation for stable content, incremental revalidation on CMS webhook. No client-side-only pages, so every page is crawlable and works without JavaScript for core content.
- Runtime
- V8 isolates at global edge locations — cold-start free, region-pinned data residency in the EU.
- Framework
- React 19 + TanStack Start + Vite 7. Standard, widely-skilled, no proprietary runtime.
- Type safety
- End-to-end TypeScript in strict mode; runtime schema validation with Zod on every server boundary; generated types from the CMS schema and database.
- State & data
- TanStack Query with route-level prefetch, stale-while-revalidate caching and suspense boundaries.
- Design system
- OKLCH token layer → Tailwind theme → component variants. Themeable, contrast-checked, dark mode native.
02
Content platform & editorial model
Structured content, not pages. Editors publish once; every surface updates.
Adapter interface
All content access passes through a single typed adapter. Swapping CMS vendor is a driver implementation, not a rebuild — the exit strategy is a design feature.
Modelled entities
Region, Local Authority, Climate Action Plan, Project, Case Study, Funding Scheme, Event, Recording, Resource, Person, Glossary Term — related by reference, not by URL nesting.
Governance workflow
Draft → review → approve → schedule → publish, with named approvers, full version history, one-click rollback and an immutable audit trail per field.
Quality gates in the CMS
Alt text, meta description, region and theme tags are required fields. Publishing is blocked until accessibility and metadata rules pass.
Preview parity
Authenticated draft preview renders the production component tree — what editors see is what ships.
Localisation ready
Locale-aware routing and field-level translation from day one, so Irish-language obligations can be met without re-platforming.
03
Search & geographic discovery
Replacing paged lists with a typed, faceted index.
- Index topology
- Two physically separate indexes. The public index never contains portal content; the portal index is reachable only through an authenticated server function. A CI test asserts separation on every build.
- Facets
- Region, local authority, theme, content type, funding stream, year, format. Facet counts computed server-side; URL-addressable so any filtered view is shareable and bookmarkable.
- Relevance
- Typo tolerance, synonym dictionary for climate terminology, Irish place-name and fada handling, weighted title/summary/body fields, curated pinned results for priority queries.
- Zero-result handling
- Query logging (anonymised) feeds an editorial report so gaps in the content estate are visible and fixable.
- Geographic model
- Region → Local Authority → Climate Action Plan → Projects → Case Studies traversable in both directions from any node, driven by metadata rather than navigation depth.
04
Performance budgets
Budgets are enforced in CI, not aspirations in a document.
LCP
< 1.8 s
75th percentile, 4G mobile
INP
< 200 ms
field data, all routes
CLS
< 0.05
reserved media dimensions
JS shipped
< 140 KB
gzip, per route
- Self-hosted variable fonts, subset and preloaded — no third-party font origin, no layout shift.
- AVIF/WebP responsive sources with explicit dimensions and priority hints on the LCP image.
- Route-level code splitting; zero blocking third-party script; no tag manager on the critical path.
- Lighthouse CI and bundle-size budgets fail the pipeline on regression, with results published to each pull request.
05
Delivery pipeline
Every change is reviewed, tested, scanned, attested and reversible.
- 01Branch & reviewTrunk-based with short-lived branches, protected main, mandatory review, signed commits, CODEOWNERS.
- 02Static analysisTypeScript strict, ESLint, Prettier, dead-code and circular-dependency checks.
- 03Security scanningSAST, dependency SCA with license policy, secret scanning with push protection, IaC scanning, container/base-image scanning.
- 04Automated testsUnit, component, contract tests against the CMS adapter, and Playwright end-to-end journeys including portal auth flows.
- 05Accessibility gateaxe-core across all key templates plus keyboard-only and screen-reader regression suites; violations fail the build.
- 06Performance gateLighthouse CI budgets and bundle analysis.
- 07Build provenanceReproducible builds, SBOM (CycloneDX) generated and signed, artefact attestation retained.
- 08DeployImmutable artefacts promoted through preview → staging → production; atomic release with instant rollback; database migrations forward-only and reviewed.
- 09VerifyPost-deploy smoke tests, synthetic monitoring, automatic rollback on error-budget burn.
06
Branching model & change workflow
A single, documented path from an idea to production — auditable at every hop.
ISSUE (ADR required for architectural change)
│
├─▶ feature/<ticket>-<slug> short-lived, < 3 days, signed commits
│ │ push → CI: typecheck · lint · unit · a11y · SAST · SCA · secrets
│ │ ephemeral PREVIEW deploy per pull request (unique URL, noindex)
│ ▼
├─▶ PULL REQUEST CODEOWNERS review · 1+ approval · all checks green
│ │ content editors review the preview URL before merge
│ ▼
├─▶ main protected · linear history · no direct pushes · no force-push
│ │ auto-deploy → STAGING (production parity, seeded content)
│ │ Playwright E2E · Lighthouse budgets · axe full sweep · link check
│ ▼
├─▶ RELEASE tagged, immutable artefact · SBOM signed · attestation stored
│ │ manual approval gate (named approver) for PRODUCTION
│ ▼
└─▶ production atomic switch · smoke tests · synthetic probes
│ fail → automatic rollback to previous artefact (< 60 s)
└─▶ hotfix/<ticket> branches from the release tag, same gates
DATABASE forward-only reviewed migrations, applied before the app switch,
always backward-compatible for one release (expand → migrate → contract)
CONTENT independent of code releases; CMS publish triggers incremental
revalidation only — no rebuild, no deploy, no supplier involvement- Branch protection
- main requires review, green checks, signed commits and linear history. Force-push and deletion disabled. CODEOWNERS enforces specialist review for identity, redirect and security-header changes.
- Change classes
- Content (editor, no deploy) · Configuration (reviewed PR) · Code (full pipeline) · Emergency (hotfix with retrospective ADR within 48 hours). Each class has a defined approver.
- Traceability
- Ticket → branch → commit → PR → artefact → deployment record → release note. Any line in production can be traced to the review that approved it.
- Definition of done
- Accessible, tested, documented, observable, reversible. A change that cannot be rolled back is not ready to ship.
- Cadence
- Two-week iterations with a demo to CARO at each stage gate; releases as often as ready, typically weekly, with a documented freeze around migration cutover.
07
Environments & infrastructure design
Four isolated environments, defined as code, with no shared credentials and no manual server administration.
LOCAL PREVIEW (per PR) STAGING PRODUCTION
───── ──────────────── ─────── ──────────
seeded data anonymised data anonymised copy live data (EU)
no secrets scoped test creds scoped test creds vault, short-lived
no indexing noindex + basic auth noindex indexed, canonical
restore rehearsal PITR + replication
PRODUCTION TOPOLOGY
┌──────────── EU edge network (anycast) ─────────────┐
│ WAF · bot management · rate limits · DDoS absorb │
│ TLS 1.3 · HSTS preload · security headers injected │
└───────┬────────────────────────────────────┬───────┘
│ static + ISR HTML, images (AVIF) │ /api/*
▼ ▼
edge cache (regional POPs) server functions
│ │
│ ┌────────────┼──────────────┐
▼ ▼ ▼ ▼
object storage headless CMS Postgres (EU) Entra ID
assets, documents + webhooks RLS · PITR OIDC · MFA
│
audit log (append-only, hash-chained)
IaC: every resource — DNS, WAF rules, headers, environments, alerts —
declared in version-controlled Terraform. No console-only configuration.- Infrastructure as code
- Terraform in the same repository, planned in CI and applied only through a protected pipeline with OIDC-federated, short-lived credentials. Drift detection runs nightly.
- Secrets
- Managed vault with per-environment scoping, automatic rotation and audited access. No secret is ever present in the repository, in client bundles or in build logs.
- Network & isolation
- No public database endpoint; data reachable only from the application tier. Portal traffic is separated at the routing layer and never shares an index or cache key with public content.
- Scaling & cost
- Edge isolates scale to demand with no idle servers to patch; cost is predictable and reported. Traffic spikes around funding announcements are absorbed at the cache.
- Domain & DNS
- DNSSEC, CAA pinning and DMARC enforcement, held in the authority's own accounts. The supplier operates them; the authority owns them.
- Patching
- Base images and dependencies patched on an SLA (critical within 24 hours), evidenced in the monthly service report.
08
Observability, resilience & disaster recovery
Service objectives that can be measured and reported monthly.
- Availability target
- 99.95% monthly for public pages; 99.9% for the authenticated portal. Measured by independent synthetic monitoring from Irish and EU probes.
- RPO / RTO
- Recovery point 15 minutes (continuous database PITR, content versioned in CMS and Git); recovery time 60 minutes with rehearsed runbooks and quarterly restore tests.
- Backups
- Automated encrypted backups with cross-region replication and immutable retention; restores tested on a schedule and evidenced in the service report.
- Monitoring
- Real-user monitoring for Core Web Vitals, structured JSON logs with correlation IDs, distributed tracing, uptime checks, error tracking with release tagging.
- Alerting & support
- Severity-based alert routing to an on-call rota; documented P1–P4 response and resolution targets; monthly service, security-patch and accessibility report.
- Change management
- Maintenance windows, release notes, and a change advisory record for anything affecting authentication, data or redirects.
09
Standards & compliance coverage
Explicit mapping between obligation and implementation.
| Standard | How it is met |
|---|---|
| WCAG 2.2 AA / EN 301 549 | Designed in, gated in CI, independently audited before launch, accessibility statement published with a named contact and feedback route. |
| S.I. 358/2020 (Web Accessibility Directive) | Conformance statement, feedback mechanism and enforcement contact published and kept current. |
| GDPR / ePrivacy (S.I. 336/2011) | Consent-first tagging, no session replay, data minimisation, EU data residency, DPIA, ROPA and retention schedule delivered as artefacts. |
| NIS2 readiness | Asset inventory, vulnerability management, logging, incident reporting procedure and supply-chain assurance documented for the contracting authority. |
| OWASP ASVS L2 / Top 10 | Controls mapped per requirement; verified by independent penetration test before go-live and annually thereafter. |
| ISO 27001-aligned operations | Documented access control, change management, backup, incident and supplier-management procedures. |
| Public sector spelling of the exit | Standard Git repository, standard toolchain, documented runbooks, full IP and content handover — operable by any competent supplier. |
10
Ownership, portability & exit
The contracting authority owns everything, at every point in the contract.
Source ownership
Code in the authority's own GitHub organisation from day one, with full history, branch protection and CI configured as code.
No proprietary runtime
Standard Node/Vite build. The platform can be built and deployed by any supplier with no bespoke tooling and no Lovable dependency.
Content portability
Content exportable as structured JSON with assets and relationships intact; the adapter interface makes CMS replacement a bounded task.
Documentation set
Architecture decision records, content model reference, runbooks, disaster-recovery plan, onboarding guide and recorded editor training.
Portability rehearsal
A documented clean-room rebuild from the repository is performed and evidenced during handover, proving there is no hidden dependency.
Exit plan
Written exit procedure covering credentials, DNS, data extraction, redirect continuity and a supported transition period.
ProvenanceThis specification describes the proposed target platform. Statements about the current caro.ie estate elsewhere on this prototype are traceable to Stage 0 evidence; targets stated here (availability, RPO/RTO, budgets) are commitments offered for negotiation, not measurements of the live service.