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:
1 parent
c233b1bfbc
commit
c8a6c77a8e
12 files changed
+267
-207
No files matched your search
@@ -15,8 +15,8 @@ import "../../styles/main.css";
|
||||
// One static register page per locale: /register, /es/register, /eu/register.
|
||||
export function getStaticPaths() {
|
||||
return [
|
||||
{ params: { lang: undefined }, props: { locale: "en" as Lang } },
|
||||
{ params: { lang: "es" }, props: { locale: "es" as Lang } },
|
||||
{ params: { lang: undefined }, props: { locale: "es" as Lang } },
|
||||
{ params: { lang: "en" }, props: { locale: "en" as Lang } },
|
||||
{ params: { lang: "eu" }, props: { locale: "eu" as Lang } },
|
||||
];
|
||||
}
|
||||
@@ -27,12 +27,16 @@ const r = t.register;
|
||||
const { theme } = site;
|
||||
const headFont = HEAD_FONTS[theme.headFont] ?? HEAD_FONTS.pixelify;
|
||||
const homePath = LANG_PATH[locale];
|
||||
const requiresInvite = site.registrationRequiresInvite;
|
||||
const registerPath = LANG_REGISTER_PATH[locale];
|
||||
const accountPath = LANG_ACCOUNT_PATH[locale];
|
||||
// Visibility of the invite-code field (default hidden). Independent of the
|
||||
// backend gate (site.registrationRequiresInvite / Drasl RequireInvite).
|
||||
const showInvite = site.registrationShowInvite;
|
||||
|
||||
// Strings the client script needs at runtime (kept minimal, passed via define:vars).
|
||||
const clientCfg = {
|
||||
apiUrl: site.draslApiUrl,
|
||||
requiresInvite,
|
||||
showInvite,
|
||||
submit: r.submit,
|
||||
submitting: r.submitting,
|
||||
skinUpload: r.skinUpload,
|
||||
@@ -57,7 +61,7 @@ const clientCfg = {
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{site.name} — {r.title}</title>
|
||||
<meta name="description" content={r.lead} />
|
||||
<link rel="icon" type="image/png" href="/logo.png" />
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
<link rel="stylesheet" href="/fonts/fonts.css" />
|
||||
{LANGS.map((l) => <link rel="alternate" hreflang={l} href={LANG_REGISTER_PATH[l]} />)}
|
||||
</head>
|
||||
@@ -82,6 +86,8 @@ const clientCfg = {
|
||||
>{LANG_LABEL[l]}</a>
|
||||
))}
|
||||
</div>
|
||||
<a class="mc-btn sm" href={registerPath}>{t.nav.register}</a>
|
||||
<a class="mc-btn sm" href={accountPath}>{t.nav.login}</a>
|
||||
<a class="mc-btn primary sm" href={`${homePath}#join`}>{t.nav.play}</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -106,7 +112,7 @@ const clientCfg = {
|
||||
<input class="reg-input" id="reg-password" name="password"
|
||||
type="password" autocomplete="new-password" placeholder={r.passwordPlaceholder} required />
|
||||
</div>
|
||||
{requiresInvite && (
|
||||
{showInvite && (
|
||||
<div class="reg-field">
|
||||
<label for="reg-invite">{r.inviteLabel}</label>
|
||||
<input class="reg-input" id="reg-invite" name="invite"
|
||||
@@ -208,7 +214,7 @@ const clientCfg = {
|
||||
const password = $("reg-password").value;
|
||||
const inviteEl = $("reg-invite");
|
||||
const invite = inviteEl ? inviteEl.value.trim() : null;
|
||||
if (!username || !password || (cfg.requiresInvite && !invite)) {
|
||||
if (!username || !password || (cfg.showInvite && !invite)) {
|
||||
showErr(errBox, cfg.errFields);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user