5.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
A REST API backend for managing code snippets, written in Clojure using XTDB for data storage. The API provides endpoints for creating, reading, editing, and deleting snippets, with support for tagging and slug-based lookup.
Related Projects:
- Snippets CMS - TUI CMS and MCP server companion project
Development Commands
Run Development Server
clojure -M -m snippets.main
Starts the API server on the configured host/port (default: localhost:8080). The REPL can be used to develop with the server:
; Start server in background from REPL:
(def server (jetty/run-jetty #'app {:port 3000 :join? false}))
; Stop server:
(.stop server)
Build Uberjar
clojure -T:build uber
Creates a standalone JAR file at target/snippets-standalone.jar that includes all dependencies.
REPL Commands
Common REPL operations:
; Pretty-print data structures
(clojure.pprint/pprint {:name "Alice" :age 30})
; Require a namespace (fresh import)
(require 'clojure.string)
(require '[clojure.string :as str])
(require 'my.namespace :reload)
; List namespace contents
(dir clojure.string)
; Switch namespaces
(in-ns 'my.namespace)
(in-ns 'user)
Linting
The project uses clj-kondo for static analysis. Configuration is in .clj-kondo/config.edn. Linting is integrated into most IDEs via LSP.
Code Architecture
Directory Structure
- src/snippets/infra/ - Infrastructure layer (HTTP API, database, configuration)
api.clj- HTTP routing and handlers using reititdb.clj- XTDB queries and transactionsconfig.clj- Configuration loading (config.edn + environment variables)
- src/snippets/use_cases/ - Business logic layer
view.clj- Query/read operations, includes serialization for JSON outputcreate.clj- Create snippetsedit.clj- Patch snippets with validationdelete.clj- Delete snippets
- test/ - Test suite
Architecture Pattern
Clean separation between layers:
-
Infrastructure (infra/): Handles external concerns
- HTTP/REST via reitit + ring
- XTDB database client and queries
- Environment configuration
-
Use Cases: Business logic implementing application features
- Each use case is a module with focused responsibility
- Calls infrastructure layer (infra.db, infra.config) as needed
- Performs serialization/transformation for API responses
-
Main Entry Point (main.clj): Minimal bootstrap that runs the API server
Data Model
Snippets are XTDB documents with:
xt/id- UUID identifier (set by create use case)title- Snippet titleslug- URL-friendly identifier for query lookupsmarkdown- Snippet content in markdown formattags- Vector of strings for categorizationpub-date- Date object (serialized to ISO-8601 strings for API responses)
API Endpoints
All routes under /api:
GET /api/ping- Health checkGET /api/snippets- List snippets (with optionallimitandskipquery params)GET /api/snippet?id=<id>- Get snippet by UUIDGET /api/snippet-by-slug?slug=<slug>- Get snippet by slugPOST /api/snippet- Create snippetPATCH /api/snippet?id=<id>- Edit snippet (patches are validated against schema)DELETE /api/snippet?id=<id>- Delete snippetGET /api/tags- List all tags with countsGET /api/tag?tag=<tag>- Get snippets by tag
Key Dependencies
- reitit (0.9.1) - HTTP routing and coercion
- ring (1.13.0) - HTTP server (jetty adapter)
- XTDB (2.0.0-beta9) - Temporal database
- malli (0.18.0) - Schema validation and generation
- muuntaja (0.6.11) - JSON/EDN encoding/decoding
- telemere (1.0.0) - Structured logging
- environ (1.2.0) - Environment variable loading
Configuration
Configuration comes from config.edn with environment variable overrides:
{:jetty {:host "localhost" :port 8080}
:xtdb {:host "192.168.1.157" :port "5007" :user "xtdb" :dbname "xtdb"}}
Environment variables can override specific values:
HOST- Jetty hostPORT- Jetty port (parsed as integer)XTDB_HOST,XTDB_PORT,XTDB_USER,XTDB_DBNAME- XTDB connection details
See infra/config.clj for how overrides are applied.
Testing
Run the test suite:
clojure -M:test:clojure.test/run
Or from REPL:
(clojure.test/run-tests 'snippets-test)
The test namespace snippets-test includes:
- Basic arithmetic tests
- XTDB integration tests using test node
- HTML rendering tests using rum
Deployment
Docker image built and pushed to AWS ECR via build.sh:
./build.sh
Requires AWS CLI configured with personal profile and permission to push to ECR repository.
Notes
- XTDB queries use XTQL (temporal query language)
- Date serialization happens in
view.clj- pub-date objects are converted to ISO-8601 strings for JSON responses - Patch validation is strict (
{:closed true}) - only specific fields can be updated - String formatting in some XTQL queries uses
evalandread-stringfor dynamic query construction - UUIDs used for snippet IDs; generated client-side on creation