Files
cameleer-saas/ui/CLAUDE.md
hsiegeln 9ed2cedc98
All checks were successful
CI / build (push) Successful in 1m14s
CI / docker (push) Successful in 1m15s
feat: self-service sign-up with email verification and onboarding
Complete sign-up pipeline: email registration via Logto Experience API,
SMTP email verification, and self-service trial tenant creation.

Layer 1 — Logto config:
- Bootstrap Phase 8b: SMTP email connector with branded HTML templates
- Bootstrap Phase 8c: enable SignInAndRegister (email+password sign-up)
- Dockerfile installs official Logto connectors (ensures SMTP available)
- SMTP env vars in docker-compose, installer templates, .env.example

Layer 2 — Experience API (ui/sign-in/experience-api.ts):
- Registration flow: initRegistration → sendVerificationCode → verifyCode
  → addProfile (password) → identifyUser → submit
- Sign-in auto-detects email vs username identifier

Layer 3 — Custom sign-in UI (ui/sign-in/SignInPage.tsx):
- Three-mode state machine: signIn / register / verifyCode
- Reads first_screen=register from URL query params
- Toggle links between sign-in and register views

Layer 4 — Post-registration onboarding:
- OnboardingService: reuses VendorTenantService.createAndProvision(),
  adds calling user to Logto org as owner, enforces one trial per user
- OnboardingController: POST /api/onboarding/tenant (authenticated only)
- OnboardingPage.tsx: org name + auto-slug form
- LandingRedirect: detects zero orgs → redirects to /onboarding
- RegisterPage.tsx: /platform/register initiates OIDC with firstScreen

Installers (install.sh + install.ps1):
- Both prompt for SMTP config in SaaS mode
- CLI args, env var capture, cameleer.conf persistence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 00:21:07 +02:00

2.4 KiB

Frontend

React 19 SPA served at /platform/* by the Spring Boot backend.

Core files

  • main.tsx — React 19 root
  • router.tsx/vendor/* + /tenant/* with RequireScope guards, LandingRedirect that waits for scopes (redirects to /onboarding if user has zero orgs), /register route for OIDC sign-up flow, /onboarding route for self-service tenant creation
  • Layout.tsx — persona-aware sidebar: vendor sees expandable "Vendor" section (Tenants, Audit Log, Certificates, Infrastructure, Identity/Logto), tenant admin sees Dashboard/License/SSO/Team/Audit/Settings
  • OrgResolver.tsx — merges global + org-scoped token scopes (vendor's platform:admin is global)
  • config.ts — fetch Logto config from /platform/api/config

Auth hooks

  • auth/useAuth.ts — auth hook (isAuthenticated, logout, signIn)
  • auth/useOrganization.ts — Zustand store for current tenant
  • auth/useScopes.ts — decode JWT scopes, hasScope()
  • auth/ProtectedRoute.tsx — guard (redirects to /login)
  • auth/LoginPage.tsx — redirects to Logto OIDC sign-in
  • auth/RegisterPage.tsx — redirects to Logto OIDC with firstScreen: 'register'

Pages

  • Onboarding: OnboardingPage.tsx — self-service trial tenant creation (org name + slug), shown to users with zero org memberships after sign-up
  • Vendor pages: VendorTenantsPage.tsx, CreateTenantPage.tsx, TenantDetailPage.tsx, VendorAuditPage.tsx, CertificatesPage.tsx, InfrastructurePage.tsx
  • Tenant pages: TenantDashboardPage.tsx (restart + upgrade server), TenantLicensePage.tsx, SsoPage.tsx, TeamPage.tsx (reset member passwords), TenantAuditPage.tsx, SettingsPage.tsx (change own password, reset server admin password)

Custom Sign-in UI (ui/sign-in/)

Separate Vite+React SPA replacing Logto's default sign-in page. Built as custom Logto Docker image — see docker/CLAUDE.md for details.

  • SignInPage.tsx — sign-in + registration form with @cameleer/design-system components. Three modes: signIn (email/username + password), register (email + password + confirm), verifyCode (6-digit email verification). Reads first_screen=register from URL query params to determine initial view.
  • experience-api.ts — Logto Experience API client. Sign-in: init -> verify password -> identify -> submit. Registration: init Register -> send verification code -> verify code -> add password profile -> identify -> submit. Auto-detects email vs username identifiers.