Setup
This site is built with SvelteKit and prerendered to static files. There is no server, no database and no UI component library.
- Framework
- SvelteKit 3, Svelte 5, adapter-static
- Styling
- Tailwind CSS 4, JetBrains Mono (self-hosted), Vesper palette
- Languages
- English and Danish with Paraglide
- Hosting
- Cloudflare Pages
No client-side framework
All routes are rendered to HTML at build time and client-side rendering is turned off. The browser receives HTML and CSS, not the Svelte runtime.
// src/routes/+layout.ts
export const prerender = true;
export const csr = false; The theme switch, the sticky header, the scroll effects and the image lightbox are handled by one
inline script in app.html. The script only changes attributes and CSS variables on
the page. The visuals and animations themselves are done in CSS.
Scroll-driven text
On the front page, the highlight text lights up word by word while scrolling. The script writes
the scroll progress to --p, and each word has its own position in --w.
.word {
opacity: clamp(0.25, calc((var(--p) - var(--w)) * 6 + 1), 1);
} Fonts and images
- The font files contain only Latin and Danish characters, which cuts each one from 93 KB to 40 KB.
- Screenshots are generated as AVIF and WebP in three widths, so a phone downloads a smaller file than a desktop. They are below the first screen, so they load lazily: the browser fetches them when the visitor scrolls near them, not on page load.
- The mobile menu and the lightbox use the HTML Popover API instead of a script.
Search and sharing
Each page sets its own title, description and Open Graph tags through one
component. The layout adds the canonical URL and hreflang links, so search engines treat
the English and Danish versions as the same page in two languages.
sitemap.xmlis a prerendered route that lists every page in both languages. New entries under /work are added automatically.- The front page includes JSON-LD describing a
Personand aWebSite. - A 1200 x 630 image is used as the preview when a link is shared.
Workflow
Conventional Commits, one branch per change, pull requests into main. pnpm verify runs formatting, linting, the build and type checking.
Note