Oliver Wolfson
ServicesProjectsContact

Development Services

SaaS apps · AI systems · MVP builds · Technical consulting

Services·Blog
© 2026 O. Wolf. All rights reserved.
webdevelopmentdeployment
GitHub-Backed MDX Editing in owolf-dot-com
How owolf-dot-com writes MDX to GitHub in production, reads it back for admin editing, and triggers Vercel deploys from commit-based saves.
February 9, 2026•O. Wolfson

In owolf-dot-com, content lives as MDX files under content/. Locally, the editor writes straight to disk. In production, the editor writes to GitHub through the Contents API, which creates a commit. That commit triggers a Vercel deployment when the repo is connected to the project.

This post covers the production path, the dev path, and how the deploy gets kicked off.

The core idea

There are two separate flows:

  • Public pages are static. Blog and study pages are built from content/ at build time.
  • Admin editor reads and writes raw MDX so you can edit content post-deploy.

That split lets the site stay fast and static while still enabling production edits.

Production vs development

Development (local)

  • Reads from local filesystem (content/blog, content/study).
  • Writes to local filesystem.
  • No GitHub token required.

Production (deployed)

  • Reads raw MDX from GitHub when loading the admin editor.
  • Writes raw MDX to GitHub when saving from the admin editor.
  • Requires GITHUB_PAT with Contents read/write permissions.

The public blog pages are still built from the repository at deploy time, which keeps them static and fast.

How the save works

The admin editor calls a server action that writes to GitHub. The implementation uses the Contents API, which creates a commit in the repo.

// src/app/actions/blog/save-post.ts
await createOrUpdateFile(token, "content/blog/my-post.mdx", content, commitMessage);

Under the hood, this is a PUT to:

https://api.github.com/repos/owolfdev/owolfsite/contents/content/blog/my-post.mdx

GitHub creates a commit with the provided message, and that commit becomes the deploy trigger.

How the admin editor reads in production

The admin edit page now reads from GitHub in production instead of local disk. It fetches the raw MDX file and passes it into the Monaco editor.

// src/app/admin/blog/edit/[slug]/page.tsx
const filePath = `content/blog/${slug}.mdx`;
const mdxSource = await getFileContent(token, filePath);

That ensures the editor always reflects the repo state, not the build artifact.

Why the deploy triggers

Vercel deploys on GitHub commits when:

  • The project is connected to the repo.
  • The production branch matches the branch the commit landed on.
  • Deploys are not explicitly ignored for that push.

Because the save action creates a real commit on the connected branch, Vercel sees a new commit and kicks off a deployment.

Notes and gotchas

  • Token scope: fine-grained PATs must include Contents: Read and write for owolfdev/owolfsite.
  • Missing token: production reads and writes will fail without GITHUB_PAT.
  • Static pages: public pages are static and only update after a deploy.

If you want to test the production flow locally, you can set GITHUB_PAT in .env.local and run with a production build.

Tags
#github#vercel#nextjs#mdx#cms