feat(landing): rework — es default, 2-step join, roster + account polish

- Default language Spanish at root /, English moves to /en/ (eu unchanged):
  getStaticPaths {lang:undefined}->es + LANG_*_PATH maps swapped in ui.ts.
- Section order: hero -> join -> status -> members -> mods -> features.
- Join flow 3 -> 2 steps (drop the Connect/IP step; launcher handles the
  address). Remove the hero IP CopyChip. Header CTA renamed Play/Jugar/Jolastu
  and gains Register + Login links on all four pages.
- Account page: hide the whole login block once authenticated (not just the
  form), add an avatar Refresh button (cache-busted NMSR re-fetch), flatten the
  avatar (no bevel). New i18n key account.refresh.
- Register page: new REGISTRATION_SHOW_INVITE env (default false/hidden) toggles
  the invite-code field independently of the REGISTRATION_MODE backend gate.
- Members roster: drop the `admin` account, render full-body via a new
  ROSTER_AVATAR_MODE (default fullbodyiso); portrait tiles.
- Style: flatten emboss on feature icons (.picon) + player tiles (.roster-tile).
  PixelIcon gains optional image support (/icons/<name>.png|svg).
- Favicon now /favicon.png (committed) on all pages.
- Docs: plan/09-landing.md Assets section (logo/favicon/features-icons drop
  points) + default-language note; .env.example documents the two new vars.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 22:03:18 +02:00
parent c233b1bfbc
commit c8a6c77a8e
12 changed files with 267 additions and 207 deletions

View File

