Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kelindar/folio

JSON document-based CMS, written with Go, SQLite & HTMX
https://github.com/kelindar/folio

cms htmx sqlite

Last synced: 8 days ago
JSON representation

JSON document-based CMS, written with Go, SQLite & HTMX

Awesome Lists containing this project

README

        


kelindar/folio


Go Version
PkgGoDev
Go Report Card
License

## Folio: Effortless Internal Tool Development

Folio is a tool I built to save time on the boring stuff. After years of building internal tools and getting stuck on UI work, I created Folio to automatically generate UIs from Go structs, letting me skip the front-end hassle and focus on the fun parts of development.

In this example, we define a `Person` struct with various fields and tags for validation and rendering. Folio automatically generates a user interface for the `Person` model, allowing users to create, read, update, and delete records.

```go
type Person struct {
folio.Meta `kind:"person" json:",inline"`
Name string `json:"name" form:"rw" is:"required"`
Age int `json:"age" form:"rw" is:"range(0|130)"`
Gender string `json:"gender" form:"rw" is:"required,in(male|female|prefer_not_to)"`
Country string `json:"country" form:"rw"`
Address string `json:"address" form:"rw"`
Phone string `json:"phone" form:"rw"`
Boss folio.URN `json:"boss" form:"rw" kind:"person"`
IsEmployed bool `json:"isEmployed" form:"rw" desc:"Is the person employed?"`
JobTitle string `json:"jobTitle" form:"rw"`
Workplace folio.URN `json:"workplace" form:"rw" kind:"company" query:"namespace=*;match=Inc"`
}
```

The generated UI includes form fields for each struct field, as well as buttons for creating, updating, and deleting records. The UI also supports pagination, sorting, and filtering.

![demo](./.github/demo.gif)

## Introduction

I’ve built a lot of internal tools over the years — everything from experimentation platforms to machine learning management tools. And while those tools were powerful, the process often felt like a never-ending cycle of reinventing the wheel, except this wheel was for a car that I didn’t really want to drive.

The problem? The minor stuff always took way more time and energy than it should. Need a UI for CRUD operations? That’ll be hours of React, CSS, and front-end misery. I just wanted to get things done, not spend my weekends pretending to enjoy writing JavaScript.

That’s where this project comes in. I built this for my personal projects where I have no team, no budget, and let’s be honest — no patience for building full-blown React apps. Folio generates the UI for me straight from my Go structs (view models), so I can focus on the fun parts (or at least the parts that don’t make me want to quit tech and become a beekeeper).

In short: Folio takes care of the boring stuff, so you can keep your focus on the good stuff—like actually building cool things instead of wrangling with endless form fields and dropdowns.

Keep in mind that this project is still in its early stages, so there’s a lot of room for improvement. I'm also not going to pretend that this is the best solution for every project, and there's still a ton of features that I want to add, so use it at your own risk.

## 🚀 Features

- **Auto-Generated UI**: Automatically generates user interfaces from view models, eliminating the need for manual UI creation.
- **CRUD Operations**: Simplifies Create, Read, Update, and Delete operations for objects.
- **Error Handling & Validation**: Provides utilities for error handling and validation.
- **Templating**: Uses the `templ` package to define and render HTML templates.
- **Abstracted Storage**: Supports SQLite database operations, but can be extended to other storage solutions.
- **Pagination, Search and Filtering**: Built-in support for paginated lists, search, and namespace (i.e project) filtering.

## 🛠 Getting Started

1. Navigate to the company example directory:

```sh
cd examples/company && go run .
```

2. Open your browser and navigate to `http://localhost:7000`.

### 📚 Usage

#### Defining Models

Define your models by embedding `folio.Meta` and specifying field tags for validation and form rendering.

```go
type Person struct {
folio.Meta `kind:"person" json:",inline"`
Name string `json:"name" form:"rw" is:"required"`
Age int `json:"age" form:"rw" is:"range(0|130)"`
Gender string `json:"gender" form:"rw" is:"required,in(male|female|prefer_not_to)"`
Country string `json:"country" form:"rw"`
Address string `json:"address" form:"rw"`
Phone string `json:"phone" form:"rw"`
Boss folio.URN `json:"boss" form:"rw" kind:"person"`
IsEmployed bool `json:"isEmployed" form:"rw" desc:"Is the person employed?"`
JobTitle string `json:"jobTitle" form:"rw"`
Workplace folio.URN `json:"workplace" form:"rw" kind:"company" query:"namespace=*;match=Inc"`
}
```

#### Registering Models

Register your models with the registry and provide options like icons, titles, and sorting.

```go
reg := folio.NewRegistry()
folio.Register[*Person](reg, folio.Options{
Icon: "user-round",
Title: "Person",
Plural: "People",
Sort: "1",
})
```

#### Starting the Server

Use the render.ListenAndServe function to start the server.

```go
db, err := sqlite.Open("file:data.db?_journal_mode=WAL", reg)
if err != nil {
panic(err)
}

if err := render.ListenAndServe(7000, reg, db); err != nil {
slog.Error("Failed to start server!", "details", err.Error())
os.Exit(1)
}
```

#### Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

#### License

This project is licensed under the MIT License. See the LICENSE file for details.

#### Acknowledgements

This project leverages several open-source libraries and tools. We would like to acknowledge and thank the following projects:

- **templ**: A Go package for defining and rendering HTML templates.
- **htmx-go**: A Go package for integrating htmx with Go web applications.
- **SQLite**: A C library that provides a lightweight, disk-based database.
- **Franken-UI**: A collection of UI components for building modern web applications.
- **Tailwind CSS**: A utility-first CSS framework for rapidly building custom user interfaces.