All work
An animated studio portfolio that barely uses any JavaScript
Astro 6Svelte 5PartytownContent collectionsTypeScript
5Hydrated islands; the rest of the site is static HTML
0Analytics code on the main thread
5Image presets shared between Astro and Svelte components
- The design called for a continuously running reel carousel, a full-screen gallery lightbox and scroll-driven reveals -- the kind of motion that usually arrives as a heavy client bundle.
- Case studies needed to be data, so adding one did not mean writing another page.
- Analytics is non-negotiable for the client and is also the single biggest main-thread cost on a site like this.
- Used islands as a budget rather than a convenience: five hydrated components across the whole site, each chosen because it genuinely needs client state.
- Modelled projects as a typed content collection with images declared in the schema, so images are validated and optimised at build time alongside the copy.
- Built one image preset system feeding both the Astro components and the Svelte islands, so both render the same responsive sources.
- Moved analytics off the main thread into a web worker, with an escape hatch so the client's tag debugger still works.
- Adding a case study is a Markdown file and a folder of images; the route, the sitemap entry and the optimised sources follow.
- The motion runs without the bundle usually attached to it, and switches itself off entirely for visitors who ask for reduced motion.
- Every page carries canonical, Open Graph and Twitter metadata from one builder, with a generated sitemap.
Technical detail
- The carousel pauses when the tab is hidden, when the pointer is over it, and until fonts have finished loading -- because starting a measured animation before the webfont swaps makes it jump on first paint.
- Reduced-motion handling is in both the CSS and the JavaScript. CSS alone stops the transition but leaves the observer running, so the script checks too and skips the work.
- Images go through the build pipeline as WebP with explicit width sets. The Svelte islands cannot call the build-time image API, so presets are resolved in Astro and passed down as pre-built source sets, which keeps one definition of each size.
- A single frontmatter flag hides a work-in-progress case study from both the routes and the sitemap, so unfinished content stays in the repository instead of living on a branch.
- The analytics worker is bypassed when a debug query parameter is present, because tag-assistant tools cannot see a worker and the client needed to verify their own tracking.
- The lightbox traps focus, handles arrow and escape keys, and marks decorative clones aria-hidden with negative tabindex, so the duplicated carousel nodes are not announced twice.