feat(website): add Nuxt 4 marketing landing page

New standalone apps/website (Nuxt 4) serving the public marketing site at
dezky.local / www.dezky.local. The customer portal moves off the root domain
to app.dezky.local only.

Landing page ported from the Dezky design handoff: light theme, Danish
default, hero variant A, with a working da/en toggle. Self-contained colour
system threaded through components (utils/landingTokens.ts), full bilingual
copy (utils/landingCopy.ts), and shared state (composables/useLanding.ts).
Sections live under components/landing/* with the Node logo under
components/brand/*.

Wired into docker-compose (website service, volume, Traefik labels, network
aliases) and bootstrap.sh (hosts list + service URLs).
This commit is contained in:
Ronni Baslund
2026-06-05 10:58:25 +02:00
parent 47eb9502f8
commit c9911cc262
35 changed files with 8760 additions and 1 deletions
@@ -32,6 +32,7 @@ volumes:
portal_node_modules:
platform_api_node_modules:
operator_node_modules:
website_node_modules:
# MinIO data (S3-compatible cold storage for audit archives). Production
# swaps the endpoint to Hetzner Object Storage and this volume goes away.
minio_data:
@@ -58,6 +59,8 @@ services:
aliases:
- traefik.dezky.local
- auth.dezky.local
- dezky.local
- www.dezky.local
- app.dezky.local
- operator.dezky.local
- api.dezky.local
@@ -490,7 +493,9 @@ services:
condition: service_healthy
labels:
- traefik.enable=true
- traefik.http.routers.portal.rule=Host(`app.dezky.local`) || Host(`dezky.local`)
# Root dezky.local + www now belong to the public marketing site; the
# customer portal lives only on app.dezky.local.
- traefik.http.routers.portal.rule=Host(`app.dezky.local`)
- traefik.http.routers.portal.tls=true
- traefik.http.services.portal.loadbalancer.server.port=3000
@@ -537,6 +542,34 @@ services:
- traefik.http.routers.operator.tls=true
- traefik.http.services.operator.loadbalancer.server.port=3000
# ─────────────────────────────────────────────────────────────────
# Website — public marketing site at dezky.local / www.dezky.local.
# Fully public: no OIDC, no Mongo, no platform-api coupling. Runs in dev
# mode here; in production it can be statically generated and served from
# a CDN/edge independently of this stack.
# ─────────────────────────────────────────────────────────────────
website:
image: node:20-alpine
container_name: dezky-website
restart: unless-stopped
working_dir: /app
command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev"
environment:
NODE_ENV: development
NUXT_HOST: 0.0.0.0
NUXT_PORT: 3000
volumes:
- ../../apps/website:/app
# Shared packages — see portal service for explanation.
- ../../packages:/shared-packages:ro
- website_node_modules:/app/node_modules
networks: [dezky]
labels:
- traefik.enable=true
- traefik.http.routers.website.rule=Host(`dezky.local`) || Host(`www.dezky.local`)
- traefik.http.routers.website.tls=true
- traefik.http.services.website.loadbalancer.server.port=3000
# ─────────────────────────────────────────────────────────────────
# platform-api — NestJS service. Owns tenants, partners, users,
# subscriptions, and provisioning orchestration.