Our Feature Flags course is now live!
Marketing website with zero-cost CMSNEW

Setup Pages CMS

We will connect to the online version of Pages CMS.

What is Pages CMS?

Pages CMS is a free, open-source content management system that works directly with your Git repository. It allows non-technical users to edit website content in a simple web interface—no need to touch code, Git, or Markdown directly.

The online version of Pages CMS makes setup easy: you don’t need to self-host, and everything stays in sync with your repo automatically. Though if you want to, you can self-host it easily.

How does it work?

Pages CMS works by connecting directly to your GitHub repository. Instead of storing content in a separate database, it edits the Markdown (or other content) files that already live inside your repo.

Here’s the flow:

  1. User edits content A user logs into Pages CMS and edits text, images, or metadata through a clean web interface.

  2. Pages CMS commits changes When they hit save, Pages CMS creates a commit in your GitHub repository—just like a developer would.

  3. Your site rebuilds Since your hosting provider (like Netlify or Vercel) is watching the repo, any new commit automatically triggers a rebuild and deployment.

  4. Updated site goes live The updated content appears on the live website, with no developer involvement required.

In short: Pages CMS acts as a Git-based editor for your content. It gives users a friendly UI, while you still keep the simplicity and power of a fully static site.

Setup Pages CMS

This is quite easy.

  1. Sign In with your GitHub account here.

  2. Then you will be prompted to add an account.

Pages CMS prompt to add a GitHub account after signing in

If you notice, I already have my company's GitHub account linked here. I already use Pages CMS in production, I liked it, hence I am creating this course to teach you a great tool.

  1. Choose the account where you want to install the Pages CMS client. (This is safe!)

List of GitHub accounts available to connect with Pages CMS

  1. But ideally, only install it for select repositories for better security. (Highly recommended!)

Option to install Pages CMS only for selected repositories for better security

  1. After installing the Pages CMS app, you will land up on a page asking you to create a configuration file. By the way, if you want to do this on a different branch you can do that by selecting the dropdown with your account to top-left.

Pages CMS interface showing option to create a configuration file with branch selector

  1. The moment you click on the "Create a configuration file", it creates a file and commits it to the repo.

Confirmation screen where Pages CMS has created and committed the configuration file to the repo

Astro project structure

Let us quickly have a look at how our Astro project is structured.

first-post.md
markdown-style-guide.md
second-post.md
third-post.md
consts.ts
content.config.ts
astro.config.mjs
package.json
pnpm-lock.yaml
tsconfig.json

The "blog" content is at the root of the repository. This folder holds our assets (images) and individual blog posts as markdown files. You can quickly check out the structure of each blog post or have a look at the content.config.ts, this is an Astro feature that helps provide better type-safety with your content.

first-post.md
---
title: 'First post'
description: 'Lorem ipsum dolor sit amet'
pubDate: 'Jul 08 2022'
heroImage: './assets/blog-placeholder-3.jpg'
---
 
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
src/content.config.ts
import { glob } from 'astro/loaders';
import { defineCollection, z } from 'astro:content';
 
const blog = defineCollection({
  loader: glob({ base: 'blog', pattern: '**/*.{md,mdx}' }),
  schema: ({ image }) =>
    z.object({
      title: z.string(),
      description: z.string(),
      pubDate: z.coerce.date(),
      heroImage: image().optional(),
    }),
});
 
export const collections = { blog };

These files should help you understand our blog posts structure.

We will now setup Pages CMS to work with this structure. We can do this with configuration file.

.pages.yml configuration file

Let us first try to have a look at our assets (images in this case) through Pages CMS.

We know this stuff because it is well documented!

Media

  1. We tell Pages CMS, the location of our Media (assets) with input, and the relative path with the output (we will talk more about output soon).
.pages.yml
media:
  input: blog/assets
  output: assets

  1. Save, and you should immediately see a Media tab on the dashboard.

  1. Check the Media tab out and you will see all the assets you have in the repo.

So, you should be getting the idea of how Pages CMS works. Let us now try to also wire up the actual content.

Content

  1. Just like our media setup, we will add a new key content in our settings.
.pages.yml
media:
  input: blog/assets
  output: assets
content:
  - name: posts
    type: collections
    path: blog

  1. Save, and you should immediately see a posts tab on the dashboard.

  1. Try editing one of the posts.

  1. There should be commit when you save the changes.

  1. Let us have a way better view and editing interface.
.pages.yml
media:
  input: blog/assets
  output: assets
content:
  - name: posts
    type: collection
    path: blog
    fields:
      - name: title
        label: Title
        type: string
      - name: description
        label: Description
        type: text
      - name: pubDate
        label: Published Date
        type: date
      - name: heroImage
        label: Hero Image
        type: image
    view:
      fields: [title, description, pubDate, heroImage]

  1. Hmm, the images are broken. This is where understanding the output of media is important. This should translate to the relative location of the asset to your content file. So, in our case that is ./assets
.pages.yml
media:
  input: blog/assets
  output: ./assets
  output: assets
content:
  - name: posts
    type: collection
    path: blog
    fields:
      - name: title
        label: Title
        type: string
      - name: description
        label: Description
        type: text
      - name: pubDate
        label: Published Date
        type: date
      - name: heroImage
        label: Hero Image
        type: image
    view:
      fields: [title, description, pubDate, heroImage]

  1. But dates are still broken. Let us see why.

  1. Ahaan, we have a different format than dd/mm/yyyy, luckily the author of Pages CMS gave us an option to configure this too!
.pages.yml
media:
  input: blog/assets
  output: ./assets
content:
  - name: posts
    type: collection
    path: blog
    fields:
      - name: title
        label: Title
        type: string
      - name: description
        label: Description
        type: text
      - name: pubDate
        label: Published Date
        type: date
        options:
          format: MMM dd yyyy
      - name: heroImage
        label: Hero Image
        type: image
    view:
      fields: [title, description, pubDate, heroImage]

  1. Perfect! Let us do a final touch and bring in the rich-text block for the major content.
.pages.yml
media:
  input: blog/assets
  output: ./assets
content:
  - name: posts
    type: collection
    path: blog
    fields:
      - name: title
        label: Title
        type: string
      - name: description
        label: Description
        type: text
      - name: pubDate
        label: Published Date
        type: date
        options:
          format: MMM dd yyyy
      - name: heroImage
        label: Hero Image
        type: image
      - name: body
        label: Body
        type: rich-text
    view:
      fields: [title, description, pubDate, heroImage]

  1. This is a nice editor with good / support to add markdown nodes!

In case you got lost, the final code should be available in the branch 1-pages-cms, the only file you have to care about is the .pages.yml file.

Invite collaborators

Now, how do you give your team the access to edit this content without them having GitHub account and go through the whole permissions thing?

Well, the author gave us a flow to invite your team through email!

More features are in the pipeline

This is a great product in our opinion and one to support and keep an eye on!

Support the author!

Ronan Berder is the person behind this amazing project! If you like it and you use it in some capacity, consider sponsoring!

Last updated on

On this page