/* global React, Icon, Origin, SyncChip, Meter, CB, RoleChip, JobChip, Portrait, Tag, Empty, Seg, Input, useRoute */ // ============================================================ // Screens 1-2: Landing + Character binding // ============================================================ const { useState: useS12, useEffect: useE12 } = React; // -------------------- 1. Landing / login -------------------- function ScreenLanding() { const { go } = useRoute(); return (
Aether Hub
Changelog Docs Sign in
Now in open beta

One home for your characters, grinds, static, and FC.

A companion app + Discord bot that ties together what's currently scattered across spreadsheets and single-purpose sites. We sync the public data; you and your group track the rest — painlessly.

We never read your game client — only public data (Lodestone, FFLogs, community item APIs).

Track your grinds
Relics, mounts, achievements — checkable, zone-grouped, satisfying. Auto when we can, manual when we must.
Run your static
Roster, schedule, loot, and prog in one place. Paste an FFLogs link — attendance fills itself.
Bring your FC together
100-row roster, FC-wide stats, and a Discord bot that lives where your group already does.
); } // -------------------- 2. Character binding -------------------- function ScreenBinding() { const { go } = useRoute(); const [step, setStep] = useS12(1); // 1 = find, 2 = verify, 3 = done const [selected, setSelected] = useS12(null); const [verifyState, setVerifyState] = useS12('idle'); // idle | checking | error | ok const [query, setQuery] = useS12(''); const RESULTS = [ { name: "Aerith Nightsong", world: 'Sargatanas', dc: 'Aether', race: 'Au Ra' }, { name: 'Aerith Lightwhisper', world: 'Faerie', dc: 'Aether', race: 'Miqo\'te' }, { name: 'Aerith of the Veil', world: 'Adamantoise', dc: 'Aether', race: 'Viera' }, ]; return (
Aether Hub
Welcome, jakob

Bind your character

We use the Lodestone to prove ownership — no game client access, no addons.

{['Find character', 'Verify ownership', 'Done'].map((label, i) => { const n = i + 1; const state = step > n ? 'done' : step === n ? 'active' : 'idle'; return (
{state === 'done' ? : {n}}
{label}
{n < 3 &&
n ? 'done' : ''}`}>
}
); })}
{step === 1 && (

Find your character

Search the Lodestone by character name. World or data center is optional.

} placeholder="Character name" value={query} onChange={(e) => setQuery(e.target.value)} />
{RESULTS.map((r, i) => ( ))}
)} {step === 2 && (

Verify ownership

Paste the token below into your Lodestone character profile bio, save, then click verify. You can remove it afterward.

One-time verification token
aether-verify-7Q2F
  1. Open your Lodestone profile in a new tab.
  2. Click Edit profile and paste the token into your character profile / bio.
  3. Save your profile, then come back and click Verify.
{verifyState === 'checking' && (
Looking for your token on the Lodestone… this can take up to 30 seconds.
)} {verifyState === 'error' && (
We couldn't find the token yet
Make sure your profile is saved and visible. The Lodestone caches for a few minutes — try again shortly.
)}
{verifyState === 'idle' && ( )} {verifyState === 'checking' && ( )} {verifyState === 'error' && ( <> )}
)} {step === 3 && (

You're bound

{RESULTS[selected || 0].name} · {RESULTS[selected || 0].world} is now linked to your account. You can remove the token from your Lodestone bio whenever you like.

{RESULTS[selected || 0].name}
{RESULTS[selected || 0].world} · {RESULTS[selected || 0].dc} · Lv 100
Initial sync complete
)}

We only read your public Lodestone page. We never touch the game client and never ask for your Square Enix password.

); } Object.assign(window, { ScreenLanding, ScreenBinding });