backend

module
v0.0.0-...-e840766 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2026 License: MIT

README

Chukfi CMS Logo

Chukfi CMS

Chukfi (chook-fee) is the Choctaw word for rabbit, a symbol of speed, agility, and quick thinking.
Chukfi CMS embraces those qualities by providing a fast, modern, open-source headless CMS built with Go.

Release Go Version

Overview

Chukfi is a Go library for building content management systems. It provides authentication, permissions, schema registration, and a REST API out of the box. You define your schemas and Chukfi handles the rest.

Installation

go get github.com/chukfi/backend

Or install the CLI globally:

go install github.com/chukfi/backend/cmd/chukfi@latest

Automatic Quick Start

1. Download the CLI
go install github.com/chukfi/backend/cmd/chukfi@latest
2. Run the init command
chukfi init # OPTIONAL: --directory=./backend

This will create a directory called "backend" which clones the crm/backend-test as well as the frontend, builds & places it in the public folder.

Manual Quick Start

1. Set Up Database

Chukfi uses MySQL/TiDB. The easiest way to get started is with Docker:

# docker-compose.yml
version: '3.8'

services:
  tidb:
    image: pingcap/tidb:latest
    ports:
      - "4002:4000"
    command:
      - --store=unistore
      - --path=/tmp/tidb
    volumes:
      - ./docker-tidb:/tmp/tidb
docker-compose up -d
2. Create Your Project
mkdir my-cms && cd my-cms
go mod init my-cms
go get github.com/chukfi/backend
go install github.com/chukfi/backend/cmd/chukfi@latest
chukfi setup-frontend # optional --url={url} --directory={directory}
3. Define Your Schema
// schema.go
package main

import "github.com/chukfi/backend/database/schema"

type Post struct {
    schema.BaseModel
    Type     string `gorm:"type:varchar(100);not null"`
    Body     string `gorm:"type:text;not null"`
    Title    string `gorm:"type:varchar(255);not null;index"`
    AuthorID string `gorm:"type:char(36);index"`
}

type HiddenModel struct {
    schema.BaseModel
    schema.Hidden
    Key        string `gorm:"type:char(64);not null;uniqueIndex"`
}

type APIKeys struct {
    schema.BaseModel
    schema.AdminOnly
    Key        string `gorm:"type:char(64);not null;uniqueIndex"`
    OwnerEmail string `gorm:"type:varchar(100);not null;index"`
    ExpiresAt  int64  `gorm:"not null;index"`
}

// or any other schemas, there are examples

Embed schema.AdminOnly in any model to restrict access to authenticated admin users. Embed schema.Hidden in any model to hide it from any user as well as the dashboard.

4. Create Your Server
// main.go
package main

import (
    "net/http"

    database "github.com/chukfi/backend/database/mysql"
    "github.com/chukfi/backend/server/router"
    "github.com/chukfi/backend/server/serve"
    "github.com/chukfi/backend/src/httpresponder"
    "github.com/chukfi/backend/src/lib/permissions"
    "github.com/go-chi/chi/v5"
    "gorm.io/gorm"
    "my-module/schema"
)

func main() {
    customSchema := []interface{}{
        &schema.Post{},
        &schema.APIKeys{},
        &schema.HiddenModel{}
    }

    database.InitDatabase(customSchema)

    r := router.SetupRouter(database.DB, "./public") // or r := router.SetupRouter(database.DB) for no server.

    r.Get("/posts", func(w http.ResponseWriter, r *http.Request) {
        posts, err := gorm.G[Post](database.DB).Find(r.Context())
        if err != nil {
            httpresponder.SendErrorResponse(w, r, err.Error(), 500)
            return
        }
        httpresponder.SendNormalResponse(w, r, posts)
    })

    r.Route("/api", func(r chi.Router) {
        r.Use(router.AuthMiddlewareWithDatabase(database.DB))

        r.Get("/whoami", func(w http.ResponseWriter, r *http.Request) {
            user, _ := router.GetUserFromRequest(r, database.DB)
            httpresponder.SendNormalResponse(w, r, user)
        })
    })

    serveConfig := serve.NewServeConfig("3000", []interface{}{}, database.DB, r)
    serve.Serve(serveConfig)
}
5. Configure Environment
# .env
DATABASE_DSN="root:@tcp(127.0.0.1:4002)/test?charset=utf8mb4&parseTime=True&loc=Local"
6. Run
go run .

