The org has 3 landing page theme templates (Minimal, Bold, Classic) in `packages/ui/` that all accept `OrgLandingPageProps` uniformly. However:
1. The templates are **only used in Storybook** — the actual public landing page (`landing-page.svelte`) renders its own custom legacy HTML
2. The stored `OrgLandingPageJson` is a complex format (header, aboutUs, faq, contact, mailinglist, etc.) that **doesn't align** with what the templates need
3. There is no theme selection UI
4. There is no edit flow like the course landing page (split-screen with live preview)
This plan: simplifies the stored format to match `OrgLandingPageProps`, replaces the legacy public landing page renderer with the theme components, adds a theme picker in settings, and adds a split-screen content editor modeled after the course landing page editor.
---
## Simplified Data Model
Replace `OrgLandingPageJson` (the DB-stored type) with a structure that maps 1:1 to `OrgLandingPageProps`:
```ts
// apps/dashboard/src/lib/utils/types/org.ts
exportinterfaceOrgLandingPageJson{
theme:'minimal'|'bold'|'classic';
hero:{
heading: string;
subheading: string;
primaryAction:{label: string;href: string};
secondaryAction?:{label: string;href: string};
image?: string;
};
navItems: Array<{label: string;href: string}>;
footerLinks: Array<{label: string;href: string}>;
footerText: string;
}
```
Sections removed from old format: `header` (with banner/background/show toggles), `aboutUs`, `courses`, `faq`, `contact`, `mailinglist`, `customLinks`, `footer` (social links only).
Fields from org data (not stored in `landingpage`): `orgName` → `org.name`, `logoUrl` → `org.avatarUrl`, `courses` → `orgApi.publicCourses`.
Remove all existing form fields. The page now shows only:
- **Theme picker** (`Field.Set` "Choose a Theme"): 3 cards in `grid grid-cols-3 gap-4` using `RadioGroup.Root bind:value={$landingPageSettings.theme}`. Each card:
- Inline SVG thumbnail (distinct per theme — see SVG specs below)
- Theme name label
- Radio selection state: `border-primary ring-2 ring-primary/20` vs `border-border`
Mirrors the section-based structure of the course landing page `editor.svelte`.
Sections (left sidebar menu → click to edit):
1.**Hero** — heading, subheading, primaryAction (label + href), secondaryAction (optional label + href toggle), image (upload widget, used by Bold/Classic)
2.**Navigation** — list of nav items (label + href), add/remove rows
3.**Footer** — footer text, list of footer links (label + href), add/remove rows
Header: "Save" button + close button (back to settings).
Section form pattern: inline `Input` / `Textarea` / `UploadWidget` fields, two-way bound to `settings` prop, changes reflect live in the preview panel.
### 6. Replace legacy public landing page renderer
-`Sidebar.Provider/Root/Inset` from `@cio/ui/base/sidebar` — same as course landing page editor route
-`RadioGroup.Root/Item` — already imported in `landingpage.svelte`
-`Field.Set/Field.Legend/Field.Separator` — already imported in `landingpage.svelte`
-`UploadWidget` — already imported in `landingpage.svelte`
-`orgApi.update($currentOrg.id, { landingpage: ... })` — same save pattern
-`UnsavedChanges` component — already in `landingpage.svelte`
-`goto()` for close/navigate — same as course editor
## Verification
1.**Theme picker**: `/org/[slug]/settings/landingpage` shows 3 cards with distinct SVG previews; clicking a card highlights it; saving persists the selection; reload reflects saved theme
2.**Edit Content**: clicking "Edit Content" navigates to `/org/[slug]/settings/landingpage/edit`; the editor opens as a full-screen overlay with the selected theme visible on the right; editing fields updates the preview live
3.**Public landing page**: visiting the org's public URL renders the selected theme (Minimal/Bold/Classic) using actual org courses; switching theme in settings and saving changes what public visitors see
4.**Backward compat**: orgs with old `OrgLandingPageJson` format get reset to minimal defaults gracefully (no crash)