tui-pages website
Static marketing site for the 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
# 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:
make serve # python3 -m http.server 8000
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 ascii # regenerate the body-rain ASCII art (needs `chafa`)
Animated ASCII body background
The page background is animated ASCII art generated by
chafa from a stripped-down version
of the Open Graph card (static/img/og-image-bg.svg — black background,
grid, the tui-pages wordmark, the "A framework for / building TUIs in
Rust." headline, and the subtitle, with the install button cropped out
because chafa was rendering it as a row of @ symbols). The art is plain
text inside <pre> blocks; the animation is pure CSS.
static/ascii/rain.txt ← 240 × ~50 grid of og-image-bg.svg
To re-render after changing the source SVG (you need chafa on $PATH,
or run inside nix develop):
make ascii
The source SVG is committed (static/img/og-image-bg.svg) so make ascii
is fully reproducible — no ImageMagick, no cropping step.
How it's wired
- A single
<div class="tp-ascii-rain" aria-hidden="true">is placed at the top of<body>, fixed full-bleed, withz-index: -1andpointer-events: noneso it never blocks the UI. - Inside, a
<pre class="tp-ascii-rain-track">holds two byte-identical copies of the chafa output stacked vertically for a seamlesstranslateY(0 → -50%)loop over 90 s. - Color is
#f4a26b(warm rust-orange) at 14% opacity with a fainttext-shadowglow — picks up the brand colour and reads as a subtle background, not a wall of@blocks. - A
::afteroverlay draws a 2 px CRT scanline pattern that ticks downward at 8 s/cycle. - The hero section has a
.tp-ascii-hero-overlayclass that paints a vertical gradient over the top of the page, so the hero text stays readable while the ASCII art shows through on the bottom half and below. - The light theme inverts to dark text on light, dimmer, no glow.
- All animations are disabled inside
@media (prefers-reduced-motion: reduce).
The hero (#hero) is not animated — it keeps the original static
static/img/terminal-default.svg mockup, exactly as designed.
Nix (optional, recommended)
A flake.nix is included that ships a reproducible dev shell, a buildable
package, a serve app, and an html-tidy check. You do not need Nix to
use this project — it's a convenience.
# Enter the dev shell (gives you: gnumake, python3, asciinema, html-tidy, …)
nix develop
# Build the whole site → ./result/ (16 files, ~150 kB, ready to upload)
nix build
ls result/
# Build + serve on http://localhost:8000 (or $PORT)
nix run .#serve
# Validate the HTML, format the flake
nix flake check
nix fmt
What the flake provides
| Output | Command | What it does |
|---|---|---|
packages.<sys>.default |
nix build |
Assembles the static site into a single derivation |
apps.<sys>.serve |
nix run .#serve |
Builds the package, then python3 -m http.server it |
devShells.<sys>.default |
nix develop |
Shell with make, python3, asciinema, tidy, curl |
checks.<sys>.tidy |
nix flake check |
Runs html-tidy over every .html in the built site |
formatter.<sys> |
nix fmt |
nixpkgs-fmt for the flake itself |
Why no Rust toolchain?
The crate lives in ../komp_ac/tui-pages/. This repo only contains the
static website, so the flake intentionally omits rust-overlay and a
rustPlatform — they would add hundreds of MB to the shell closure for
nothing. When the site eventually gains a Rust backend, those inputs come
back.
Why the per-system pattern?
Mirrored from the upstream Codex CLI flake so future contributors see a
shape they already recognise. forAllSystems is a one-liner that
guarantees linux/darwin × x86_64/aarch64 parity without sprinkling
if branches across the file.
Going to production
The CDN approach is fine for marketing pages. For better performance (smaller CSS, no runtime Tailwind compile), swap the Play CDN for the Tailwind standalone CLI:
# 1. Download the standalone CLI
# https://tailwindcss.com/blog/standalone-cli
# 2. Put the binary in ./bin/tailwindcss
# 3. Create src/site.css that imports Tailwind and DaisyUI:
# @import "tailwindcss";
# @plugin "daisyui";
# 4. Build
./bin/tailwindcss -i src/site.css -o static/css/site.css --minify
Then in index.html remove the Tailwind Play CDN <script> and the DaisyUI
<link>, and ensure /static/css/site.css is loaded last in <head>.
File layout
tui-pages-web/
├── index.html # landing page
├── examples.html # examples gallery
├── 404.html # not found
├── robots.txt # search engine hints
├── sitemap.xml # sitemap
├── static/
│ ├── css/
│ │ ├── site.css # our custom layer (small)
│ │ └── ascii.css # animation rules for the body-rain ASCII art
│ ├── img/
│ │ ├── favicon.svg
│ │ ├── logo.svg
│ │ ├── og-image.svg # 1200x630 social share card (used as-is)
│ │ ├── og-image-bg.svg # 1200x500 cropped variant (chafa source)
│ │ ├── terminal-default.svg
│ │ ├── terminal-canvas.svg
│ │ └── terminal-keybindings.svg
│ ├── ascii/
│ │ └── rain.txt # chafa render of og-image-bg.svg
│ └── demos/ # (empty — drop asciinema .cast files here)
├── content/ # (empty — markdown for blog/changelog later)
├── flake.nix # Nix dev shell, package, app, checks
├── flake.lock # (generated — pinned nixpkgs)
├── Makefile
├── .gitignore
└── README.md
Adding an asciinema demo to the hero
The hero currently shows the static SVG mockup
static/img/terminal-default.svg. To replace it with a real asciinema
recording (much more impressive, but requires a recorded cast):
-
Record one of the examples:
cd ../komp_ac/tui-pages/examples/default asciinema rec ../../tui-pages-web/static/demos/intro.cast # ... run the app for a few seconds, hit ctrl-d to stop -
In
index.html, replace the<!-- Hero terminal mockup -->block with:<div class="tp-terminal"> <asciinema-player src="/static/demos/intro.cast" autoplay loop></asciinema-player> </div> -
Add the asciinema player to the
<head>:<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/asciinema-player@3.7.0/dist/bundle/asciinema-player.css"> <script src="https://cdn.jsdelivr.net/npm/asciinema-player@3.7.0/dist/bundle/asciinema-player.js" defer></script>
The body-rain ASCII art is independent of the hero and stays as-is.
License
The website source is MIT-licensed. The terminal mockup SVGs in static/img/
are hand-drawn and original. The crate itself is at
https://gitlab.com/filipriec/tui-pages.