Skip to main content
← Back to Projects
Web Development Live Website and CMS

Portfolio CMS (avnishyadav.com)

This site and its back office in one Next.js app

The Next.js site you are reading and its admin CMS: one content layer with design-copy fallback, four AI providers, and SQL changes tested before release.

Solo build

Next.jsTursoPrismaCMSAI Content
01 / Problem

The problem

I write posts, ship projects and run a newsletter, and I wanted one place to do all of it: the public site and the back office in the same codebase, with AI help where it saves time. I also needed every page to render even when the database has nothing for it, and every database change to be checked before it reaches production.

02 / Solution

What I built

The site you are reading. It is one Next.js App Router application with a public side (portfolio, blog, series, projects, offers) and a password-protected admin at /admin where I edit content, draft posts and social copy with AI, manage leads and send newsletters. As of October 2026 it has 43 editable content sections, 4 AI text providers and 92 API routes. The code is private; this page describes how it is put together.

03 / Demo

See it running

Demo coming

A recorded walkthrough of Portfolio CMS (avnishyadav.com) is on the way. Until then, the write-up and the diagram below show how it works.

04 / Architecture

How it fits together

Portfolio CMS (avnishyadav.com)

One content layer for the site and its admin

  1. BrowserPublic pages and /admin behind loginPosts, projects, seriesNewsletters
    requests
  2. Next.js serverNetlify: pages and 92 API routesCached with tagsAI: 4 text providers
    getSection
  3. Content layer43 sections: DB row firstDesign copy fills gaps
    row wins
  4. Tursolibsql/SQLite through Prisma 7SQL files applied twice first
Counts as of October 2026. Claude is the default AI provider, with Gemini, OpenAI and DeepSeek as fallbacks.
05 / Write-up

How it works

Public pages read content through a single content layer. A registry lists each section, where it is stored (its own table or a row in a generic content table) and which design copy it falls back to. The rule is simple: the database row wins and the design copy fills whatever is missing, so a new section looks right before anyone edits it. Reads are cached with tags, and saving a section invalidates its tag.

The AI module wraps four text providers, Anthropic, Google Gemini, OpenAI and DeepSeek, with Claude as the default and a fallback chain through the others. Images come from Gemini, OpenAI or Pollinations. Media lives in Cloudflare R2, email goes out through Resend, and the app runs on Netlify.

Production data lives in Turso. I don't use migrations against it: every schema or content change is a hand-written SQL file. Before I apply one, a script copies production into a local read-only replica, applies the file twice to a throwaway copy and compares the result, so a file that isn't safe to re-run is caught. A production build then runs on that copy and a link checker crawls it. CI repeats the apply-twice check on every push. Long-form series, like the Salesforce Headless 360 series (coming soon), are Markdown files in the repo built into the same kind of SQL file.

Status and links

Live at avnishyadav.com and in active development. The repository is private, so there is no code link. The counts above are taken from the code as of October 2026 and will change as the site grows.

Work with me

Need something like this built?

I build AI automations, agents and Salesforce solutions for teams. Tell me what you want to automate and I’ll tell you honestly whether it’s a fit.

Share
Discussion

Comments

Loading comments...

Add a comment

Comments are reviewed before they appear.