# 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.