Lossless Changelog
product

Project Scaffold — Astro 6, Svelte 5, Tailwind 4, Sveltia CMS

Initial project scaffold for arthouse-site — an image-heavy portfolio site for boutique e-commerce. Astro 6 + Svelte 5 + Tailwind 4 stack, three-mode theme system with client-managed colors, Sveltia CMS at /admin, WhatsApp CTA via server-side redirect, content collections for galleries/pricing/pages/SEO, and a horizontal swipe carousel component.

Michael StatonMusic Editoraugmented with Claude Code on Opus 4.6

Changelog - 2026-04-21 (01)

Project Scaffold — Astro 6, Svelte 5, Tailwind 4, Sveltia CMS

Overview

Full project scaffold for arthouse-site, a mobile-first image-heavy portfolio site for a boutique e-commerce client based in Paris. The site is designed to be self-manageable by the client through Sveltia CMS and deployable independently from the Astro-Knots pseudomonorepo.

Specification lives at context-v/specs/Maintain-an-Image-Heavy-Portfolio-Site.md (v0.0.0.3).


Stack

DependencyVersionRole
Astro6.1.8Static site generation with hybrid server routes
Svelte5.xInteractive components (carousels, mode toggle)
Tailwind CSS4.xUtility-first styling via @tailwindcss/vite
@astrojs/vercel10.xDeployment adapter
@astrojs/sitemap3.7.xSitemap generation
Sveltia CMSCDNGit-backed content management at /admin

Tailwind 4 Integration Notes

Tailwind 4 auto-content-detection failed in the monorepo context — .astro and .svelte files weren't being scanned for utility classes. Fixed with explicit @source directives in global.css:

CSS
@import "tailwindcss";
@source "../../src/**/*.astro";
@source "../../src/**/*.svelte";
@source "../../src/**/*.ts";

Also removed duplicate base reset styles (*, html, body, a, img) that were conflicting with Tailwind's preflight layer and preventing responsive md: variants from applying.


Theme & Mode System

Three display modes — dark (default), vibrant, and light — using CSS custom properties on data-theme="arthouse" and data-mode attributes.

Color Architecture

:root                          Named colors (hex values ONLY here)
    │
    ▼
[data-theme="arthouse"]
[data-mode="dark"]             Semantic tokens → var(--color-{name})
[data-mode="vibrant"]
[data-mode="light"]
    │
    ▼
Components                     Use ONLY semantic tokens

Client-Managed Colors

Named colors and mode assignments are defined in markdown data files (src/content/theme/colors.md and src/content/theme/modes.md), editable through the CMS. Currently rendered as CSS fallbacks in global.css — build-time generation from the data files is a future step.

Mode Toggle

localStorage-based persistence. Cycles dark → vibrant → light via a button in the nav bar. Initial mode from SITE_MODE env var, overridden by stored preference.


Content Model

Five content collections, all using loose Zod schemas (.passthrough(), no strict validation):

Galleries (src/content/galleries/)

Organized by layout orientation, not content taxonomy:

  • portrait/ — tall/vertical images

  • landscape/ — wide/horizontal images

  • grid/ — mixed aspect ratios

Images listed as a YAML array in frontmatter:

YAML
images:
  - /images/portfolio/photo-one.jpeg
  - /images/portfolio/photo-two.jpeg

Pages (src/content/pages/)

Marketing pages with hardcoded layouts but client-editable content. Sections use the marketing block content model:

YAML
sections:
  - headingLevelInt: 1
    contextSetterTxt: "Small text above heading"
    headingTxt: "The Main Heading"
    subHeadingTxt: "Supporting copy"
    ctaTxt: "Call to Action"
    ctaComponentName: "link"
    ctaHref: "/portfolio/"

Pricing (src/content/pricing/)

Each tier is a markdown file. Client can add/remove/reorder tiers by creating/deleting files.

Theme (src/content/theme/)

Single-file collections for the color palette and mode assignments.

SEO Pages (src/content/seo-pages/)

Placeholder — no content yet.

Images (src/content/images/)

Placeholder — individual image metadata files. Currently galleries reference image paths directly rather than image slugs.


Components

MarketingBlock.astro

Reusable component for marketing sections. Accepts the standard content model props (headingLevelInt, contextSetterTxt, headingTxt, subHeadingTxt, ctaTxt, ctaComponentName, ctaHref). Renders dynamic heading levels, WhatsApp CTA variant, and styled copy.

HorizontalSwipe.svelte

Touch-swipe carousel for gallery images:

  • Svelte 5 with $props() and $state()

  • CSS scroll-snap with momentum-based touch scrolling

  • Responsive slide widths: 85% mobile, 45% tablet, 30% desktop

  • Dot indicators with active state animation

  • Arrow buttons on desktop (hidden on mobile)

  • Lazy loading for off-screen images

  • 3:4 aspect ratio crop on slides

BaseLayout.astro

Page wrapper with sticky nav, mode toggle, footer. Pure Tailwind utilities, px-6 md:px-12 horizontal padding aligned across nav/content/footer.


Sveltia CMS

Setup

Single Astro page at src/pages/admin.astro loads the CMS from CDN. Config at public/admin/config.yml maps all content collections.

Local Mode

"Work with Local Repository" mode reads/writes markdown files on disk. Does not handle image uploads — binary file writes from the browser are blocked by browser security. Image files must be placed manually during local development.

Production Mode

GitHub OAuth backend commits both text and binary (uploaded images) directly to the repo via GitHub API. Auto-deploys via Vercel on push.

Config Fixes

  • Single-file collections (theme-colors, theme-modes) must be nested under a parent collection with a files: array — cannot sit at the top level of collections:

  • Nested fields: inside YAML flow mappings ({ }) is invalid — expanded to block syntax

  • Gallery image lists use widget: list with field: { widget: image } instead of markdown body


WhatsApp CTA

Server-side redirect at /api/contact.ts:

  • Phone number from WHATSAPP_NUMBER env var — never in client-side HTML

  • Pre-filled message from WHATSAPP_DEFAULT_MESSAGE env var

  • Query params for tier and ref tracking

  • 302 redirect to wa.me URL


Route Map

RouteStatusDescription
/WorkingSplit layout: marketing copy left, hero image right
/portfolio/WorkingGallery carousel from content collection
/services/StubPricing tiers placeholder
/contact/WorkingWhatsApp CTA with server redirect
/adminWorkingSveltia CMS
/design-system/StubComponent browser placeholder

Pseudomonorepo Integration

  • Added as git submodule at sites/arthouse-site

  • Added to pnpm-workspace.yaml

  • Private repo at lossless-group/arthouse-site

  • .npmrc configured with link-workspace-packages=false

  • Builds independently: pnpm install && pnpm build from site directory


Known Issues / Next Steps

  1. Theme CSS generator — colors.md and modes.md data files exist but CSS is still hardcoded as fallbacks. Need build-time generation.

  2. Gallery detail pages — /portfolio/[slug] routes not yet implemented

  3. Lightbox — click-to-enlarge on gallery images

  4. MasonryGrid and VerticalSwipe — only HorizontalSwipe implemented

  5. Mobile nav — hamburger menu not yet implemented (nav links hidden on mobile)

  6. Vercel deployment — not yet connected

  7. GitHub OAuth — not yet configured for CMS production use

  8. OG images — no Open Graph image generation yet

  9. SEO landing pages — content type exists but no pages or routes

  10. Image optimization — not using Astro's <Image> component yet