managarten/services/mana-landing-builder/CLAUDE.md
Till JS 22a73943e1 chore: complete ManaCore → Mana rename (docs, go modules, plists, images)
Final cleanup of references missed in previous rename commits:

- Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL
- Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files)
- launchd plists: com.manacore.* → com.mana.* (14 files renamed + content)
- Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files)
- .env.example files: ManaCore brand strings → Mana
- .prettierignore: stale apps/manacore/* paths → apps/mana/*
- Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc.

Excluded from rename: .claude/, devlog/, manascore/ (historical content),
client testimonials, blueprints, npm package refs (@mana-core/*).

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

208 lines
6.6 KiB
Markdown

# Mana Landing Builder Service
Static landing page builder for organizations. Takes a JSON config, generates an Astro site, and deploys it to Cloudflare Pages.
## Overview
- **Port**: 3030
- **Technology**: NestJS + Astro + Cloudflare Pages
- **Purpose**: Build and deploy static landing pages for organizations under `{slug}.mana.how`
## Architecture
```
Admin Dashboard (Mana Web)
│ POST /api/v1/build { slug, config }
Landing Builder Service (Port 3030)
├── 1. Copy Astro template to temp dir
├── 2. Write config.json (section data)
├── 3. Generate theme.css (colors)
├── 4. pnpm install + astro build
└── 5. wrangler pages deploy → Cloudflare Pages
{slug}.mana.how
```
## Quick Start
```bash
# Start the builder service
pnpm dev:landing-builder
# Or directly
pnpm --filter @mana-landing-builder/service start:dev
```
## API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/build` | Build and deploy a landing page |
| GET | `/api/v1/health` | Health check |
### Build Request
```bash
curl -X POST http://localhost:3030/api/v1/build \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"organizationId": "org-id",
"slug": "chorverein-harmonie",
"config": {
"enabled": true,
"theme": "warm",
"sections": {
"hero": { "title": "Chorverein Harmonie", "subtitle": "Seit 1952" },
"about": { "title": "About", "features": [] },
"team": { "title": "Team", "members": [] },
"contact": { "title": "Contact", "email": "info@example.com" },
"footer": { "copyright": "2024 Chorverein Harmonie" }
}
}
}'
```
### Response
```json
{
"success": true,
"url": "https://chorverein-harmonie.mana.how",
"duration": 15000
}
```
## Configuration
The landing page config is stored in `organizations.metadata.landingPage` in mana-auth. The Admin UI in Mana Web writes this config, then triggers the builder.
### Config Structure (LandingPageConfig)
Types are defined in `packages/shared-types/src/landing-config.ts`.
```typescript
interface LandingPageConfig {
enabled: boolean;
theme: 'classic' | 'warm';
customColors?: { primary?, primaryHover?, primaryGlow? };
sections: {
hero: { title, subtitle, variant?, primaryCta?, image? };
about: { title, subtitle?, features[] };
team: { title, subtitle?, members[] };
contact: { title, subtitle?, email?, phone?, address? };
footer: { copyright?, links?, socialLinks? };
};
}
```
### Available Themes
| Theme | Style | Best For |
|-------|-------|----------|
| `classic` | Professional dark (slate tones) | Businesses, institutions |
| `warm` | Inviting light (amber tones) | Schools, clubs, community orgs |
Both themes support `customColors` overrides for the primary color.
## Available Sections
All sections use shared components from `@mana/shared-landing-ui`:
| Section | Component | Description |
|---------|-----------|-------------|
| Hero | `HeroSection.astro` | Title, subtitle, CTA button, image |
| About | `FeatureSection.astro` | Feature cards in a grid |
| Team | `TeamSection.astro` | Team member cards with avatars |
| Contact | `ContactSection.astro` | Email, phone, address display |
| Footer | `Footer.astro` | Copyright, links, social links |
## Project Structure
```
services/mana-landing-builder/
├── src/
│ ├── main.ts # NestJS bootstrap
│ ├── app.module.ts
│ ├── builder/
│ │ ├── builder.controller.ts # POST /api/v1/build
│ │ ├── builder.service.ts # Core build logic
│ │ └── dto/
│ │ └── build-landing.dto.ts
│ └── config/
│ └── configuration.ts
└── template/ # Astro template project
├── astro.config.mjs
├── package.json
├── src/
│ ├── layouts/Layout.astro # HTML shell
│ ├── pages/index.astro # Reads config.json, renders sections
│ ├── styles/theme.css # Overwritten per build
│ └── data/config.json # Overwritten per build
└── public/
```
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | 3030 | Service port |
| `MANA_AUTH_URL` | http://localhost:3001 | Auth service URL |
| `CLOUDFLARE_API_TOKEN` | - | Cloudflare API token (Pages + DNS permissions) |
| `CLOUDFLARE_ACCOUNT_ID` | - | Cloudflare account ID |
| `ORG_LANDING_DOMAIN` | mana.how | Base domain for org landing pages |
## Admin UI
The landing page editor lives in the Mana web dashboard:
- **Route**: `/organizations/[id]/landing`
- **Components**: `apps/mana/apps/web/src/lib/components/landing/`
- **API Client**: `apps/mana/apps/web/src/lib/api/services/landing.ts`
The editor provides a form-based interface where org admins can:
1. Select a theme (classic/warm)
2. Optionally override the primary color
3. Fill in content for each section (Hero, About, Team, Contact, Footer)
4. Save (stores config in org metadata) or Publish (save + build + deploy)
## Build Process Details
1. Template directory is copied to a temporary working directory
2. `config.json` is written with the section data from the landing config
3. `theme.css` is generated from the selected theme + any custom color overrides
4. `pnpm install` runs to resolve `@mana/shared-landing-ui` from the workspace
5. `astro build` generates static HTML/CSS/JS in `dist/`
6. `wrangler pages deploy` pushes to Cloudflare Pages as project `org-{slug}`
7. Custom domain `{slug}.mana.how` is configured (if Cloudflare token is set)
8. Temp directory is cleaned up
Concurrent builds for the same org are rejected (409 Conflict).
## Development Commands
```bash
# Start service
pnpm dev:landing-builder
# Build for production
pnpm --filter @mana-landing-builder/service build
# Type check
pnpm --filter @mana-landing-builder/service type-check
```
## Related Files
| Location | Purpose |
|----------|---------|
| `packages/shared-types/src/landing-config.ts` | TypeScript types for landing config |
| `packages/shared-landing-ui/src/sections/TeamSection.astro` | Team member grid component |
| `packages/shared-landing-ui/src/sections/ContactSection.astro` | Contact info component |
| `packages/shared-landing-ui/src/themes/org-classic.css` | Classic dark theme |
| `packages/shared-landing-ui/src/themes/org-warm.css` | Warm light theme |
| `apps/mana/apps/web/src/lib/components/landing/` | Admin UI components |