Skip to content

How It Works

Understanding the GitCMS architecture and workflow.

Architecture Overview

GitCMS uses GitHub as the single source of truth for all content. Here's how the pieces fit together:

Components

1. Admin Panel

Purpose: Visual content management interface

Key Features:

  • Web-based UI (no installation)
  • GitHub OAuth authentication
  • Schema designer
  • Rich text editor
  • Media uploader

Technology Stack:

  • Next.js (React framework)
  • TipTap (rich text editor)
  • TailwindCSS (styling)
  • Octokit (GitHub API client)

URL: gitcms-admin.bestplayer.dev

2. GitHub Repository

Purpose: Content storage and version control

What's Stored:

  • Content files (JSON/Markdown)
  • Media files (images, videos, etc.)
  • Schema definitions
  • Configuration

Benefits:

  • Free hosting
  • Automatic backups
  • Version history
  • Collaboration features
  • Branch workflows

3. Client SDK

Purpose: Fetch and display content in applications

Key Features:

  • TypeScript SDK
  • SQL-like queries
  • Progressive media loading
  • Framework agnostic
  • Type-safe API

Technology Stack:

  • TypeScript
  • Octokit (GitHub API)
  • Zod (validation)

Package: @git-cms/client on npm

Workflow

Content Creation Flow

Step by Step:

  1. Authentication: User signs in with GitHub OAuth
  2. Repository Connection: Select and connect a repository
  3. Content Creation: Use visual editor to create content
  4. Media Upload: Upload images/videos as needed
  5. Publishing: Click publish to commit to GitHub

Content Consumption Flow

Step by Step:

  1. Initialization: Configure SDK with repository details
  2. Query: Request specific content with filters
  3. Fetch: SDK fetches from GitHub API
  4. Parse: Content is parsed and validated
  5. Return: Type-safe data returned to app
  6. Display: App renders content for users

Data Flow

Writing Content

┌─────────────┐
│ Content     │
│ Creator     │
└──────┬──────┘


┌─────────────────────────────────┐
│ Admin Panel UI                  │
│ ┌─────────────────────────────┐ │
│ │ Rich Text Editor            │ │
│ │ Media Uploader              │ │
│ │ Form Fields                 │ │
│ └─────────────────────────────┘ │
└──────┬──────────────────────────┘
       │ GitHub API (Authenticated)

┌─────────────────────────────────┐
│ GitHub Repository               │
│                                 │
│ content/posts/my-post.md        │
│ media/images/hero.jpg           │
│ .gitcms/schemas/post.json       │
└─────────────────────────────────┘

Reading Content

┌─────────────────────────────────┐
│ GitHub Repository               │
│                                 │
│ content/posts/my-post.md        │
│ media/images/hero.jpg           │
└──────┬──────────────────────────┘
       │ GitHub API (Public or Auth)

┌─────────────────────────────────┐
│ Client SDK                      │
│ ┌─────────────────────────────┐ │
│ │ Query Parser                │ │
│ │ Data Validator              │ │
│ │ Media Loader                │ │
│ └─────────────────────────────┘ │
└──────┬──────────────────────────┘


┌─────────────────────────────────┐
│ Your Application                │
│                                 │
│ Display content to users        │
└─────────────────────────────────┘

Storage Structure

Repository Layout

your-repository/
├── .gitcms/
│   ├── config.json              # GitCMS configuration
│   └── schemas/                 # Content type definitions
│       ├── blog-post.json      # Schema for blog posts
│       ├── project.json        # Schema for projects
│       └── page.json           # Schema for pages

├── content/                     # All content files
│   ├── posts/                  # Blog posts
│   │   ├── 2025-11-01-hello.md
│   │   └── 2025-11-02-world.md
│   ├── projects/               # Project entries
│   │   ├── project-one.json
│   │   └── project-two.json
│   └── pages/                  # Static pages
│       ├── about.md
│       └── contact.json

└── media/                       # Uploaded media
    ├── images/
    │   ├── hero.jpg
    │   └── thumbnail.png
    ├── videos/
    │   └── demo.mp4
    └── documents/
        └── resume.pdf

