Simplicity of Sanity.io

I wanted a personal blog - a space to organize, record, and share things capturing my interest in the development field. My first instinct was the tried-and-true path: WordPress.
I even went as far as creating a custom theme, but soon, a familiar feeling crept in. Being tied to a single, monolithic platform didn't sound fun or engaging. Look, I know WordPress is great, especially for blogging, but as a developer, I knew I had the experience to build a simpler, more custom experience.
If you’ve dealt with WordPress before, you've probably run into the common frustrations: the bloat, the constant plugin updates, and the annoying, breaking changes that occur when any part of the platform, a plugin, or a theme is updated.
Before deploying the WP site, I changed my mind. I decided to start from the ground up using a headless CMS.
The Freedom and Flexibility of Headless
A headless CMS is an architecture where the "head" (the frontend/presentation layer) is completely decoupled from the "body" (the backend/content repository like Sanity.io).
- Traditional CMS: Content management and content delivery are tightly coupled and bound by their platform.
- Headless CMS: Content is stored and managed separately, and delivered via an API (Application Programming Interface). This allows developers to use any frontend framework they choose.
Frameworks are always changing and evolving. Using a headless CMS not only allows the freedom to choose your presentation languages but also your deployment environments. You can switch between frontend implementations without the annoying migration process to move your content data to a new platform. The content is future-proofed.
Enter Sanity.io
I was looking for something that allowed me to easily define my CMS objects and fields, and that I could use with React and Next.js. Having worked primarily in a Laravel no-SPA stack lately, I missed building with the React/Next stack.
Sanity.io fit the bill perfectly. I chose it for several key reasons:
- Generous Free Tier: Great for personal projects.
- Built with React: The Sanity Studio itself is a React application.
- Flexible JSON Structure: All objects are stored as JSON, making them incredibly flexible to both create and consume.
- Intuitive Querying (GROQ): While it's another proprietary query syntax, GROQ (Graph-Relational Object Queries) is fast and intuitive for shaping the data you need.
Setting Up the Sanity Studio
The Sanity Studio is the content editor and design tool where you define your content structure and manage your posts. (This is separate from the Sanity Management Console, which handles administrative settings.)
1. Initialize the Studio
bashnpm create sanity@latestFollow the prompts to create a new project. For a blog, selecting "schema" and a "clean project" is a great starting point.
2. Define Schemas
The content structure is defined in schema files. Here is the definition for a typical blog post:
typescript// post.ts
import { allBlocks } from "./blocks";
import seo from './schemaObjects/seo';
export default {
name: 'post',
title: 'Post',
type: 'document',
fields: [
{ name: 'title', type: 'string', title: 'Title' },
{ name: 'slug', type: 'slug', title: 'Slug', options: { source: 'title' } },
{
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true, // Allows for cropping
},
fields: [
{
name: 'alt',
type: 'string',
title: 'Alternative text',
description: 'A brief description for search engines and screen readers.',
},
],
},
{
name: 'excerpt',
title: 'Excerpt',
type: 'string',
description: 'A brief summary of the post for previews.',
},
{
name: 'publishedDate',
title: 'Published Date',
type: 'datetime',
options: {
dateFormat: 'YYYY-MM-DD',
timeFormat: 'HH:mm',
timeStep: 15,
},
},
{ name: 'body', type: 'array', title: 'Body', of: allBlocks },
{ name: 'categories', type: 'array', title: 'Categories', of: [{ type: 'reference', to: [{ type: 'category' }] }] },
{ name: 'tags', type: 'array', title: 'Tags', of: [{ type: 'reference', to: [{ type: 'tag' }] }] },
{ name: 'seo', type: 'seo', title: 'Post SEO' },
],
};What is Sanity Portable Text?
Notice the body field is an array. This uses Sanity Portable Text, their method for handling rich text (like paragraphs, lists, and images). It stores content as a structured array of JSON objects instead of a single block of messy HTML.
This is the key to flexibility: the content is decoupled from its presentation, allowing your frontend to completely control how the data is rendered.
Connecting Next.js to Sanity
Next, we build the frontend "head." I created a Next.js application with TypeScript using create-next-app.
1. Install Dependencies
You'll need the client library to communicate with Sanity:
bashnpm install @sanity/client2. Connect to Sanity
Create a file (e.g., lib/sanity.ts) to configure the client. We use environment variables for security.
typescript// lib/sanity.ts
import { createClient } from "@sanity/client";
export const sanityClient = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
});Make sure to create a .env.local file in your project root with your credentials:
NEXT_PUBLIC_SANITY_PROJECT_ID="your-project-id"
NEXT_PUBLIC_SANITY_DATASET="production"
3. Fetching Data with GROQ
To fetch content, your Next.js application uses GROQ (Graph-Relational Object Queries). It allows you to use a single string expression to select, shape, and project exactly the data you need, bypassing the need for complex REST endpoints or GraphQL schema setup. This makes things incredibly fast.
Here is an example query to fetch a single blog post:
javascriptasync function getPostData(slug: string): Promise<IPost> {
const query = `
*[_type == "post" && slug.current == $slug][0] {
title,
slug,
body,
"publishedAt": publishedDate,
"updatedAt": _updatedAt,
mainImage,
categories[]->,
tags[]->,
seo
}
`;
const post = await sanityClient.fetch(query, { slug });
return post;
}Beyond the Blog
I built this simple blog for my personal use, and Sanity.io is a perfect fit for me. However, if I were implementing a solution for a client whose primary requirement was feature-rich content creation, I might still recommend a more robust, dedicated blogging platform, or allocate significantly more time to customize the Sanity Studio to achieve feature parity with a traditional blogging WYSIWYG, or more modern editable UI.
The real beauty and power of Sanity.io lies in its versatility. With the flexibility to easily define your own schemas and to shape the returned data objects with GROQ, I can see many applications for Sanity far beyond a simple blog, such as:
E-Commerce Product Catalogs: Managing product details, variations, and structured metadata.
Documentation Sites: Defining hierarchies, metadata, and linked information.
Configuration Hubs: Storing and serving global application settings or feature flags.
Empowering Content Managers: allows content creators to easily edit and update information, images, and structured content without requiring a developer to touch the underlying code or deployment process.
Taking the time to build a custom solution using Sanity.io has been incredibly rewarding. It was a lot of fun to explore the ins and outs of this platform, and I look forward to continuing to build with it and discovering its full range of applications in future projects.
Ready to
Connect?
For professional inquiries, feedback, or any other questions, please use the form on the contact page