v0.1.27
All checks were successful
Build and Push / build (push) Successful in 1m26s
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":
- Create Application → PieCed Portal → Web → Authentication Method: CODE
- Redirect URI:
https://app.pieced.ch/api/auth/callback/zitadel - Post-logout URI:
https://app.pieced.ch/login - Note Client ID and Client Secret
2. OpenBao Secrets
bao kv put pieced/portal/oidc \
client_id="<from step 1>" \
client_secret="<from step 1>" \
nextauth_secret="$(openssl rand -base64 32)"
3. Build & Push
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
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)
Description
Languages
TypeScript
95.2%
JavaScript
3.5%
Shell
1%
CSS
0.2%