diff --git a/README.md b/README.md index 054eb33..0cbaa4f 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,22 @@ theme: studio # or: minimal, editorial, classic, noir, monograph, botanica Editorial theme Classic theme + + Noir
Darkroom analog, film noir + Monograph
Typographic, book-like + + + Noir theme + Monograph theme + + + Botanica
Organic, nature-inspired + + + + Botanica theme + + → **[Theming Guide](docs/theming.md)** diff --git a/docs/screenshots/hero-fullbleed-home.png b/docs/screenshots/hero-fullbleed-home.png new file mode 100644 index 0000000..2b9f277 Binary files /dev/null and b/docs/screenshots/hero-fullbleed-home.png differ diff --git a/docs/screenshots/hero-minimal-home.png b/docs/screenshots/hero-minimal-home.png new file mode 100644 index 0000000..2c5aeb2 Binary files /dev/null and b/docs/screenshots/hero-minimal-home.png differ diff --git a/docs/screenshots/hero-mosaic-home.png b/docs/screenshots/hero-mosaic-home.png new file mode 100644 index 0000000..a6f355c Binary files /dev/null and b/docs/screenshots/hero-mosaic-home.png differ diff --git a/docs/screenshots/hero-split-home.png b/docs/screenshots/hero-split-home.png new file mode 100644 index 0000000..cf5435d Binary files /dev/null and b/docs/screenshots/hero-split-home.png differ diff --git a/docs/screenshots/hero-stacked-home.png b/docs/screenshots/hero-stacked-home.png new file mode 100644 index 0000000..da7355e Binary files /dev/null and b/docs/screenshots/hero-stacked-home.png differ diff --git a/docs/screenshots/hero-typographic-home.png b/docs/screenshots/hero-typographic-home.png new file mode 100644 index 0000000..2a8e146 Binary files /dev/null and b/docs/screenshots/hero-typographic-home.png differ diff --git a/docs/screenshots/theme-botanica-grid.png b/docs/screenshots/theme-botanica-grid.png new file mode 100644 index 0000000..239bb08 Binary files /dev/null and b/docs/screenshots/theme-botanica-grid.png differ diff --git a/docs/screenshots/theme-botanica-home.png b/docs/screenshots/theme-botanica-home.png new file mode 100644 index 0000000..885f732 Binary files /dev/null and b/docs/screenshots/theme-botanica-home.png differ diff --git a/docs/screenshots/theme-classic-grid.png b/docs/screenshots/theme-classic-grid.png index a08c5ad..e6c31d3 100644 Binary files a/docs/screenshots/theme-classic-grid.png and b/docs/screenshots/theme-classic-grid.png differ diff --git a/docs/screenshots/theme-classic-home.png b/docs/screenshots/theme-classic-home.png index 91cd245..b136808 100644 Binary files a/docs/screenshots/theme-classic-home.png and b/docs/screenshots/theme-classic-home.png differ diff --git a/docs/screenshots/theme-editorial-grid.png b/docs/screenshots/theme-editorial-grid.png index 6ff2a08..6fb0baf 100644 Binary files a/docs/screenshots/theme-editorial-grid.png and b/docs/screenshots/theme-editorial-grid.png differ diff --git a/docs/screenshots/theme-editorial-home.png b/docs/screenshots/theme-editorial-home.png index bc36e49..ce90ca4 100644 Binary files a/docs/screenshots/theme-editorial-home.png and b/docs/screenshots/theme-editorial-home.png differ diff --git a/docs/screenshots/theme-minimal-grid.png b/docs/screenshots/theme-minimal-grid.png index 4c5e207..87cb2e1 100644 Binary files a/docs/screenshots/theme-minimal-grid.png and b/docs/screenshots/theme-minimal-grid.png differ diff --git a/docs/screenshots/theme-minimal-home.png b/docs/screenshots/theme-minimal-home.png index 6f87b00..f243ccc 100644 Binary files a/docs/screenshots/theme-minimal-home.png and b/docs/screenshots/theme-minimal-home.png differ diff --git a/docs/screenshots/theme-monograph-grid.png b/docs/screenshots/theme-monograph-grid.png new file mode 100644 index 0000000..d17ae4d Binary files /dev/null and b/docs/screenshots/theme-monograph-grid.png differ diff --git a/docs/screenshots/theme-monograph-home.png b/docs/screenshots/theme-monograph-home.png new file mode 100644 index 0000000..3c15ce5 Binary files /dev/null and b/docs/screenshots/theme-monograph-home.png differ diff --git a/docs/screenshots/theme-noir-grid.png b/docs/screenshots/theme-noir-grid.png new file mode 100644 index 0000000..f4db044 Binary files /dev/null and b/docs/screenshots/theme-noir-grid.png differ diff --git a/docs/screenshots/theme-noir-home.png b/docs/screenshots/theme-noir-home.png new file mode 100644 index 0000000..03b4028 Binary files /dev/null and b/docs/screenshots/theme-noir-home.png differ diff --git a/docs/screenshots/theme-studio-grid.png b/docs/screenshots/theme-studio-grid.png index 2ffc4d5..141e1bf 100644 Binary files a/docs/screenshots/theme-studio-grid.png and b/docs/screenshots/theme-studio-grid.png differ diff --git a/docs/screenshots/theme-studio-home.png b/docs/screenshots/theme-studio-home.png index 6f77833..2b9f277 100644 Binary files a/docs/screenshots/theme-studio-home.png and b/docs/screenshots/theme-studio-home.png differ diff --git a/docs/theming.md b/docs/theming.md index a5cac08..5a1f258 100644 --- a/docs/theming.md +++ b/docs/theming.md @@ -26,6 +26,41 @@ That's it. Your entire gallery switches to the minimal theme. Default is `studio` if no theme is specified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Studio
Leica-inspired, red dot
Minimal
Swiss brutalist, fullbleed hero
Studio themeMinimal theme
Editorial
Cinematic magazine, warm charcoal
Classic
Gilded gallery, gold accents
Editorial themeClassic theme
Noir
Darkroom analog, film noir
Monograph
Typographic, book-like
Noir themeMonograph theme
Botanica
Organic, nature-inspired
Botanica theme
+ ### What makes each theme unique **Studio** (default) — Leica-inspired with a red nav dot, passepartout photo frames, film grain, and a split hero layout. Clean editorial feel with Playfair Display headings. @@ -112,6 +147,29 @@ Controls the homepage hero layout: - **`typographic`** — no hero image; massive centered title with numbered album navigation list (used by Monograph) - **`mosaic`** — asymmetric multi-image grid with frosted-glass title overlay centered on top + + + + + + + + + + + + + + + + + + + + + +
SplitFullbleedMinimal
Split HeroFullbleed HeroMinimal Hero
StackedTypographicMosaic
Stacked HeroTypographic HeroMosaic Hero
+ ### `grid.layout` Controls the photo grid layout on album pages: diff --git a/scripts/screenshots.ts b/scripts/screenshots.ts index 50b00de..1cfaac4 100644 --- a/scripts/screenshots.ts +++ b/scripts/screenshots.ts @@ -19,11 +19,11 @@ import { spawn, type ChildProcess } from 'child_process'; import fs from 'fs'; import path from 'path'; -const THEMES = ['studio', 'minimal', 'editorial', 'classic']; +const THEMES = ['studio', 'minimal', 'editorial', 'classic', 'noir', 'monograph', 'botanica']; const BASE_URL = 'http://localhost:3000'; -const GRID_PATH = '/deutschland/kloster-chorin-2024'; // public subpage with photos +const GRID_PATH = '/deutschland/kloster-chorin'; // public subpage with photos const OUTPUT_DIR = path.join(process.cwd(), 'docs', 'screenshots'); -const GALLERY_YAML = path.join(process.cwd(), 'content', 'gallery.yaml'); +const SETTINGS_YAML = path.join(process.cwd(), 'content', 'settings.yaml'); const VIEWPORT = { width: 1440, height: 900 }; const IMAGE_LOAD_TIMEOUT = 8000; // ms to wait for images after networkidle @@ -31,8 +31,8 @@ async function main() { // Ensure output directory exists fs.mkdirSync(OUTPUT_DIR, { recursive: true }); - // Read original gallery.yaml to restore later - const originalYaml = fs.readFileSync(GALLERY_YAML, 'utf8'); + // Read original settings.yaml to restore later + const originalYaml = fs.readFileSync(SETTINGS_YAML, 'utf8'); // Dynamic import for Playwright (may not be installed globally) const { chromium } = await import('playwright'); @@ -43,9 +43,9 @@ async function main() { console.log(`\nšŸŽØ Theme: ${theme}`); console.log('─'.repeat(50)); - // Update gallery.yaml with the theme - const yamlWithTheme = setThemeInYaml(originalYaml, theme); - fs.writeFileSync(GALLERY_YAML, yamlWithTheme); + // Update settings.yaml with the theme + const yamlWithTheme = setThemeInSettingsYaml(originalYaml, theme); + fs.writeFileSync(SETTINGS_YAML, yamlWithTheme); // Start dev server console.log(' ā³ Starting dev server...'); @@ -89,13 +89,62 @@ async function main() { await context.close(); // Stop dev server - server.kill('SIGTERM'); - await new Promise((resolve) => server.on('close', resolve)); + if (server.pid) { + process.kill(-server.pid, 'SIGTERM'); + } + await new Promise((resolve) => { + const timeout = setTimeout(resolve, 3000); + server.on('close', () => { + clearTimeout(timeout); + resolve(null); + }); + }); + console.log(' šŸ›‘ Server stopped'); + } + + const HERO_STYLES = ['split', 'fullbleed', 'minimal', 'stacked', 'typographic', 'mosaic']; + for (const hero of HERO_STYLES) { + console.log(`\nšŸ–¼ Hero Style: ${hero} (Theme: studio)`); + console.log('─'.repeat(50)); + + const yamlWithTheme = setThemeInSettingsYaml(originalYaml, 'studio'); + const yamlWithHero = setHeroStyleInSettingsYaml(yamlWithTheme, hero); + fs.writeFileSync(SETTINGS_YAML, yamlWithHero); + + console.log(' ā³ Starting dev server...'); + const server = startDevServer(); + await waitForServer(BASE_URL, 15000); + console.log(' āœ… Server ready'); + + const context = await browser.newContext({ viewport: VIEWPORT }); + const page = await context.newPage(); + + console.log(' šŸ“ø Capturing homepage hero...'); + await page.goto(BASE_URL, { waitUntil: 'networkidle' }); + await waitForImages(page); + await page.screenshot({ + path: path.join(OUTPUT_DIR, `hero-${hero}-home.png`), + fullPage: false, + }); + console.log(` āœ… hero-${hero}-home.png`); + + await context.close(); + + if (server.pid) { + process.kill(-server.pid, 'SIGTERM'); + } + await new Promise((resolve) => { + const timeout = setTimeout(resolve, 3000); + server.on('close', () => { + clearTimeout(timeout); + resolve(null); + }); + }); console.log(' šŸ›‘ Server stopped'); } } finally { - // Always restore original gallery.yaml - fs.writeFileSync(GALLERY_YAML, originalYaml); + // Always restore original settings.yaml + fs.writeFileSync(SETTINGS_YAML, originalYaml); console.log('\nāœ… Restored original gallery.yaml'); await browser.close(); } @@ -111,14 +160,35 @@ async function main() { // ── Helpers ────────────────────────────────────────────────────── -function setThemeInYaml(yaml: string, theme: string): string { - // Replace existing theme line or insert after the header comment - if (/^theme:\s*.+$/m.test(yaml)) { - return yaml.replace(/^theme:\s*.+$/m, `theme: ${theme}`); +/** + * Replace the theme preset in settings.yaml. + * Handles both `theme: preset` shorthand and `theme:\n preset: "x"` block. + */ +function setThemeInSettingsYaml(yaml: string, theme: string): string { + // Handle ` preset: "studio"` or ` preset: studio` (block format) + if (/^ preset:\s*/m.test(yaml)) { + return yaml.replace(/^ preset:\s*.+$/m, ` preset: "${theme}"`); } - // Insert theme after the header comments - const marker = '# Secrets (API key, server URL) stay in .env.local.'; - return yaml.replace(marker, `${marker}\n\ntheme: ${theme}`); + // Handle `theme: studio` shorthand + if (/^theme:\s*\w+\s*$/m.test(yaml)) { + return yaml.replace(/^theme:\s*\w+\s*$/m, `theme: ${theme}`); + } + // Fallback: insert block after the theme comment + const marker = '# Presets: studio, minimal, editorial, classic, noir, monograph, botanica'; + if (yaml.includes(marker)) { + return yaml.replace(marker, `${marker}\ntheme: ${theme}`); + } + return yaml + `\ntheme: ${theme}\n`; +} + +/** + * Replace the heroStyle in settings.yaml. + */ +function setHeroStyleInSettingsYaml(yaml: string, style: string): string { + if (/^ heroStyle:\s*/m.test(yaml)) { + return yaml.replace(/^ heroStyle:\s*.+$/m, ` heroStyle: "${style}"`); + } + return yaml; } function startDevServer(): ChildProcess { @@ -126,6 +196,7 @@ function startDevServer(): ChildProcess { cwd: process.cwd(), stdio: 'pipe', env: { ...process.env }, + detached: true, }); // Suppress server output unless DEBUG is set @@ -196,8 +267,8 @@ main().catch((err) => { console.error('āŒ Screenshot generation failed:', err); // Try to restore gallery.yaml on error try { - const original = fs.readFileSync(GALLERY_YAML + '.bak', 'utf8'); - fs.writeFileSync(GALLERY_YAML, original); + const original = fs.readFileSync(SETTINGS_YAML + '.bak', 'utf8'); + fs.writeFileSync(SETTINGS_YAML, original); } catch { // Backup may not exist }