Skip to content

ObneyAI/grain-todo-list

Repository files navigation

grain-todo-list

A teaching project for learning how to build with Grain through a small todo workspace.

This repository accompanies Grain Sessions, a video series about how to use Grain:

Grain Todo home screen

What This Demonstrates

The app is intentionally small, but it exercises the main parts of a Grain application:

  • Capturing, renaming, reordering, completing, canceling, archiving, and reactivating tasks.
  • Grouping work into projects and tracking project task counts.
  • Marking tasks as due within a number of days.
  • Reviewing active tasks and projects through a weekly review workflow.
  • Building server-rendered UI from Grain query results with the Grain Datastar checked UI DSL and Hiccup.
  • Organizing command handlers, event schemas, read models, query handlers, processors, periodic tasks, and UI in a compact Clojure app.

How It Works

The app uses:

  • Grain for commands, queries, events, read models, request handlers, processors, and periodic tasks.
  • Datastar for server-rendered reactive pages.
  • Integrant for application composition and lifecycle.
  • Tailwind CSS and DaisyUI for styling.
  • An in-memory event store and temporary LMDB cache for local development.

The code is laid out as a small Clojure project rather than a Polylith system. Foundation code lives under src/cjbarre/grain_todo_list/foundation/, service code lives under src/cjbarre/grain_todo_list/service/, and the root app namespace handles system startup and routes.

Foundation And Service Components

Foundation components are small, targeted units of functionality that support the app as a whole. They hold shared infrastructure and reusable primitives, such as app UI chrome, email delivery, JWT helpers, and auth interceptors.

Service components own state changes in an area of the domain. When visualized, they should look like Event Models and information systems: commands introduce changes, events record what happened, read models describe useful views of state, and queries present that information back to users.

Project Map

.
├── src/cjbarre/grain_todo_list.clj                    # Integrant system, routes, lifecycle
├── src/cjbarre/grain_todo_list/foundation/
│   ├── ui.clj                                         # App shell and page chrome
│   ├── ui/components.clj                              # Reusable visual primitives
│   ├── email.clj                                      # Email boundary
│   ├── jwt.clj                                        # JWT helpers
│   └── auth_interceptors.clj                          # Auth cookie interceptors
├── src/cjbarre/grain_todo_list/service/
│   ├── todo_list_service/                             # Todo domain service component
│   │   ├── schemas.clj                                # Command, event, query, read-model schemas
│   │   ├── read_models.clj                            # Reducers and projection helpers
│   │   ├── commands.clj                               # Command validation and event emission
│   │   ├── queries.clj                                # Query assembly and UI render boundary
│   │   ├── ui.clj                                     # Todo page composition
│   │   ├── ui/components.clj                          # Todo controls, cards, lists, gallery specimens
│   │   ├── todo_processors.clj                        # Todo processor lifecycle
│   │   └── periodic_tasks.clj                         # Periodic trigger lifecycle
│   └── user_service/                                  # User account service component
├── css/main.css                                       # Tailwind/DaisyUI input CSS
├── resources/public/                                  # Generated static assets
├── test/                                              # Clojure tests
├── CLAUDE.md                                           # Primary agent guide (golden path, gates)
├── AGENTS.md                                           # Condensed agent quick-reference
└── .claude/skills/                                     # Grain build, verification, and spec skills

Requirements

  • Clojure CLI
  • Node.js and npm

The app must be started with the :dev alias because LMDB needs Java module opens.

Install Frontend Dependencies

npm install

Build CSS

One-shot build:

npm run css:build

Watch mode while developing UI:

npm run css:dev

The CSS build writes to resources/public/css/main.css.

Run The App

Start an nREPL:

./scripts/nrepl.sh

Then evaluate:

(require '[cjbarre.grain-todo-list :as app])
(def system (app/start))

Open:

http://localhost:8080/

Stop the app:

(app/stop system)

Development Loop

Typical local loop:

npm run css:dev

In another terminal:

./scripts/nrepl.sh

Then work from the REPL. Reload namespaces after edits and restart the Integrant system as needed

Tests And Checks

Run tests:

clojure -T:build test

Run clj-kondo:

clj-kondo --lint src test

Agent Instructions

The primary agent guide is CLAUDE.md — the Charter, the Grain golden path, self-verification with code-agent-tools, the Definition of Done, and the running/reloading discipline. AGENTS.md is the condensed quick reference. Task-specific skills (schemas, commands, read models, queries, views, UI components, verification, and the allium spec family) live in .claude/skills/.

About

No description, website, or topics provided.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors