Skip to content

Commit 27018c8

Browse files
committed
add Xote CSR and SSR templates
1 parent c2878d5 commit 27018c8

27 files changed

Lines changed: 4354 additions & 6 deletions

src/Templates.res

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ type t = {
77
let basicTemplateName = "rescript-template-basic"
88
let viteTemplateName = "rescript-template-vite"
99
let nextjsTemplateName = "rescript-template-nextjs"
10+
let xoteTemplateName = "rescript-template-xote"
11+
let xoteSsrTemplateName = "rescript-template-xote-ssr"
1012
let templateNamePrefix = "rescript-template-"
1113

12-
let supportedTemplateNames = ["vite", "nextjs", "basic"]
14+
let supportedTemplateNames = ["vite", "nextjs", "xote", "xote-ssr", "basic"]
1315

1416
let getTemplateName = templateName => {
1517
let templateName = templateName->String.toLowerCase
@@ -30,6 +32,16 @@ let templates = [
3032
displayName: "Next.js",
3133
shortDescription: "Next.js 15 with static export and Tailwind 3",
3234
},
35+
{
36+
name: xoteTemplateName,
37+
displayName: "Xote",
38+
shortDescription: "Xote with Vite, signals and Tailwind 4 (CSR)",
39+
},
40+
{
41+
name: xoteSsrTemplateName,
42+
displayName: "Xote SSR",
43+
shortDescription: "Xote with Vite, signals and Tailwind 4 (SSR)",
44+
},
3345
{
3446
name: basicTemplateName,
3547
displayName: "Basic",
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# xote · SSR template
2+
3+
A server-rendered starter for [xote](https://github.com/brnrdog/xote) apps. Renders HTML on a Node server, then hydrates on the client so reactivity takes over without re-rendering.
4+
5+
## Stack
6+
7+
- ReScript v12 (JSX transform: `XoteJSX`)
8+
- xote ^6.2 — uses `SSR.renderToString`, `SSRState`, and `Hydration`
9+
- rescript-signals
10+
- Vite 7 — runs in middleware mode for dev, and produces both client and SSR bundles for production
11+
- Tailwind CSS v4 (`@tailwindcss/vite`)
12+
13+
## Layout
14+
15+
```
16+
.
17+
├── index.html # template with <!--app-html--> and <!--app-state--> placeholders
18+
├── server.mjs # Node HTTP server (Vite middleware in dev, static + SSR in prod)
19+
├── vite.config.mjs
20+
├── rescript.json
21+
├── package.json
22+
└── src/
23+
├── styles.css
24+
├── Counter.res # uses SSRState.signal so state survives hydration
25+
├── Page.res # landing page composition
26+
├── App.res # shared `view` thunk used by server and client
27+
├── Server.res # exports render() → { html, stateScript }
28+
└── Client.res # imports styles, calls Hydration.hydrateById
29+
```
30+
31+
## How it fits together
32+
33+
1. `server.mjs` reads `index.html` and (in dev) hands it to Vite for asset/CSS transformation.
34+
2. It imports `Server.res` and calls `render()`, which uses `SSR.renderToString(App.view)` to produce HTML and `SSRState.generateScript()` to produce a `<script>` tag carrying initial signal values.
35+
3. The placeholders `<!--app-html-->` and `<!--app-state-->` in `index.html` are replaced with those two strings.
36+
4. The browser loads `Client.res.mjs`, which calls `Hydration.hydrateById(App.view, "root")`. xote walks the existing DOM, attaches reactive bindings, and reads back the serialized `SSRState` so signals start with the same values the server used.
37+
38+
## Scripts
39+
40+
| Script | What it does |
41+
| --- | --- |
42+
| `npm run res:dev` | Watches and compiles ReScript on save. Run during development. |
43+
| `npm run res:build` | One-shot ReScript build. |
44+
| `npm run res:clean` | Removes ReScript build artifacts. |
45+
| `npm run dev` | Runs `node server.mjs` with Vite in middleware mode. |
46+
| `npm run build` | Builds the client bundle and the SSR bundle. |
47+
| `npm run build:client` | Just the client bundle (`dist/client/`). |
48+
| `npm run build:ssr` | Just the SSR bundle (`dist/server/Server.res.js`). |
49+
| `npm run start` | Runs the server in production mode against the built bundles. |
50+
51+
## Develop
52+
53+
```bash
54+
npm install
55+
npm run res:dev
56+
# in another terminal:
57+
npm run dev
58+
```
59+
60+
Open http://localhost:3000. The page is server-rendered (view source — the counter HTML is already there) and becomes interactive after hydration.
61+
62+
## Build & run in production
63+
64+
```bash
65+
npm run res:build
66+
npm run build
67+
npm run start
68+
```
69+
70+
`server.mjs` defaults to port 3000; override with `PORT=8080 npm run start`.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
dist
3+
lib
4+
*.res.mjs
5+
*.res.js
6+
.DS_Store
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>xote · SSR template</title>
7+
<link rel="stylesheet" href="/src/styles.css" />
8+
</head>
9+
<body>
10+
<div id="root"><!--app-html--></div>
11+
<!--app-state-->
12+
<script type="module" src="/src/Client.res.mjs"></script>
13+
</body>
14+
</html>

0 commit comments

Comments
 (0)