The Remix Blog Stack

Roger Stringer

Roger Stringer / September 1, 2022

4 min read

The Remix Blog Stack is a Remix stack I wrote for quickly building an MDX blog in Remix, it's had a few revisions recently so I thought I'd share how to get it set up and running.

To get started, you can fork the repo or run the following command:

npx create-remix --template freekrai/remix-blog


By default, remix-blog will try to use the file system to read files, this works great but if you are on a hosting service like cloudflare where you can't access the file system then we need to use Github, you can configure how it accesses files in your .env file:

  • SESSION_SECRET: Session Secret used for sessions such as dark mode
  • USE_FILESYSTEM_OR_GITHUB: this is either fs or gh
  • GITHUB_TOKEN: your Personal access token
  • GITHUB_OWNER: your Github name
  • GITHUB_REPO: your Github repo

The Github variables are only needed if USE_FILESYSTEM_OR_GITHUB is set to gh, it's fs by default.

This does allow you to do things like have one repo for the codebase and one for just content which can be handy.



To run your Remix app locally, first, copy .env.example to .env and configure as needed following the Config step above.

Next, make sure your project's local dependencies are installed:

npm install

Afterwards, start the Remix development server like so:

npm run dev

Open up http://localhost:3000 and you should be ready to go!



It's been set up so that you have flexiblity in terms of content, for example the default setup is:

  • content: where mdx is stored
  • content/posts: blog posts, stored as: SLUG/index.mdx
  • content/pages: pages, stored as SLUG/index.mdx

The structure is based on Gatsby and gives more flexibility, each page and post is a folder and contains an index.mdx file, this folder name becomes the slug.

This can be used to create other content types as well, posts, pages, workshops, snippets, anything you want and then just call it, you can look at the blog files for using an entire post type.

This can be expanded further, for example, you can have multiple files and folders inside one folder:

  • content/posts/hello-world/index.mdx returns as /hello-world
  • content/posts/hello-world/abc.mdx returns as /hello-world/abc
  • content/posts/hello-world/more-hello/index.mdx returns as hello-world/more-hello
  • content/posts/hello/still-hello/index.mdx returns as hello/still-hello
  • content/posts/2022/test/index.mdx returns as /2022/test

This lets you structure content however you want.

On build, the stack generates a json file in content (blog-cache.json) for all blog posts, which is then referenced later for the blog index, rss, sitemap, etc.

The stack also generates a separate json file in content (page-cache.json) for all pages, this can then be used for sitemap, etc as well.

If you are doing other content types besides posts and pages, you may want to edit scripts/cachePosts.ts and follow what was done for getPosts and getPages functions to create a cache file for each of those as well, the app uses these as a sort of read-only database.

Mdx files contain frontmatter which is used to know about each post, this frontmatter looks like:

  title: Another Post
  description: A description
date: '2021-10-02T00:00:00'
excerpt: Hello Gaseous cloud...
  Cache-Control: no-cache


Initially, this stack is set up for deploying to Vercel, but it can be deployed to other hosts quickly and I'll update the wiki with instructions for each, but to get started on Vercel:

Open server.js and save it as:

import { createRequestHandler } from "@remix-run/vercel";
import * as build from "@remix-run/dev/server-build";
export default createRequestHandler({ build, mode: process.env.NODE_ENV });

Then update your remix.config.js file as follows:

/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
  serverBuildTarget: "vercel",
  server: process.env.NODE_ENV === "development" ? undefined : "./server.js",
  ignoredRouteFiles: ["**/.*"],

This will instruct your Remix app to use the Vercel runtime, after doing this, you only need to import your Git repository into Vercel, and it will be deployed.

If you'd like to avoid using a Git repository, you can also deploy the directory by running Vercel CLI:

npm i -g vercel

It is generally recommended to use a Git repository, because future commits will then automatically be deployed by Vercel, through its Git Integration.

This repo is open for pull requests and ideas to expand on it, but I wanted to make it flexible to start off.

Do you like my content?

Sponsor Me On Github