Skip to content

asahi-fj/structcms

Repository files navigation

structcms

Use GitHub as a headless CMS. Fetch and transform content stored in a GitHub repository via the GitHub API.

Why structcms?

structcms treats a GitHub repository as your content store — no extra infrastructure, no vendor lock-in.

Feature structcms Outstatic Decap CMS Contentlayer
Zero added infrastructure ✅ No DB, no server ⚠️ Needs Git Gateway / Netlify
Separate content & app repos ✅ Any repo, any owner ❌ Same repo only ⚠️ Manual config ❌ Local files only
Private repository support ✅ Token-based access ❌ Public repos only ⚠️ Limited
Setup requirement GitHub Token only GitHub OAuth App Netlify / OAuth Local file system

How it works

Store content under a contents/ directory in any GitHub repository. Each piece of content lives in its own slug-named folder with a Markdown file and a JSON metadata file.

your-content-repo/
└── contents/
    ├── hello-world/
    │   ├── content.md
    │   └── meta.json
    └── my-second-post/
        ├── content.md
        └── meta.json

Installation

npm install @asahi-fj/structcms

Quick start

import StructCms from "@asahi-fj/structcms";

const cms = StructCms({
  token: process.env.GITHUB_TOKEN!,
  owner: "your-org",
  repo: "your-content-repo",
});

const posts = await cms.getAll();
// [{ slug: "hello-world", content: "# Hello\n...", meta: { title: "Hello World", ... } }]

See USAGE.md for full examples.

Content format

meta.json

{
  "title": "Post title",
  "description": "A short description",
  "publishedAt": "2026-04-11",
  "draft": false,
  "tags": ["typescript", "cms"]
}

content.md — standard Markdown.

API

Method Description
cms.getAll() Fetch all content entries
cms.getById(id) Fetch a single entry by slug (coming soon)

Requirements

  • Node.js 18+
  • GitHub Personal Access Token with read access to the content repository

License

ISC

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors