




What is inside
Kiri Studio gives creative teams two complete visual modes without duplicating components. The visitor’s theme choice persists, work and articles come from typed collections, and the animated menu and custom cursor add character while preserving keyboard access and reduced-motion support.
Light and dark, remembered
The theme is resolved by an inline script before the first paint, so there is no flash. It persists in localStorage and follows the OS until the visitor picks.
An animated fullscreen menu
A desktop hover carousel with a blur effect and the current route highlighted, closing on Escape with focus put back where it was.
Works and a blog, both in files
Case studies with cover, grid and hover images, and a paginated blog with its own RSS feed. Related content is resolved for you.
Reveals you add with an attribute
Scroll animations and the hero intro come from data attributes read by one library, with a programmatic escape hatch when you need it.
Smooth scrolling, synced to the ticker
One Lenis instance wired to GSAP ScrollTrigger in the layout, so pinned sections and reveals never drift against the scroll.
Responsive images, no round-trips
Every image is a local asset and sharp builds a srcset per image at build time. There is no remote path, by design.
A contact form behind a provider interface
Zod validation, honeypot, Upstash rate limiting and Resend delivery, with the provider swappable in one file.
A custom cursor
SVG cursors for the default and interactive states, driven from pointer position so they stay correct while the page is scrolling.
Typed content collections. You write a file, and the listing, the detail page, the feed and the sitemap pick it up on the next build.
src/content/works/*.mdxCase studies with cover, optional grid and hover images, tags, client and date. Featured entries appear on the home page.src/content/blogs/*.mdPosts with topics, date and reading time. They join the paginated listing, the RSS feed and the sitemap.src/content/legals/*.mdTitle and description. The filename becomes the route.src/config/*.data.tsNavigation, social links and the structured data the sections render, all typed.---
title: 'Olmo Studio'
description: 'Brand identity and product site for a design studio.'
coverImage: '../../assets/img-projects/09.webp'
tags: ['Branding', 'Web Development']
date: 2026-02-10
client: 'Olmo'
featured: true
---The copy
src/config/labels.tsEvery string and every SEO field, read through a typed helper. An unknown key fails the build rather than rendering nothing.
The typefaces
astro.config.mjsA local display face and a Google body face, each declared with explicit weights and subsets so you ship two files and not nine.
The two palettes
src/styles/global.cssLight and dark are two sets of custom properties on the same token names, exposed to Tailwind through one theme block.
Both have a free tier, and the contact form needs them: the ZIP ships an .env.template with the variables to fill in.
A README written for this template, not copied between them, inside the ZIP. It covers:
Try any demo before you decide
The demos are the real templates, deployed. No signup, no email in the way.





