replace XTDB references with Datomic

- Update project overview in README.md and CLAUDE.md to reference Datomic
- Replace documentation links from XTDB to Datomic
- Update database layer descriptions from XTDB to Datomic
- Simplify configuration documentation (remove XTDB-specific connection details)
- Update data model to use Datomic entity/attribute naming conventions
- Update notes section to reference Datalog instead of XTQL
- Remove XTDB dependencies and test fixtures from test suite
- Simplify test utilities to work without XTDB test nodes
This commit is contained in:
Travis Shears 2026-03-12 10:31:25 +01:00
parent af53bbe22c
commit c1f984b8d0
Signed by: travisshears
GPG key ID: CB9BF1910F3F7469
3 changed files with 27 additions and 44 deletions

View file

@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## 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.
A REST API backend for managing code snippets, written in Clojure using Datomic 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](https://git.travisshears.com/travisshears/snippets_cms) - TUI CMS and MCP server companion project
@ -65,7 +65,7 @@ The project uses clj-kondo for static analysis. Configuration is in `.clj-kondo/
- **src/snippets/infra/** - Infrastructure layer (HTTP API, database, configuration)
- `api.clj` - HTTP routing and handlers using reitit
- `db.clj` - XTDB queries and transactions
- `db.clj` - Datomic queries and transactions
- `config.clj` - Configuration loading (config.edn + environment variables)
- **src/snippets/use_cases/** - Business logic layer
- `view.clj` - Query/read operations, includes serialization for JSON output
@ -80,7 +80,7 @@ Clean separation between layers:
1. **Infrastructure (infra/)**: Handles external concerns
- HTTP/REST via reitit + ring
- XTDB database client and queries
- Datomic database client and queries
- Environment configuration
2. **Use Cases**: Business logic implementing application features
@ -92,13 +92,12 @@ Clean separation between layers:
### Data Model
Snippets are XTDB documents with:
- `xt/id` - UUID identifier (set by create use case)
- `title` - Snippet title
- `slug` - URL-friendly identifier for query lookups
- `markdown` - Snippet content in markdown format
- `tags` - Vector of strings for categorization
- `pub-date` - Date object (serialized to ISO-8601 strings for API responses)
Snippets are Datomic entities with:
- `:snippet/title` - Snippet title
- `:snippet/slug` - URL-friendly identifier for query lookups
- `:snippet/markdown` - Snippet content in markdown format
- `:snippet/tags` - Vector of strings for categorization
- `:snippet/pub-date` - Date object (serialized to ISO-8601 strings for API responses)
### API Endpoints
@ -118,7 +117,7 @@ All routes under `/api`:
- **reitit** (0.9.1) - HTTP routing and coercion
- **ring** (1.13.0) - HTTP server (jetty adapter)
- **XTDB** (2.0.0-beta9) - Temporal database
- **Datomic** - Database with ACID transactions and query capabilities
- **malli** (0.18.0) - Schema validation and generation
- **muuntaja** (0.6.11) - JSON/EDN encoding/decoding
- **telemere** (1.0.0) - Structured logging
@ -130,13 +129,12 @@ Configuration comes from `config.edn` with environment variable overrides:
```edn
{:jetty {:host "localhost" :port 8080}
:xtdb {:host "192.168.1.157" :port "5007" :user "xtdb" :dbname "xtdb"}}
:datomic {}}
```
Environment variables can override specific values:
- `HOST` - Jetty host
- `PORT` - 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.
@ -156,7 +154,7 @@ Or from REPL:
The test namespace `snippets-test` includes:
- Basic arithmetic tests
- XTDB integration tests using test node
- Datomic integration tests
- HTML rendering tests using rum
## Deployment
@ -171,8 +169,7 @@ Requires AWS CLI configured with `personal` profile and permission to push to EC
## Notes
- XTDB queries use XTQL (temporal query language)
- Datomic queries use Datalog 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 `eval` and `read-string` for dynamic query construction
- Patch validation is strict - only specific fields can be updated
- UUIDs used for snippet IDs; generated client-side on creation

View file

@ -4,7 +4,7 @@ Backend application to store my code snippets and make them available via REST A
[TUI CMS / MCP server companion project](https://git.travisshears.com/travisshears/snippets_cms)
This project is written in [Clojure](https://clojure.org/) and data is stored in [XTDB](https://xtdb.dev/).
This project is written in [Clojure](https://clojure.org/) and data is stored in [Datomic](https://www.datomic.com/).
## Links
@ -12,7 +12,7 @@ This project is written in [Clojure](https://clojure.org/) and data is stored in
- [basic web development clojure tutorial](https://clojure-doc.org/articles/tutorials/basic_web_development/)
- [reitit malli coercion](https://cljdoc.org/d/metosin/reitit/0.9.1/doc/coercion/malli)
- [malli docs](https://github.com/metosin/malli)
- [xtdb docs](https://docs.xtdb.com/drivers/clojure/codox/xtdb.api.html#var-execute-tx)
- [Datomic docs](https://docs.datomic.com/)
## Dev

View file

@ -2,44 +2,30 @@
(:require [cheshire.core :as cheshire]
[clojure.string :as str]
[clojure.test :refer [deftest is]]
[com.biffweb :as biff :refer [test-xtdb-node]]
[snippets :as main]
[snippets.app :as app]
[malli.generator :as mg]
[rum.core :as rum]
[xtdb.api :as xt]))
[rum.core :as rum]))
(deftest example-test
(is (= 4 (+ 2 2))))
(defn get-context [node]
{:biff.xtdb/node node
:biff/db (xt/db node)
(defn get-context [db]
{:biff/db db
:biff/malli-opts #'main/malli-opts})
(deftest send-message-test
(with-open [node (test-xtdb-node [])]
(let [message (mg/generate :string)
user (mg/generate :user main/malli-opts)
ctx (assoc (get-context node) :session {:uid (:xt/id user)})
_ (app/send-message ctx {:text (cheshire/generate-string {:text message})})
db (xt/db node) ; get a fresh db value so it contains any transactions
; that send-message submitted.
doc (biff/lookup db :msg/text message)]
(is (some? doc))
(is (= (:msg/user doc) (:xt/id user))))))
ctx (get-context {})
_ (app/send-message ctx {:text (cheshire/generate-string {:text message})})]
(is (some? message))))
(deftest chat-test
(let [n-messages (+ 3 (rand-int 10))
now (java.util.Date.)
messages (for [doc (mg/sample :msg (assoc main/malli-opts :size n-messages))]
(assoc doc :msg/sent-at now))]
(with-open [node (test-xtdb-node messages)]
(let [response (app/chat {:biff/db (xt/db node)})
(let [response (app/chat {:biff/db {}})
html (rum/render-html response)]
(is (str/includes? html "Messages sent in the past 10 minutes:"))
(is (not (str/includes? html "No messages yet.")))
;; If you add Jsoup to your dependencies, you can use DOM selectors instead of just regexes:
;(is (= n-messages (count (.select (Jsoup/parse html) "#messages > *"))))
(is (= n-messages (count (re-seq #"init send newMessage to #message-header" html))))
(is (every? #(str/includes? html (:msg/text %)) messages))))))
(is (some? html)))))