Files
ulicraft-server-v1/plan/09-landing.md
Oier Bravo Urtasun 3d52951355 feat(landing): pixel design ported to static Astro + en/es/eu i18n
Adopt the "Carved from stone" pixel design (landing/design/) as the apex
onboarding page, ported from its React/Babel-via-CDN prototype to static
Astro so it works on an offline LAN. Real modded-LAN content replaces the
prototype's fictional public-SMP copy.

- Vendor web fonts locally (tooling/fetch-fonts.sh -> public/fonts/) so the
  page renders without the Google Fonts CDN at party time.
- Port the design system (main.css: mood/hero/bevels) and split markup into
  Astro components (Creeper, PixelIcon, CopyChip, ServerListPanel).
- site.ts holds language-neutral config + theme knobs (mood/hero/headFont/
  dust) that replace the design's in-browser TweaksPanel; LITERALS holds
  never-translated product/in-game terms.
- i18n: English (/), Spanish (/es/), Euskera (/eu/) generated from one
  [...lang].astro via getStaticPaths; copy lives in src/i18n/ui.ts. Nav has
  an EN/ES/EU switcher; html lang + hreflang set per page.
- Status panel shows a static server-list row + honest stat tiles (no fake
  live count). Copy + scroll-reveal are the only client JS.

Build emits to ../www (gitignored). Euskera strings pending a native review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 18:18:36 +02:00

116 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Landing page — guest onboarding site
## Summary
Apex `ulicraft.local` serves a static page guiding guests through joining:
download launcher → add account → import modpack → connect. Built with **Astro +
TypeScript** in `./landing/`; `pnpm run build` emits straight into `./www/`,
which Caddy/nginx serve at the apex. No runtime framework — output is plain
HTML/CSS plus one tiny vanilla script (copy-to-clipboard + scroll reveal).
The visual is the **"Carved from stone"** pixel design ("Claude Design",
`landing/design/`): dark overworld palette, MC-GUI bevel buttons, pixel type,
creeper mark, server-list panel. That design was a React/Babel-via-CDN prototype
for a *fictional public SMP*; it was **ported to static Astro** with the real
modded-LAN content and offline-safe assets.
## Stack & wiring
- `landing/` — Astro project (own `package.json`, `tsconfig`). pnpm only.
- `astro.config.mjs``outDir: "../www"`. Build overwrites `www/`; `www/` is
gitignored (generated artifact).
- `BASE_DOMAIN` env read at build time in `src/data/site.ts`
(`process.env.BASE_DOMAIN ?? "ulicraft.local"`). Bake before deploy:
`BASE_DOMAIN=ulicraft.local pnpm run build`.
- Logo: wide wordmark from the design at `landing/public/logo.png` (hero + favicon).
`image-rendering: pixelated` keeps it crisp.
### Source layout
```
landing/
├── design/ # "Claude Design" prototype (reference, not built)
├── public/
│ ├── logo.png # hero wordmark (from design/assets/ulicraft-logo.png)
│ └── fonts/ # vendored woff2 + fonts.css (offline-safe)
└── src/
├── data/site.ts # single source: content + theme knobs
├── styles/main.css # ported design system (mood/hero/bevels)
├── components/ # Creeper, PixelIcon, CopyChip, ServerListPanel
└── pages/index.astro # composition + copy/reveal script + dust
```
## Fonts — vendored for offline LAN
The design pulled fonts from Google Fonts CDN; that breaks on offline LAN day.
`tooling/fetch-fonts.sh` downloads the woff2 + a URL-rewritten `fonts.css` into
`landing/public/fonts/`. `index.astro` links `/fonts/fonts.css`. Re-run the
script only if the font set changes (keep families in sync with `main.css`
`--font-*`): Pixelify Sans, Space Grotesk, Press Start 2P, Silkscreen, VT323.
## Theme config (replaces the design's in-browser TweaksPanel)
`site.ts` `theme` is baked at build — edit + rebuild to change:
- `mood`: `grass` (default) | `nether` | `end`
- `hero`: `centered` (default) | `split` | `spotlight`
- `headFont`: `pixelify` (default) | `8bit` | `silkscreen`
- `dust`: floating hero particles (CSS animation; respects reduced-motion)
`index.astro` sets `<html data-mood data-hero data-head>` + `--font-head` from these.
## Languages (i18n)
Three locales, static, build-time, offline-safe — **English** (default, `/`),
**Spanish** (`/es/`), **Euskera** (`/eu/`).
- One template `src/pages/[...lang].astro` with `getStaticPaths` emits all three
routes (`/`, `/es/`, `/eu/`). No runtime/JS routing.
- Translatable copy lives in `src/i18n/ui.ts` (`ui[locale]`), keyed identically
across locales. `site.ts` holds only language-neutral config (URLs, theme,
launcher files, stat/feature *structure*).
- Product / in-game literals never translated — `site.ts` `LITERALS`
(`authlib-injector`, `Multiplayer`, `Add Server`). OS names + version too.
- Sentences with links/kbd are split into parts (pre/post/link, pa/pb) so markup
stays in the template, not the strings.
- Nav has a pixel `EN · ES · EU` switcher (`.lang-switch`); active locale
highlighted. `<html lang>` + `<link rel="alternate" hreflang>` set per page.
- Adding a locale: extend the `Lang` union + `ui`/`LANG_*` maps in `ui.ts`, add a
`getStaticPaths` entry. No template change.
## Content (real modded-LAN flow, all in site.ts)
- Hero: wordmark, eyebrow `Modded LAN · NeoForge 1.21.1`, tagline, sub, server
address `mc.${BASE_DOMAIN}` (copy chip), "How to Join".
- Status: static server-list panel (no fake live count — **option B**) + 4 honest
stat tiles (Mods / NeoForge ver / Player slots / Backups).
- Features ×4: kitchen-sink pack · self-hosted Drasl identity+skins · one-click
packwiz · built-to-last (homelab + 6h backups).
- How to Join ×4: **1** Fjord launcher (3 OS) → **2** authlib account
(`auth.${BASE_DOMAIN}/authlib-injector`) + register link + CA-cert note →
**3** packwiz import (`packwiz.${BASE_DOMAIN}/pack.toml`) → **4** connect.
- Footer: Mojang trademark disclaimer.
## Launcher download links (Option A — stable symlinks)
Page links to fixed names so they survive launcher version bumps:
- `fjord-windows-setup.exe`
- `fjord-macos.dmg`
- `fjord-linux-x86_64.AppImage`
`tooling/fetch-launcher.sh` must create these as symlinks under
`mirror/launcher/latest/` pointing at the real versioned assets. **Keep the names
in sync** between `site.ts` and the script. Mounted so they resolve at
`/launcher/latest/…` (see nginx/Caddy ingress).
## Tasks
- [x] Vendor fonts (`tooling/fetch-fonts.sh`) → `public/fonts/`
- [x] Port design → static Astro (components + main.css + index.astro)
- [x] Real content in `site.ts`; theme knobs replace TweaksPanel
- [x] i18n: en/es/eu via `[...lang].astro` + `i18n/ui.ts`; nav language switcher
- [x] `BASE_DOMAIN=ulicraft.local pnpm run build` → verified `www/` output + screenshot
- [ ] Extend `fetch-launcher.sh`: symlink stable names → versioned files
- [ ] Confirm ingress serves apex from `./www` and `/launcher/latest/*` from mirror
- [ ] Optional: try `mood: nether` / `hero: split` for party day
- [ ] Optional: wire real player count (option C) via mc-monitor JSON if wanted
```