Features

Schema System

All models should embed schema.BaseModel which provides:

  • ID (UUID)
  • CreatedAt
  • UpdatedAt
  • DeletedAt (soft delete)
type Product struct {
    schema.BaseModel
    Name  string `gorm:"type:varchar(255);not null"`
    Price int    `gorm:"not null"`
}
Admin-Only Models

Embed schema.AdminOnly to restrict model access to authenticated users with admin permissions:

type SecretConfig struct {
    schema.BaseModel
    schema.AdminOnly
    Key   string `gorm:"type:varchar(100)"`
    Value string `gorm:"type:text"`
}
Hidden Models

Embed schema.Hidden to restrict model access to everyone, so it is not displayed in the API or the chukfi interfaces.

type HiddenConfig struct {
    schema.BaseModel
    schema.Hidden
    Key   string `gorm:"type:varchar(100)"`
    Value string `gorm:"type:text"`
}
Authentication

Chukfi provides built-in auth endpoints:

Endpoint Method Description
/admin/auth/login POST Login with email/password, returns auth token
/admin/auth/me GET Get current user info

Use router.AuthMiddlewareWithDatabase(db) to protect routes:

r.Route("/protected", func(r chi.Router) {
    r.Use(router.AuthMiddlewareWithDatabase(database.DB))
    
    r.Get("/data", handler)
})
Permissions

Register custom permissions and check them in handlers:

viewPosts, _ := permissions.RegisterPermission("ViewPosts")

r.Get("/posts", func(w http.ResponseWriter, r *http.Request) {
    if !router.RequestRequiresPermission(r, database.DB, viewPosts) {
        httpresponder.SendErrorResponse(w, r, "Forbidden", 403)
        return
    }
    // ...
})

Or use middleware for entire route groups:

r.Route("/admin-only", func(r chi.Router) {
    r.Use(router.RoutesRequiresPermission(database.DB, permissions.ManageModels))
    // all routes here require ManageModels permission
})
Collection API

Chukfi automatically provides REST endpoints for registered schemas:

Endpoint Method Description
/admin/collection/all GET List all collections (requires auth)
/admin/collection/{name}/get GET Get all entries in collection
/admin/collection/{name}/create POST Create new entry (requires auth)
/admin/collection/{name}/metadata GET Get collection schema metadata
Database Helper

Use the typed query builder for cleaner database operations:

import databasehelper "github.com/chukfi/backend/database/helper"

post, err := databasehelper.Get[Post](database.DB).
    Where("title = ?", "My Post").
    First()

posts, err := databasehelper.Get[Post](database.DB).
    Where("author_id = ?", userID).
    Order("created_at DESC").
    Limit(10).
    Find()
TypeScript Type Generation

Generate TypeScript types from your Go schemas:

import generate_types "github.com/chukfi/backend/cmd/generate-types"

generate_types.GenerateTypescriptTypes(&generate_types.GenerateTypesConfig{
    Schema:   customSchema,
    Database: database.DB,
})

Or use the CLI:

chukfi generate-types --schema=path/to/schema.go # optionally --dsn={dsn} --database={database provider (mysql/postgres)}
Admin Frontend Serving

Serve a static admin frontend directory:

r := router.SetupRouter(database.DB, "./public")

Build and download the admin frontend automatically:

chukfi setup-frontend # --url=https://github.com/your/frontend.git

CLI Commands

Use any command with -h to see the options. Or use just chukfi to see the commands.

chukfi generate-types    # Generate TypeScript types from database schema
chukfi setup-frontend     # Clone, build, and serve frontend
chukfi init

License

MIT License - see LICENSE for details.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL