summaryrefslogtreecommitdiff
path: root/CLAUDE.md
blob: 2d367d302efa07bf7da585ba48df7228a6d28a04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# OCaml SSR React APP on Eio

This app is a WIP to implement a blog as a React webapp using Ocaml, mlx for JSX, Piaf for HTTP handling, Caqti to handle database queries, using Eio across the app for async.

## Current Status

The project is successfully running as a server-side rendered React application in OCaml with the following features implemented:

- **Database**: SQLite with schema for posts, comments, and votes
- **Routing**: Type-safe routing using the `routes` library
- **SSR React**: JSX-like syntax via mlx, server-side rendering
- **API Endpoints**: RESTful endpoints for posts, comments, and votes
- **Frontend**: Tailwind CSS styling with responsive design
- **Static Assets**: Serving CSS, images, and other static files

## Build the app 
To compile the app and see if the code is correct do:
`dune clean && dune build`

## Running the app
```bash
# Build and run the server
dune exec bs5

# Or use the run script
./run.sh
```

## Tech Stack

### Core
- **OCaml**: Primary language
- **Eio**: Async runtime for OCaml 5
- **mlx**: JSX syntax for OCaml React components
- **dune**: Build system

### Web Framework
- **Piaf**: HTTP server and client
- **React (server-side)**: Rendering React components on the server

### Database
- **Caqti**: Database abstraction layer
- **SQLite**: Embedded database with WAL mode
- **Rapper**: Type-safe SQL queries with PPX

### Styling
- **Tailwind CSS**: Utility-first CSS framework
- **Custom fonts**: Crimson Text and Inter fonts included

### Development
- **Nix**: Development environment with flake.nix
- **ocaml-lsp-server**: Language server support
- **ocamlformat-mlx**: Code formatting for mlx files

## Project Structure

```
├── lib/                    # Core application code
│   ├── handler.ml         # HTTP handlers
│   ├── router.ml          # Route definitions
│   ├── html.ml            # HTML rendering utilities
│   ├── post_handlers.ml   # POST request handlers
│   ├── shared/
│   │   └── query.ml       # Database queries
│   └── pages/
│       ├── BlogIndex.mlx  # Main blog page React component
│       └── components/    # Reusable React components
├── assets/                # Static assets
│   ├── styles.css        # Generated Tailwind CSS
│   ├── fonts/            # Web fonts
│   ├── board/            # Board/category icons
│   └── avatars/          # User avatars
├── bulkdata/             # Database files
│   ├── blog.db          # SQLite database
│   └── schema.sql       # Database schema
└── bin/                  # Main executable
```

## Key Features Implemented

### Database Schema
- **Posts**: id, title, content, date, tags, url
- **Comments**: id, content, date, tags, url, post_id, parent, author
- **Votes**: post_id, comment_id, user_id, vote_type

### API Endpoints
- `GET /` - Main blog page with post previews
- `GET /posts` - Get all posts
- `GET /posts/:id` - Get specific post
- `GET /posts/:id/comments` - Get comments for a post
- `POST /posts` - Create new post
- `POST /comments` - Create new comment
- `POST /votes` - Create new vote
- `GET /assets/*` - Serve static assets

### React Components
- **Layout**: Main page layout with HTML boilerplate
- **PostPreviews**: Displays list of blog post previews
- **Navbar**: Navigation component
- **SiteTitle**: Header component

## Things to take into account

### Ocaml Routes library

#### The `@-->` Operator

The `@-->` operator is from the `routes` library and is used to bind route patterns to handler functions.

##### Example:
```ocaml
`GET, (s "posts" /? nil) @--> Handler.get_posts
```

##### Breaking it down:
- `s "posts"` - matches the string "posts" in the URL path
- `/?` - path concatenation operator 
- `nil` - end of path (no more segments)
- `@-->` - "maps to" operator that binds the route to the handler

So `(s "posts" /? nil) @--> Handler.get_posts` means "the route `/posts` maps to the `Handler.get_posts` function".

##### Other common operators in the routes library:
- `/:` for path parameters (e.g., `s "user" /: int /? nil` matches `/user/123`)
- `//` for wildcard paths
- `<$>` for transforming matched values

It's a DSL (domain-specific language) for expressing routes in a concise, type-safe way.