# tui-pages website Static marketing site for the [`tui-pages`](https://gitlab.com/filipriec/tui-pages) Rust crate. No build step required — open `index.html` in a browser and you're done. ## Stack | Layer | Tech | Source | | --- | --- | --- | | HTML | Hand-written semantic | `*.html` | | CSS framework | Tailwind CSS v3 (Play CDN) | runtime | | Components | DaisyUI v4 (prebuilt CSS) | runtime | | Interactivity | HTMX 2 | runtime | | Light JS | Alpine.js 3 | runtime | | Code highlight | highlight.js 11 (Rust, TOML, Bash) | runtime | | Fonts | Inter + JetBrains Mono (Google Fonts) | runtime | | Icons | Lucide (inline SVG) | hand-written | | Page transitions | View Transitions API (native) | n/a | Everything is loaded from public CDNs. The only thing served from this repo is the HTML, our small `static/css/site.css` layer, and the SVG assets in `static/img/`. ## Local development ```bash # Just open the file xdg-open index.html # Linux open index.html # macOS # Or serve it (recommended — gives you a stable URL for htmx) python3 -m http.server 8000 # then visit http://localhost:8000 ``` The `Makefile` wraps the Python server and a few convenience commands: ```bash make serve # python3 -m http.server 8000 (serves the WORKING TREE — use this while iterating) make size # report file sizes make validate # quick HTML syntax check (search for unclosed tags) make tidy # run html-tidy on every .html (warnings only) make video NAME=foo # regenerate the ASCII background from video/foo.mp4 ``` > **Note:** `make serve` reads from the working tree (so it picks up the latest > `static/js/mountain.js` after a `make video`). For a production build, use > `nix run .#serve` — but note that the Nix build only includes **git-tracked** > files, so you must `git add` your new `mountain.js` (and any other new files) > before `nix run .#serve` will pick them up. ## Animated ASCII video background The page background is an **animated chafa ASCII playback of a video**, running at 12 fps behind the entire page. `ffmpeg` extracts frames from a video you provide; `chafa` converts each frame to an 80 × 24 ASCII grid; a bundler (`tools/build_mountain_js.py`) concatenates all grids into a single JS array (`static/js/mountain.js`). A tiny cycler (`static/js/mountain-bg.js`) swaps `textContent` on a single `
` every ~83 ms.
### Swap the video
1. Drop a `.mp4` in `video/`:
```bash
cp ~/Videos/my-clip.mp4 video/myclip.mp4
```
2. Build it into the site (run inside the nix dev shell for ffmpeg + chafa):
```bash
nix develop -c make video NAME=myclip
```
This runs three steps:
- `make video-frames NAME=myclip` — `ffmpeg` extracts PNGs at 12 fps into `build/myclip/`, then `chafa -s 80x24 --symbols ascii` produces ASCII for each
- `make video-bundle NAME=myclip` — bundles all `frame-*.txt` into `static/js/mountain.js`
- the wrapper `make video` does both
3. Serve and view:
```bash
make serve
# → http://localhost:8000
```
### Helper targets
```bash
make video-list # show available videos in video/
make video-frames NAME=foo # only extract + chafa, skip the bundle
make video-bundle NAME=foo # only re-bundle from an existing build/foo/
```
### Tuning
- **Frame rate** — edit `Makefile` `fps=12` in the `video-frames` target. If
you change it, also update `TP_MOUNTAIN_FPS` at the bottom of
`static/js/mountain.js` (regenerated automatically each `make video`).
- **ASCII resolution** — `-s 80x24` in the `chafa` call. Wider/higher = larger
bundle, more detail.
- **Bundle size** — the resulting `static/js/mountain.js` is `~1.7 kB × N_FRAMES`
(333 kB for a 15 s clip at 12 fps). For long videos, drop `fps` or downscale
the source video first.
```
↓ chafa -s 80x24
build/mountain/frame-*.txt intermediate ASCII grids
↓
static/js/mountain.js bundled 60-frame array (≈120 kB)
↓ requestAnimationFrame
DOM what you actually see, 12 fps
```
To re-render (you need `chafa` and `python3` on `$PATH`, or use `nix develop`):
```bash
make mountain # frames + bundle, end-to-end
make mountain-frames # just the PNG + ASCII frames
make mountain-bundle # just rebundle the JS array from existing frames
```
### How it's wired
- `static/js/mountain.js` exposes `window.TP_MOUNTAIN_FRAMES` (an array of
60 template strings) plus `TP_MOUNTAIN_N_FRAMES = 60` and
`TP_MOUNTAIN_FPS = 12`.
- `static/js/mountain-bg.js` mounts a `