@@ -11,31 +11,31 @@
export type Lang = "en" | "es" | "eu";
export const LANGS: Lang[] = ["en", "es", "eu"];
export const LANG_LABEL: Record<Lang, string> = { en: "EN", es: "ES", eu: "EU" };
// URL path per locale (en is default, served at root).
export const LANG_PATH: Record<Lang, string> = { en: "/", es: "/es/", eu: "/eu/" };
// Register page path per locale (mirrors LANG_PATH: en at /register).
// URL path per locale (es is default, served at root; en moves to /en/).
export const LANG_PATH: Record<Lang, string> = { es: "/", en: "/en/", eu: "/eu/" };
// Register page path per locale (mirrors LANG_PATH: es at /register).
export const LANG_REGISTER_PATH: Record<Lang, string> = {
en: "/register",
es: "/es/register",
es: "/register",
en: "/en/register",
eu: "/eu/register",
};
// Fjord (alternative path) page path per locale (mirrors LANG_REGISTER_PATH).
export const LANG_FJORD_PATH: Record<Lang, string> = {
en: "/fjord",
es: "/es/fjord",
es: "/fjord",
en: "/en/fjord",
eu: "/eu/fjord",
};
// Account page path per locale (mirrors LANG_REGISTER_PATH).
export const LANG_ACCOUNT_PATH: Record<Lang, string> = {
en: "/account",
es: "/es/account",
es: "/account",
en: "/en/account",
eu: "/eu/account",
};
export interface UI {
htmlLang: string;
copied: string; // transient copy-button feedback
nav: { status: string; members: string; features: string; mods: string; join: string; play: string };
nav: { status: string; members: string; features: string; mods: string; join: string; play: string; register: string; login: string };
hero: {
eyebrow: string; // "Modded LAN · NeoForge" — version appended at render
tagline: string;
@@ -84,13 +84,6 @@ export interface UI {
registerLink: string;
};
s2: { kicker: string; h: string; p: string };
s3: {
kicker: string;
h: string;
pa: string; // before the Multiplayer/Add Server kbds
pb: string; // after them
copy: string;
};
};
fjord: {
navHome: string; // "← Home" link in nav
@@ -164,6 +157,7 @@ export interface UI {
noAccount: string; // "No account yet?"
registerLink: string; // links to /register
// Skin panel
refresh: string; // re-fetch the NMSR avatar
playerLabel: string; // "Logged in as"
skinTitle: string;
skinLead: string; // reuses register.skinLead concept
@@ -189,7 +183,7 @@ export const ui: Record<Lang, UI> = {
en: {
htmlLang: "en",
copied: "Copied!",
nav: { status: "Status", members: "Members", features: "Features", mods: "Mods", join: "How to Join", play: "Play Now" },
nav: { status: "Status", members: "Members", features: "Features", mods: "Mods", join: "How to Join", play: "Play", register: "Register", login: "Log in" },
hero: {
eyebrow: "Modded LAN · NeoForge",
tagline: "Kitchen-sink survival, built to outlast the weekend.",
@@ -249,7 +243,7 @@ export const ui: Record<Lang, UI> = {
empty: "Mod list not generated yet — check back soon.",
},
join: {
eyebrow: "How to Join · 3 Steps",
eyebrow: "How to Join · 2 Steps",
title: "From zero to spawning in.",
lead: "One-time setup. After this, the launcher keeps you in sync.",
s1: {
@@ -262,14 +256,7 @@ export const ui: Record<Lang, UI> = {
s2: {
kicker: "Launcher",
h: "Download {name}",
p: "Grab {name} for your system and log in with your Ulicraft credentials — it installs the modpack and everything else automatically.",
},
s3: {
kicker: "Connect",
h: "Join the server",
pa: "Launch the launcher, open",
pb: ", paste the address, and join.",
copy: "Copy IP",
p: "Grab {name}, log in with your Ulicraft credentials, and hit play. Everything else — the modpack, the server address, updates — is handled inside the launcher.",
},
},
fjord: {
@@ -354,6 +341,7 @@ export const ui: Record<Lang, UI> = {
submitting: "Logging in…",
noAccount: "No account yet?",
registerLink: "Register here",
refresh: "Refresh",
playerLabel: "Logged in as",
skinTitle: "Your skin",
skinLead: "Upload a Minecraft skin PNG. The 3D preview below updates instantly; the in-game avatar takes ~1 minute.",
@@ -377,7 +365,7 @@ export const ui: Record<Lang, UI> = {
es: {
htmlLang: "es",
copied: "¡Copiado!",
nav: { status: "Estado", members: "Miembros", features: "Características", mods: "Mods", join: "Cómo entrar", play: "Jugar ahora" },
nav: { status: "Estado", members: "Miembros", features: "Características", mods: "Mods", join: "Cómo entrar", play: "Jugar", register: "Registro", login: "Entrar" },
hero: {
eyebrow: "LAN con mods · NeoForge",
tagline: "Supervivencia todo incluido, para durar más que el finde.",
@@ -437,7 +425,7 @@ export const ui: Record<Lang, UI> = {
empty: "La lista de mods aún no está generada — vuelve pronto.",
},
join: {
eyebrow: "Cómo entrar · 3 pasos",
eyebrow: "Cómo entrar · 2 pasos",
title: "De cero a aparecer en el mundo.",
lead: "Configuración única. Después, el launcher te mantiene sincronizado.",
s1: {
@@ -450,14 +438,7 @@ export const ui: Record<Lang, UI> = {
s2: {
kicker: "Launcher",
h: "Descarga {name}",
p: "Coge {name} para tu sistema e inicia sesión con tus credenciales de Ulicraft: instala el modpack y todo lo demás automáticamente.",
},
s3: {
kicker: "Conectar",
h: "Entra al servidor",
pa: "Lanza el launcher, abre",
pb: ", pega la dirección y entra.",
copy: "Copiar IP",
p: "Coge {name}, inicia sesión con tus credenciales de Ulicraft y dale a jugar. Todo lo demás — el modpack, la dirección del servidor, las actualizaciones — se gestiona dentro del launcher.",
},
},
fjord: {
@@ -542,6 +523,7 @@ export const ui: Record<Lang, UI> = {
submitting: "Entrando…",
noAccount: "¿Aún no tienes cuenta?",
registerLink: "Regístrate aquí",
refresh: "Actualizar",
playerLabel: "Sesión iniciada como",
skinTitle: "Tu skin",
skinLead: "Sube un PNG de skin de Minecraft. La vista previa 3D se actualiza al instante; el avatar en el juego tarda ~1 minuto.",
@@ -565,7 +547,7 @@ export const ui: Record<Lang, UI> = {
eu: {
htmlLang: "eu",
copied: "Kopiatuta!",
nav: { status: "Egoera", members: "Kideak", features: "Ezaugarriak", mods: "Mods", join: "Nola sartu", play: "Jokatu orain" },
nav: { status: "Egoera", members: "Kideak", features: "Ezaugarriak", mods: "Mods", join: "Nola sartu", play: "Jolastu", register: "Erregistroa", login: "Sartu" },
hero: {
eyebrow: "Mod-dun LANa · NeoForge",
tagline: "Mod ugariko biziraupena, irauteko egina.",
@@ -625,7 +607,7 @@ export const ui: Record<Lang, UI> = {
empty: "Mod zerrenda oraindik ez da sortu — itzuli laster.",
},
join: {
eyebrow: "Nola sartu · 3 urrats",
eyebrow: "Nola sartu · 2 urrats",
title: "Zerotik mundura agertzera.",
lead: "Behin bakarrik konfiguratu. Gero, launcherrak sinkronizatuta mantenduko zaitu.",
s1: {
@@ -638,14 +620,7 @@ export const ui: Record<Lang, UI> = {
s2: {
kicker: "Launcherra",
h: "Deskargatu {name}",
p: "Hartu {name} zure sistemarako eta hasi saioa zure Ulicraft kredentzialekin: modpacka eta gainerako guztia automatikoki instalatzen du.",
},
s3: {
kicker: "Konektatu",
h: "Sartu zerbitzarira",
pa: "Abiarazi launcherra, ireki",
pb: ", itsatsi helbidea eta sartu.",
copy: "Kopiatu IPa",
p: "Hartu {name}, hasi saioa zure Ulicraft kredentzialekin eta sakatu jolastu. Gainerako guztia — modpacka, zerbitzariaren helbidea, eguneraketak — launcherraren barruan kudeatzen da.",
},
},
fjord: {
@@ -730,6 +705,7 @@ export const ui: Record<Lang, UI> = {
submitting: "Sartzen…",
noAccount: "Oraindik konturik ez?",
registerLink: "Erregistratu hemen",
refresh: "Eguneratu",
playerLabel: "Saioa hasita:",
skinTitle: "Zure azala",
skinLead: "Igo Minecraft azal PNG bat. 3D aurrebista berehala eguneratzen da; jokoko avatarra ~1 minutuan.",