# PieCed Portal Customer self-service portal for the PieCed IT multi-tenant OpenClaw platform. ## Stack | Layer | Choice | |-------|--------| | Framework | Next.js 15 LTS (App Router, standalone output, Turbopack) | | Auth | NextAuth v5 + ZITADEL OIDC (CODE flow) | | Tenant mgmt | Direct K8s API → `PiecedTenant` CRs (Option A) | | Usage data | LiteLLM `/team/info` + `/global/spend/logs` | | i18n | next-intl 4.x (en/de) | | Styling | Tailwind CSS 4 | | Deployment | Container in `pieced-system`, exposed at `app.pieced.ch` | ## Setup ### 1. ZITADEL Application In ZITADEL console (`auth.pieced.ch`), project "OpenClaw Platform": 1. Create Application → **PieCed Portal** → Web → Authentication Method: **CODE** 2. Redirect URI: `https://app.pieced.ch/api/auth/callback/zitadel` 3. Post-logout URI: `https://app.pieced.ch/login` 4. Note Client ID and Client Secret ### 2. OpenBao Secrets ```bash bao kv put pieced/portal/oidc \ client_id="" \ client_secret="" \ nextauth_secret="$(openssl rand -base64 32)" ``` ### 3. Build & Push ```bash docker build -t registry.c5ai.ch/pieced/pieced-portal:0.1.0 . docker push registry.c5ai.ch/pieced/pieced-portal:0.1.0 ``` Update image tag in `pieced-gitops/apps/portal/deployment.yaml`, push, ArgoCD syncs. ### 4. DNS Ensure `app.pieced.ch` A record → MetalLB ingress IP (or ExternalDNS handles it). ## Local Development ```bash cp .env.example .env.local # Fill in values — K8s client uses ~/.kube/config locally npm install npm run dev ``` ## Project Structure ``` src/ ├── app/ │ ├── api/ │ │ ├── auth/[...nextauth]/route.ts # NextAuth handler │ │ ├── tenants/route.ts # Tenant CRUD (K8s API) │ │ └── usage/route.ts # Usage stub │ ├── [locale]/ │ │ ├── layout.tsx # Locale layout + NavShell │ │ ├── page.tsx # Redirect → /dashboard │ │ ├── login/page.tsx # ZITADEL sign-in │ │ ├── dashboard/page.tsx # Customer dashboard │ │ └── admin/page.tsx # Platform admin tenant list │ ├── layout.tsx # Root layout │ └── globals.css # Tailwind 4 theme ├── components/ │ ├── layout/nav-shell.tsx # Header + navigation │ └── ui/ # Reusable UI components ├── i18n/ │ ├── routing.ts # next-intl 4.x routing config │ ├── navigation.ts # Localized Link, redirect, etc. │ └── request.ts # Server-side i18n config ├── lib/ │ ├── auth.ts # NextAuth v5 + ZITADEL config │ ├── k8s.ts # K8s client for PiecedTenant CRs │ ├── litellm.ts # LiteLLM API client │ └── session.ts # Session helpers ├── messages/ │ ├── en.json │ └── de.json └── types/index.ts # Shared TypeScript types ``` ## Session Roadmap - **6.1** ← This session: scaffold, auth, basic pages - **6.2**: Instance management, package config, usage display - **6.3**: Onboarding flow (create ZITADEL org → PiecedTenant CR) - **6.4**: Workspace editor (SOUL.md, AGENTS.md, TOOLS.md) - **6.5**: Admin panel (tenant lifecycle, billing overview)