Add full-screen API-key gate

In user-key mode a browser with no stored Ollama key now gets a polished
gate instead of the app shell: one masked input with a show/hide toggle,
a single Continue button, inline validation errors, and a "?" help sheet
with the steps to a free key.

- Validates the draft key through /api/health (real 1-token probe) before
  saving; invalid-key and network failures read differently.
- Key still lives only in this browser's localStorage; nothing server-side.
- Gate wraps /, /create and deck study; server-key and local-daemon modes
  skip it; removing the key in Settings brings it back.
- Removes the now-redundant dashboard/create API-key banner.
- Monochrome corner glows (dark near-black / light near-white), 24px card,
  48px field and button, gentle fade/slide-in, reduced-motion aware.
- Help modal: centred dialog on desktop, bottom sheet on mobile, closes via
  X, Escape or backdrop.
- README and browser suites updated (34 gate checks, 15 key-flow checks,
  12 shipped-default checks; ui/folders/docs/pwa/security/contrast green).
This commit is contained in:
Martin Dvořák 2026-10-06 21:20:22 +00:00
commit dfa7b7502a
13 changed files with 505 additions and 94 deletions

View file

@ -1,3 +1,4 @@
import { ApiKeyGate } from "@/components/ApiKeyGate";
import { AppHeader } from "@/components/AppHeader";
import { MobileSidebar, Sidebar, SidebarOffset } from "@/components/Sidebar";
import { TabBar } from "@/components/TabBar";
@ -9,17 +10,19 @@ export const metadata = {
export default function CreatePage() {
return (
<div className="flex min-h-dvh bg-[var(--page)]">
<Sidebar />
<SidebarOffset />
<MobileSidebar />
<main className="min-w-0 flex-1">
<AppHeader />
<div className="mx-auto w-full max-w-3xl px-4 pb-cta lg:px-10 lg:pb-20">
<UploadScreen />
</div>
<TabBar />
</main>
</div>
<ApiKeyGate>
<div className="flex min-h-dvh bg-[var(--page)]">
<Sidebar />
<SidebarOffset />
<MobileSidebar />
<main className="min-w-0 flex-1">
<AppHeader />
<div className="mx-auto w-full max-w-3xl px-4 pb-cta lg:px-10 lg:pb-20">
<UploadScreen />
</div>
<TabBar />
</main>
</div>
</ApiKeyGate>
);
}