Syntic
← All skills
LanguagesFreeCommunityv1.0.0

Clojure Developer

Use when building data-oriented systems with Clojure, REPL-driven development, persistent data structures, and Ring/Compojure.

About this skill

Use when building data-oriented systems with Clojure, REPL-driven development, persistent data structures, and Ring/Compojure.

SKILL.md

clojure-developer.SKILL.md

Place it in your Syntic skills folder. For Syntic Code, install in your local skills directory, review the contents and run it in a controlled environment first.

SKILL.md
---
name: Clojure Developer
description: Use when building data-oriented systems with Clojure, REPL-driven development, persistent data structures, and Ring/Compojure.
category: Languages
version: 1.0.0
tools: []
---

# Clojure Development

Build robust, data-oriented systems using functional programming and immutable data structures via REPL-driven development.

## REPL-Driven Development

1. Connect to a running REPL. Evaluate code forms incrementally rather than restarting the application.
2. Define functions and test them immediately with sample data before writing formal tests.
3. Use `comment` blocks (rich comments) at the bottom of each namespace for exploratory code and examples.
4. Reload changed namespaces with `require :reload` or `tools.namespace/refresh`. Design state management for safe reloads.
5. Use `tap>` and `add-tap` to inspect intermediate values without modifying production code.

## Data-Oriented Design

- Model entities as plain maps with namespaced keywords: `{:user/id 1 :user/name "Alice" :user/email "alice@example.com"}`.
- Use `clojure.spec.alpha` or Malli for schemas. Validate at system boundaries (API input, database output).
- Prefer data transformations over object methods. Functions operate on maps.
- Persistent data structures (vectors, maps, sets) provide structural sharing for efficient immutable updates.
- Represent state transitions as data: `{:event/type :order/placed :order/id "123" :order/items [...]}`.

## Web Applications with Ring

- HTTP handlers as pure functions: `(fn [request] response)`. Request is a map, response is a map.
- Compose middleware as function wrappers. Apply in order: logging → error handling → auth → routing → body parsing.
- **Compojure** or **Reitit** for routing. Reitit defines routes as data structures for better introspection.
- Return proper HTTP status codes and structured error responses. Use `ring.util.response` helpers.
- `ring.middleware.json` for JSON parsing/generation. `ring.middleware.params` for query strings.

## Concurrency Primitives

- **Atoms** for independent, synchronous state updates. `swap!` applies a pure function atomically.
- **Refs** and **STM** when multiple pieces of state must update in a coordinated transaction.
- **Agents** for independent, asynchronous state updates where order matters but timing does not.
- **core.async channels** for complex coordination: producer-consumer, pub-sub, pipeline processing.
- **Future** for simple fire-and-forget async computation. `deref` with timeout to avoid blocking.

## Namespace Organization

- One namespace per file. File names match namespace paths: `my_app/user/handler.clj` → `my-app.user.handler`.
- Separate concerns by layer: `my-app.user.handler` (HTTP), `my-app.user.service` (business logic), `my-app.user.db` (persistence).
- **Component** or **Integrant** for system lifecycle management.
- Keep namespace dependencies acyclic.

## ClojureScript

- **shadow-cljs** for builds. Configure `:target :browser` or `:target :node-library`.
- **Reagent** or **Re-frame** for React-based UIs. Reagent atoms drive reactive re-rendering.
- Interop: `js/` prefix for globals, `clj->js` / `js->clj` for data conversion.
- Google Closure Library utilities ship with ClojureScript at no extra bundle cost.

## Testing

- `clojure.test` with `deftest` and `is` assertions. Group with `testing` blocks.
- `test.check` for generative (property-based) testing. Define generators with `gen/fmap` and `gen/bind`.
- Test stateful systems by starting a test system with Component, running assertions, and stopping in a fixture.

Install

Syntic App

  1. 1Create a dedicated folder for this skill in your local skills library.
  2. 2Place SKILL.md into that folder.
  3. 3Restart Syntic and invoke this skill on matching tasks.

Syntic Code (CLI)

  1. 1Save SKILL.md in your local Syntic Code skills directory.
  2. 2Keep related files in the same skill folder.
  3. 3Run in a safe environment and validate outputs.