Next.jsMDXVercelArchitecture

Building a Database-less Blog on Vercel Blob with MDX

How I added a fully editable, SEO-ready blog to my portfolio using MDX and Vercel Blob — no database, no CMS, just content stored as objects and an admin editor gated behind TinTorch SSO.

Anuj Pandey··3 min read
Building a Database-less Blog on Vercel Blob with MDX

Most personal blogs reach for a database far too early. A database means migrations, a connection pool, a hosting bill, and a backup story — for what is, in the end, a handful of articles that change a few times a month. So when I rebuilt the writing section of this site, I set myself one rule: no database. Content lives as plain objects in Vercel Blob, and the entire publishing workflow runs on top of it.

This first post is a tour of how that works.

Why Blob instead of a database

A blog post is just text plus a little metadata. Vercel Blob gives me durable, CDN-backed object storage with a one-line put() API. Each article is a single JSON object:

await put(`blog/posts/${slug}.json`, JSON.stringify(post), {
  access: 'public',
  contentType: 'application/json',
  allowOverwrite: true,
})

Listing posts is a list({ prefix: 'blog/posts/' }). Reading one is a fetch() of its public URL. There is no schema to migrate and nothing to keep running. When the blob store is empty — say, on a fresh deploy — the app falls back to a small set of seed posts baked into the bundle, so the blog is never blank.

MDX for the writing experience

Articles are authored in MDX, so prose and the occasional React component live side by side. Rendering happens on the server with next-mdx-remote/rsc, which compiles the MDX string pulled from Blob at request time:

import { MDXRemote } from 'next-mdx-remote/rsc'

<MDXRemote source={post.content} components={mdxComponents} />

A remark-gfm plugin handles tables and strikethrough; rehype-slug gives every heading an anchor. Code blocks get syntax highlighting. The result is a reading experience that feels handcrafted but is driven entirely by content.

SEO and Open Graph, baked in

Every post exports a Next.js generateMetadata function, so each article ships with its own title, description, canonical URL, Open Graph card and Twitter summary. Search engines and social previews get exactly what they expect, per-page, with zero manual <head> juggling.

Editing without a CMS

The admin lives at a quiet route that isn't linked anywhere on the site. It's gated behind TinTorch single sign-on, and only a short allow-list of admin emails can get in. Once authenticated, I get a clean black-on-white editor: write MDX on the left, see it rendered live on the right, fill in the SEO fields, and hit publish. Saving writes the JSON object to Blob and the post is live.

That's the whole system — storage, rendering, SEO and editing — with no database in sight. The rest of this blog is where I'll write about engineering, Web3, and the occasional cricket tangent.

Frequently asked questions

Do I need a database to run this blog?+

No. Every post is a single JSON object in Vercel Blob, with a small set of seed posts baked into the app as a fallback. There is nothing to migrate or keep running.

How is the content cached?+

Posts are held in Next.js' Data Cache under a tag and served indefinitely. The cache is only invalidated — via revalidateTag — when a post is created, edited or deleted, so reads almost never touch Blob.

Who can edit posts?+

Only the emails on the admin allow-list, after signing in with TinTorch single sign-on. The editor lives on a route that isn't linked anywhere on the public site.

Is it good for SEO?+

Yes — every post ships per-page Open Graph and Twitter tags, canonical URLs, BlogPosting structured data, and FAQPage structured data generated from blocks exactly like this one.