232 lines
8.3 KiB
Markdown
232 lines
8.3 KiB
Markdown
# 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
|
||
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`](https://github.com/hpjansson/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`):
|
||
|
||
```bash
|
||
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, with `z-index: -1` and
|
||
`pointer-events: none` so 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 seamless
|
||
`translateY(0 → -50%)` loop over 90 s.
|
||
- Color is `#f4a26b` (warm rust-orange) at 14% opacity with a faint
|
||
`text-shadow` glow — picks up the brand colour and reads as a subtle
|
||
background, not a wall of `@` blocks.
|
||
- A `::after` overlay draws a 2 px CRT scanline pattern that ticks
|
||
downward at 8 s/cycle.
|
||
- The hero section has a `.tp-ascii-hero-overlay` class 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.
|
||
|
||
```bash
|
||
# 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**:
|
||
|
||
```bash
|
||
# 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):
|
||
|
||
1. Record one of the examples:
|
||
|
||
```bash
|
||
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
|
||
```
|
||
|
||
2. In `index.html`, replace the `<!-- Hero terminal mockup -->` block
|
||
with:
|
||
|
||
```html
|
||
<div class="tp-terminal">
|
||
<asciinema-player src="/static/demos/intro.cast" autoplay loop></asciinema-player>
|
||
</div>
|
||
```
|
||
|
||
3. Add the asciinema player to the `<head>`:
|
||
|
||
```html
|
||
<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>.
|