arrow_back Back to Blog
Engineering 3 min read

Building a CMS-Driven Portfolio with Sanity and SvelteKit

Oladokun Oladipupo

Oladokun Oladipupo

Published November 20, 2024

Building a CMS-Driven Portfolio with Sanity and SvelteKit

Choosing a CMS for a modern web project is about more than just the editing experience. It's about how the content model maps to your frontend, how you query it, and whether your editors will actually use it. After building several projects with Sanity, here's what I've learned.

Why Sanity?

Sanity positions itself as a "content platform" rather than just a CMS. The key differentiators that made me choose it over alternatives like Contentful or Strapi:

  • Schema-as-code — your content model lives in TypeScript files, not a GUI
  • GROQ — a powerful query language that feels natural for JSON documents
  • Real-time collaborative editing with conflict resolution built-in
  • Portable Text — a structured rich-text format that renders anywhere
  • Self-hosted Studio — fully customisable admin panel you control

Integrating with SvelteKit

The Client Setup

The official @sanity/client package works seamlessly in SvelteKit's server-side load functions. The key is keeping your token server-side and using the CDN client for public reads:

GROQ Queries

GROQ (Graph-Relational Object Queries) takes some getting used to, but it's remarkably expressive. A typical query for a portfolio project list looks like:

"The best part of GROQ is the projection syntax — you specify exactly what fields to return, so you never over-fetch."

Portable Text Rendering

Portable Text is Sanity's answer to the rich-text storage problem. Instead of storing HTML, it stores a normalised block structure that you render with a library — in our case @portabletext/svelte.

Custom block renderers let you handle code blocks, images, and any custom types you define in your schema. The rendering is fully under your control.

Schema Design Tips

After building multiple projects with Sanity, these patterns have saved me the most time:

  • Use
  • Define a shared
  • Use
  • Keep your rich-text schemas tight — only enable block types you actually need
  • Validation rules in your schema catch data issues before they reach the frontend

Performance Considerations

Sanity's CDN is fast, but for a portfolio site you want zero CMS latency on page loads. The solution is SvelteKit's server-side rendering with a short cache TTL:

With this setup, the first request fetches from Sanity and caches the result. Subsequent requests are served from edge cache until the TTL expires. For a portfolio site with infrequent content changes, a 60-second TTL is perfectly fine.

Final Thoughts

Sanity + SvelteKit is one of my favourite stacks right now. The type-safe schema, the expressive query language, and SvelteKit's flexible rendering modes make for a very pleasant development experience. The learning curve is real but shallow — most developers are productive within a day.

Share this post
arrow_back All Posts
Oladokun Oladipupo

Written by Oladokun Oladipupo

I specialize in turning ideas into high-performing digital products — from frontend interfaces, to scalable backends using modern frameworks. Whether working solo or as part of a remote team, I bring a detail-oriented, user-focused approach to everything I build.

Follow on LinkedIn
Book a Call arrow_forward Start a Project arrow_forward Book a Call arrow_forward Start a Project arrow_forward