



What is inside
Acacia Studio pairs a warm, organic art direction with an automatically rotating canvas globe and a content-driven portfolio. Projects, articles and legal pages live in typed collections, while the contact route is ready for real leads with server validation, anti-spam protection and Resend delivery.
A globe that draws itself
The hero is a hand-written canvas renderer, not a 3D library, and it stops painting the moment it scrolls out of view.
A warm, organic design system
Seven colour tokens, dashed grid rules and three self-hosted families. Change the tokens and every surface, chip and border follows.
Case studies and a blog, both in files
Projects in MDX, articles in Markdown, legal pages alongside them. Slugs come from filenames and routes appear on the next build.
Animations you add with an attribute
Scroll reveals come from data-anim attributes read by one shared library. No per-component GSAP, and a guard against the flash of unstyled content.
Smooth scrolling with a live article index
Lenis drives the scroll, same-page anchors animate to their target, and the article index follows the heading you are reading.
A contact form that works without JavaScript
Zod validation on the server, honeypot, Upstash rate limiting and Resend delivery. With JS off the errors still come back rendered.
Images with real srcset and sizes
One entry point, every source local, sharp doing the work at build time. No remote fetches, so the build runs offline.
Motion that asks before it moves
Every animation honours prefers-reduced-motion, and nothing is hidden behind an opacity that JavaScript has to undo.
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/projects/*.mdxCase studies with client, tags, date and a brand icon. Marking one as featured surfaces it on the home page.src/content/blogs/*.mdArticles with topics, author and reading time. They join the listing, the RSS feed and the sitemap.src/content/legals/*.mdThe filename becomes the route.src/config/*.data.tsServices, process, clients, testimonials, FAQ and the contact form's own dropdown options, all typed.---
title: 'Olmo Studio'
description: 'A portfolio template.'
coverImage: '../../assets/works/olmo-studio/olmo-01.webp'
tags: ['Web Design', 'Web Development']
client: 'Olmo'
clientLink: 'https://example.com'
date: 2026-01-16
featured: true
icon: 'olmo-logo'
---The copy
src/config/labels.tsEvery user-facing string, every aria-label and all the SEO text, read through a typed helper. An unknown key fails the build instead of shipping empty.
The typefaces
astro.config.mjsThree self-hosted families declared in one block. Nothing is fetched from a font CDN at runtime, and the weights you load are the weights you asked for.
The palette
src/styles/global.cssSeven colour tokens in the theme block. There are no arbitrary colour values anywhere in the source, so changing a token changes the site.
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.





