CMS: Fjord
Theme: Nordic
Module Set: Extended
Date: 2026-04-25

## Prompt

Build a complete, self-contained single-file CMS administration panel called Fjord with the Nordic theme. This must be a convincing simulation of a real content management system backend — not a toy, not a prototype. A full SPA.

The file is a single .html file with all CSS and JS inline. No external images anywhere. Use sessionStorage for all state persistence (NOT localStorage). On first load, generate seed data so the CMS feels lived-in. On refresh, resume existing state. Closing the tab destroys state.

### Theme — Nordic (Scandinavian Minimalism)
- Palette: Snow (#FAFAFA), Slate (#64748B), Ice (#E2E8F0), Steel (#334155), Frost Blue (#3B82F6), Charcoal (#0F172A), Error (#EF4444)
- Sidebar: Near-white (#F8FAFC) with 1px right border, nav items in slate text with frost blue 3px left-border on active (no background change)
- Cards: White background, 1px #E2E8F0 border, 8px radius, generous internal padding (24px)
- Buttons: Primary is charcoal bg with white text, 6px radius. Ghost is no bg, slate text, underline on hover
- Tables: Ultra-clean, no row borders, alternate row shading (#FAFAFA / #FFFFFF), thin header underline
- Typography: System font stack, light weight (300) for headings, regular (400) for body, tight letter-spacing (-0.02em) on headings
- Inputs: Bottom-border only (no box), 1px slate border-bottom, focus changes to frost blue
- Toasts: Top-right, white card with 4px left color bar (full height), auto-dismiss 3.5s
- Generous whitespace everywhere, content breathes, sidebar nav items widely spaced

### Module Set — Extended
Core modules (Dashboard, Posts, Pages, Categories, Tags) + Extended (Media, Comments, Users). Target approximately 1800–2200 lines of production HTML/CSS/JS. Every line must be written — no placeholder comments, no "// rest of code", no elisions.

### Architecture

**State Layer (sessionStorage):** Key `cms_state`. Contains `posts`, `pages`, `categories`, `tags`, `comments`, `users`, `media`, `settings`, `_meta`. Every mutation immediately persists.

**Router:** Hash-based SPA. Listen to `hashchange`. Parse `#/section`, `#/section/action`, `#/section/action/:id`. Default route is `#/dashboard`. Unrecognized routes redirect to dashboard.

**Routes required:**
- `#/dashboard` — Stats cards, recent activity timeline, quick draft, at-a-glance sidebar, pending comments, content calendar mini-dots
- `#/posts` — Post list with sortable table, search, status filter tabs (All/Published/Draft/Pending/Trash with counts), pagination (10 per page), bulk actions, row actions (Edit/Quick Edit/Trash), empty state
- `#/posts/new` — Full editor with title, slug (auto-generated), rich text contenteditable toolbar (Bold/Italic/H2/H3/Link/UL/OL/Blockquote/Code), word count + reading time, publish sidebar (status, date picker, categories checkboxes, tags comma-input with pills, excerpt textarea), autosave indicator, unsaved changes warning
- `#/posts/edit/:id` — Same as new but pre-filled
- `#/pages` — Similar to posts but with hierarchical indentation, Template column
- `#/pages/new`, `#/pages/edit/:id` — Same editor as posts but sidebar has Page Attributes (template, parent, order) instead of categories/tags
- `#/categories` — Two-panel layout: add form on left, table on right. Hierarchical display. Inline editing. Delete with confirmation
- `#/tags` — Two-panel layout. Table view with toggle to tag cloud view. Inline editing
- `#/media` — Grid/List toggle. Cards with type-colored borders. Upload simulation form. Detail side panel. Type filters
- `#/comments` — Status tabs (All/Pending/Approved/Spam/Trash). Cards with avatar, author info, post link, content (truncated), action links. Threaded replies. Bulk actions. Reply inline
- `#/users` — Table with avatar+name, role filter, edit view with role/color/bio, password section (simulated)
- `#/users/edit/:id` — User edit form

### Seed Data
- 14 posts: mix of published (10), draft (2), pending (1), trash (1). Real company blog titles: "Introducing the New Design System", "Q3 Engineering Retrospective", "How We Scaled to 1M Users", "Building a Remote-First Culture", "Our Approach to API Design" etc. Multi-paragraph content.
- 7 pages: Home, About, Contact, Services, Blog, Privacy Policy, Terms of Service. Parent-child: About → Team, About → Careers
- 10 categories: Technology, Design, Engineering, Product, Company News, AI → Machine Learning, AI → Deep Learning, Design → UI/UX, Design → Branding, Engineering → DevOps
- 18 tags: javascript, react, typescript, design-systems, scalability, remote-work, api, devops, ux-research, accessibility, performance, security, mobile, data-science, leadership, open-source, testing, analytics
- 12 comments: mix of approved (6), pending (3), spam (2), trash (1). Some threaded replies
- 5 users: 1 admin (Jane Foster), 1 editor (Marcus Lee), 2 authors (Sarah Chen, Diego Martinez), 1 subscriber (Alex Kim). Distinct display names with avatar colors
- 8 media items: described files with filename, type, dimensions, size

### Interaction Quality
- Optimistic updates on all saves
- Confirmation dialogs before destructive actions (delete, trash, bulk operations)
- Ctrl/Cmd+S to save in editors, Escape to close modals, Enter to confirm dialogs
- Empty states for every list view with CTA buttons
- Unsaved changes warning when navigating from dirty editors
- Undo toast on delete ("Moved to trash. Undo?" with restore action)
- Bulk operations on posts: select rows → bulk action dropdown → Apply
- Inline editing for categories and tags (click name to edit in-place)
- Loading skeleton shimmer on view transitions (300ms simulated delay)
- Toast notifications on all mutations (success/error/warning/info)

### Visual Components
- Sidebar: collapsible (hamburger on mobile < 768px), nav items with SVG icons, section grouping, active state highlighting
- Top bar: CMS name "Fjord", search input filtering current view, notification bell with comment pending badge count, user avatar dropdown (profile/logout)
- Breadcrumbs below top bar
- Data tables: sortable headers, row hover, checkbox column, pagination with "Showing 1–10 of N", empty state
- Forms: labeled inputs with validation, status badges (green Published, grey Draft, yellow Pending, red Trash), select/checkbox/textarea/date
- Rich text: contenteditable div with formatting toolbar (Bold, Italic, H2, H3, Link, UL, OL, Blockquote, Code)
- Modals: overlay + centered card for confirmations, pointer-down-to-dismiss
- Toast container: fixed top-right, 4px colored left bar, auto-dismiss 3.5s
- User avatars: colored circles with initials
- Stats cards: number + label + trend indicator on dashboard
- Loading skeletons: shimmer animation on view transitions
- Screen Options toggle in list views (show/hide columns)
- Word count and reading time in post editor
- Slug auto-generation from title (with manual override)

### Accessibility
- Semantic HTML (nav, main, aside, table, form, section)
- ARIA labels on icon-only buttons
- Focus management on modal open/close
- prefers-reduced-motion respected (disable skeleton shimmer, toast slide)
- Skip-to-content link
- Minimum 44px touch targets

NO TRIMMING. Every module, every route handler, every UI component must be written out in full. A complete CMS is always better than a trimmed one.

## Notes

- Defaulting to Nordic theme for its clean, professional aesthetic that showcases the data model and admin UX without visual noise
- Extended module set chosen for the best balance of impressiveness and feasibility
- All seed content feels like a real tech company blog — not lorem ipsum
- SessionStorage ensures opening in two tabs gives two independent instances
- contenteditable div used for rich text (not a textarea)
- Canvas API used for mini content-calendar dots and optional dashboard sparklines

## Seed Data Summary
- Posts: 14 (10 published, 2 draft, 1 pending, 1 trash)
- Pages: 7 (including child pages)
- Categories: 10 (3-level hierarchy)
- Tags: 18
- Comments: 12 (mix of statuses, some threaded)
- Users: 5 (1 admin, 1 editor, 2 authors, 1 subscriber)
- Media: 8 described files
