SeanPedersen/demole

★ 0Forks 0CSSGitHub ↗Compare

README

RAW.SCRIPTS

Bilingual (DE/EN) personal site of Philip Demole Lortz — short stories, screenplay work, contact. Built as a static SvelteKit site, prerendered at build time and served as plain files.

Tech

  • SvelteKit + Svelte 5 — routing, SSR/prerender
  • adapter-static — outputs a fully static site to build/
  • mdsvex — Markdown posts rendered as Svelte components (frontmatter parsed automatically)
  • Vite 8 — dev server with HMR
  • TypeScript
  • pnpm

Commands

pnpm install
pnpm run dev       # http://localhost:5173 (HMR)
pnpm run build     # outputs to build/
pnpm run preview   # serve build/ locally
pnpm run check     # svelte-check type check
pnpm run deploy    # build + push to lortz.pages.dev via wrangler

deploy uses pnpm dlx wrangler@latest pages deploy build --project-name=lortz. Wrangler is fetched on demand, so no local install is needed — but you must be logged in once (pnpm dlx wrangler@latest login).

To serve the production build with any static server, e.g.:

python -m http.server 4173 --directory build

Project layout

src/
  app.css                       global styles (responsive rules, hamburger, cards)
  app.html                      SvelteKit HTML shell
  lib/
    components/Header.svelte    top nav + lang toggle + mobile hamburger
    components/Footer.svelte    legal links
    i18n.ts                     Lang type, t(lang), pathPrefix(lang)
    posts.ts                    getAllPosts(lang) — globs src/posts/**/*.md
  params/lang.ts                URL param matcher for /en/
  posts/
    de/*.md                     German posts (frontmatter + body)
    en/*.md                     English posts
  routes/
    +layout.svelte              Header + <slot/> + Footer
    [[lang=lang]]/+page.svelte          home (post grid)
    [[lang=lang]]/post/[slug]/+page.svelte   single post
    [[lang=lang]]/work/+page.svelte     work page
    [[lang=lang]]/contact/+page.svelte  contact page
    datenschutz/+page.svelte    privacy (DE legal)
    impressum/+page.svelte      imprint (DE legal)
static/
  images/                       cover art, work images

Posts

Posts live as Markdown files under src/posts/<lang>/<slug>.md. <lang> is de or en — the folder name is the post's language.

Each post starts with YAML frontmatter:

---
title: "Die Katze"
date: "2025-11-15"                     # ISO, used for sorting
displayDate: "15. Nov. 2025"           # shown in UI
author: "Philip Demole Lortz"
readingTime: "3 Min. Lesezeit"
excerpt: "…short teaser…"
cover: "/images/die-katze.webp"        # path under static/
coverAlt: "Die Katze"
translationSlug: "die-katze-1"         # slug of the counterpart in the other language (optional)
---

Body in Markdown / mdsvex…

Posts are discovered at build time by src/lib/posts.ts via import.meta.glob('/src/posts/*/*.md'). No database, no CMS — add a file, rebuild, it shows up. Sorted by date descending.

Adding a post

  1. Drop the .webp cover into static/images/.
  2. Create src/posts/de/my-slug.md with frontmatter above.
  3. (Optional) Create the translated version at src/posts/en/my-slug-1.md and cross-link them via translationSlug.
  4. pnpm run build.

Routing / i18n

  • / → German home, /en/ → English home.
  • /post/<slug>/ → German post, /en/post/<slug>/ → English post.
  • Language is derived from the URL via the [[lang=lang]] optional param and src/params/lang.ts.
  • pathPrefix(lang) returns '' for de and /en for en; used everywhere links are built.
  • The header's language toggle uses translationSlug from the current post's frontmatter to switch to the matching post in the other language.

Styling

All styles are global in src/app.css. Key responsive breakpoint is max-width: 860px:

  • Header collapses into a hamburger menu (see .hamburger + .site-header.menu-open).
  • Post grid switches to single-column horizontal cards (small square cover on the left, text on the right).

Fonts: Anton (display) + Barlow Condensed (UI) via Google Fonts.

Contributors

SeanPedersen

Issues