File Formats

Markdown Files (.md):

markdown
---
title: My Blog Post
publishedAt: 2025-11-07
featured: true
---

# Hello World

This is my **first** blog post!

JSON Files (.json):

json
{
  "id": "my-project",
  "title": "Awesome Project",
  "description": "A cool project",
  "url": "https://example.com",
  "featured": true
}

Authentication & Security

Admin Panel Authentication

OAuth Permissions:

  • Repository Access: Read and write to your repositories
  • User Profile: Get your basic profile information
  • Email: Access your email address

Security Features:

  • Tokens stored server-side only
  • Encrypted session cookies
  • HTTPS everywhere
  • No tokens in browser

Client SDK Authentication

Public Repositories:

typescript
// No token needed!
const cms = new GitCMS({
  repository: 'username/blog',
});

Private Repositories:

typescript
// Token required (server-side only!)
const cms = new GitCMS({
  repository: 'username/private-blog',
  token: process.env.GITHUB_TOKEN,
});

Rate Limits:

  • Public mode: 60 requests/hour per IP
  • Authenticated mode: 5,000 requests/hour

Media Handling

Upload Process

Media Loading (Progressive)

Two-Stage Loading:

  1. Fast Render (Immediate):

    • Embedded thumbnails (base64)
    • Lightweight placeholders
    • Instant page load
  2. Full Render (Async):

    • High-resolution images
    • Actual videos
    • Progressive enhancement

Query Processing

Query Execution Flow

Optimization Techniques:

  • Caching: Reduce API calls
  • Lazy Loading: Fetch only what's needed
  • Progressive Queries: Load in chunks
  • Smart Filtering: Filter early

Example Query Processing

typescript
// User writes this query
const posts = await cms
  .from('posts')
  .where('metadata.status', '==', 'published')
  .where('featured', true)
  .orderBy('publishedAt', 'desc')
  .limit(5)
  .get();

What happens internally:

  1. Parse: Build query parameters
  2. Fetch: Get files from content/posts/
  3. Filter: Apply where conditions
  4. Sort: Order by publishedAt descending
  5. Limit: Return top 5 results
  6. Return: Type-safe array of posts

Version Control Integration

Git Workflow

Every change is a Git commit:

bash
# When you publish content via Admin Panel
git add content/posts/new-post.md
git commit -m "Add: New blog post 'Getting Started'"
git push origin main

Benefits:

  • History: See all changes over time
  • Revert: Undo mistakes easily
  • Branches: Test changes separately
  • Collaboration: Multiple authors

Viewing History

You can always:

  • View previous versions
  • Compare changes
  • Revert to any point
  • See who changed what

Performance Characteristics

Admin Panel

  • Initial Load: ~1-2s (one-time OAuth)
  • Content Load: ~500ms (GitHub API)
  • Content Save: ~1-2s (commit + push)

Client SDK

Public Mode:

  • Schema Fetch: ~200-500ms
  • Content Fetch: ~300-800ms
  • Media Thumbnails: Instant (embedded)
  • Full Media: ~500ms-2s (depends on size)

Authenticated Mode:

  • Similar to public mode
  • Higher rate limits (5,000/hr vs 60/hr)

Caching Benefits:

  • Cached: ~10-50ms
  • Reduces: API calls by 80-90%
  • Improves: User experience significantly

Scalability

Content Limits

GitHub Limits:

  • File size: 100MB (recommend < 10MB)
  • Repository size: No hard limit (5GB recommended)
  • API rate: 5,000 requests/hour (authenticated)

Best Practices:

  • Use Git LFS for large files (> 50MB)
  • Implement caching in your app
  • Static generation for high traffic
  • CDN for media files
Content TypeFilesSizePerformance
Small Blog< 100< 50MBExcellent
Medium Blog100-50050-200MBVery Good
Large Blog500-2000200MB-1GBGood
Enterprise2000+1GB+Use CDN

Next Steps

Now that you understand how GitCMS works:

Learn More

Released under the MIT License.