Menu
Public repository / 01b0c3e49ec2c526bbda745999ffed8ebfa8b8ee
AkurAI-Drive / site/frontend/index.html
Latest change c76ec8a0ae8cd38cb6707c65d41a2e3c4ccdb370 - Drive backend wired: OIDC login completes, dashboard, real S3 provisioning by olibuijr
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AkurAI Drive — your private cloud, hosted in Iceland</title>
<meta name="description" content="AkurAI Drive is a private, Iceland-hosted file cloud for businesses and teams. Single sign-on with AkurAI, S3-backed storage, your data on infrastructure you control.">
<meta property="og:title" content="AkurAI Drive — your private cloud, hosted in Iceland">
<meta property="og:description" content="A private, Iceland-hosted file cloud. Sign in with AkurAI, unlimited S3-backed storage, real data residency.">
<meta property="og:type" content="website">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@500;600;700;800&family=Inter:wght@400;450;500;600&display=swap" rel="stylesheet">
<style>
:root{
--bg:#060912; --bg2:#0b1224; --panel:#0e162b; --ink:#eef3ff; --muted:#9fb0d4; --faint:#6b7aa3;
--brand:#5b8cff; --brand2:#7af0d0; --accent:#b388ff; --line:rgba(255,255,255,.08);
--line2:rgba(255,255,255,.14); --good:#7af0d0;
--r:16px; --maxw:1120px;
--display:"Sora",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
--body:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--body);font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased}
body::before{content:"";position:fixed;inset:0;z-index:-1;
background:
radial-gradient(900px 600px at 78% -8%, rgba(91,140,255,.20), transparent 55%),
radial-gradient(700px 520px at 8% 8%, rgba(122,240,208,.10), transparent 55%),
linear-gradient(180deg,#070b16,#060912 40%)}
a{color:inherit;text-decoration:none}
.container{max-width:var(--maxw);margin:0 auto;padding:0 24px}
.grad{background:linear-gradient(92deg,var(--brand),var(--brand2));-webkit-background-clip:text;background-clip:text;color:transparent}
h1,h2,h3{font-family:var(--display);letter-spacing:-.02em;line-height:1.08;margin:0}
.eyebrow{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;font-weight:500;letter-spacing:.04em;
color:var(--brand2);border:1px solid var(--line);background:rgba(122,240,208,.05);padding:6px 13px;border-radius:999px}
.dot{width:7px;height:7px;border-radius:50%;background:var(--brand2);box-shadow:0 0 12px var(--brand2)}
.btn{display:inline-flex;align-items:center;gap:9px;font-family:var(--body);font-weight:600;font-size:15px;
border-radius:12px;padding:12px 20px;cursor:pointer;border:1px solid transparent;transition:.15s;white-space:nowrap}
.btn-primary{color:#05121a;background:linear-gradient(92deg,var(--brand),var(--brand2));box-shadow:0 12px 34px rgba(91,140,255,.28)}
.btn-primary:hover{filter:brightness(1.07);transform:translateY(-1px)}
.btn-ghost{color:var(--ink);border-color:var(--line2);background:rgba(255,255,255,.02)}
.btn-ghost:hover{background:rgba(255,255,255,.06)}
.btn-sm{padding:9px 15px;font-size:14px}
/* nav */
nav{position:sticky;top:0;z-index:40;backdrop-filter:blur(12px);background:rgba(6,9,18,.72);border-bottom:1px solid var(--line)}
.nav-in{display:flex;align-items:center;justify-content:space-between;height:64px}
.brand{display:flex;align-items:center;gap:11px;font-family:var(--display);font-weight:700;font-size:18px}
.brand small{display:block;font-family:var(--body);font-weight:450;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint)}
.mark{width:32px;height:32px;flex:none}
.nav-links{display:flex;align-items:center;gap:8px}
.nav-links a.txt{color:var(--muted);padding:8px 12px;border-radius:9px;font-size:14.5px;font-weight:500}
.nav-links a.txt:hover{color:var(--ink);background:rgba(255,255,255,.04)}
@media(max-width:720px){.nav-links a.txt{display:none}}
/* hero */
.hero{padding:78px 0 54px}
.hero h1{font-size:clamp(38px,6.4vw,68px);font-weight:800;margin:18px 0 18px}
.lede{font-size:clamp(17px,2.2vw,21px);color:var(--muted);max-width:60ch;margin:0 0 30px}
.btn-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.hero-meta{display:flex;gap:22px;flex-wrap:wrap;margin-top:30px;color:var(--faint);font-size:13.5px}
.hero-meta b{color:var(--muted);font-weight:600}
/* trust strip */
.trust{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:rgba(255,255,255,.015)}
.trust-in{display:flex;flex-wrap:wrap;gap:14px 34px;align-items:center;justify-content:center;padding:18px 24px;color:var(--faint);font-size:13px}
.trust-in span{display:inline-flex;align-items:center;gap:8px}
.trust-in svg{width:16px;height:16px;color:var(--brand2)}
/* sections */
section.block{padding:74px 0}
.sec-head{text-align:center;max-width:660px;margin:0 auto 46px}
.sec-head h2{font-size:clamp(28px,4vw,40px);font-weight:700}
.sec-head p{color:var(--muted);margin:14px 0 0;font-size:17px}
.kicker{color:var(--brand2);font-weight:600;font-size:13px;letter-spacing:.08em;text-transform:uppercase}
.grid{display:grid;gap:18px}
.g4{grid-template-columns:repeat(4,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
@media(max-width:920px){.g4{grid-template-columns:repeat(2,1fr)}.g3{grid-template-columns:1fr}}
@media(max-width:560px){.g4{grid-template-columns:1fr}}
.card{border:1px solid var(--line);border-radius:var(--r);padding:22px;background:linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.012))}
.card .ico{width:26px;height:26px;color:var(--brand);margin-bottom:12px}
.card h3{font-size:16.5px;font-weight:600;margin-bottom:7px}
.card p{color:var(--muted);font-size:14.5px;margin:0}
/* steps */
.steps{counter-reset:s}
.step{position:relative;padding-left:60px}
.step::before{counter-increment:s;content:counter(s);position:absolute;left:0;top:-2px;width:40px;height:40px;border-radius:11px;
display:grid;place-items:center;font-family:var(--display);font-weight:700;color:#05121a;background:linear-gradient(92deg,var(--brand),var(--brand2))}
.step h3{font-size:17px;margin-bottom:6px}
.step p{color:var(--muted);font-size:14.5px;margin:0}
/* pricing */
.price-grid{align-items:stretch}
.plan{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:18px;padding:26px;background:var(--panel)}
.plan.feat{border-color:rgba(91,140,255,.5);box-shadow:0 0 0 1px rgba(91,140,255,.25),0 24px 60px rgba(91,140,255,.12);position:relative}
.plan.feat::after{content:"Most popular";position:absolute;top:-11px;left:50%;transform:translateX(-50%);
font-size:11.5px;font-weight:600;letter-spacing:.04em;color:#05121a;background:linear-gradient(92deg,var(--brand),var(--brand2));padding:4px 12px;border-radius:999px}
.plan h3{font-size:18px;font-weight:700}
.plan .price{font-family:var(--display);font-weight:800;font-size:38px;margin:14px 0 2px}
.plan .price span{font-family:var(--body);font-size:15px;font-weight:500;color:var(--faint)}
.plan .sub{color:var(--muted);font-size:14px;min-height:40px}
.plan ul{list-style:none;margin:18px 0 22px;padding:0;display:grid;gap:11px}
.plan li{display:flex;gap:10px;align-items:flex-start;color:var(--muted);font-size:14.5px}
.plan li svg{width:18px;height:18px;color:var(--good);flex:none;margin-top:1px}
.plan .btn{justify-content:center;margin-top:auto}
/* security band */
.band{border:1px solid var(--line);border-radius:22px;padding:40px;background:
radial-gradient(600px 300px at 100% 0,rgba(122,240,208,.10),transparent 60%),
linear-gradient(180deg,rgba(255,255,255,.04),rgba(255,255,255,.01))}
.band-grid{display:grid;grid-template-columns:1.1fr 1fr;gap:34px;align-items:center}
@media(max-width:820px){.band-grid{grid-template-columns:1fr}}
.band h2{font-size:clamp(24px,3.4vw,32px)}
.band p{color:var(--muted);margin:14px 0 0}
.chips{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}
.chip{font-size:13px;color:var(--muted);border:1px solid var(--line2);border-radius:999px;padding:7px 13px;background:rgba(255,255,255,.02)}
/* final cta */
.final{text-align:center;border:1px solid var(--line);border-radius:24px;padding:54px 28px;background:
radial-gradient(700px 360px at 50% 0,rgba(91,140,255,.16),transparent 60%),var(--panel)}
.final h2{font-size:clamp(28px,4.4vw,44px);font-weight:800}
.final p{color:var(--muted);max-width:52ch;margin:14px auto 26px;font-size:17px}
footer{border-top:1px solid var(--line);margin-top:30px;padding:30px 0;color:var(--faint);font-size:13.5px}
.foot-in{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;align-items:center}
footer a{color:var(--muted)}footer a:hover{color:var(--ink)}
/* modal */
.modal{position:fixed;inset:0;z-index:60;display:none;place-items:center;padding:20px;background:rgba(4,7,14,.66);backdrop-filter:blur(6px)}
.modal.open{display:grid}
.sheet{width:100%;max-width:460px;border:1px solid var(--line2);border-radius:20px;background:var(--panel);
box-shadow:0 40px 100px rgba(0,0,0,.6);overflow:hidden;animation:pop .18s ease}
@keyframes pop{from{transform:translateY(8px) scale(.99);opacity:0}to{transform:none;opacity:1}}
.sheet-h{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:22px 22px 6px}
.sheet-h h3{font-size:19px}
.sheet-h p{color:var(--muted);font-size:13.5px;margin:5px 0 0}
.x{cursor:pointer;color:var(--faint);background:none;border:0;font-size:22px;line-height:1;padding:2px 4px}
.x:hover{color:var(--ink)}
form.create{padding:14px 22px 22px;display:grid;gap:14px}
.field label{display:block;font-size:13px;font-weight:500;color:var(--muted);margin-bottom:6px}
.field input,.field select{width:100%;background:#0a1124;border:1px solid var(--line2);border-radius:11px;color:var(--ink);
font-family:var(--body);font-size:15px;padding:11px 13px;outline:none}
.field input:focus,.field select:focus{border-color:var(--brand)}
.gate{border:1px dashed rgba(179,136,255,.4);border-radius:12px;padding:13px;background:rgba(179,136,255,.05)}
.gate label{color:var(--accent)}
.gate .hint{font-size:12px;color:var(--faint);margin-top:7px}
.create .btn{justify-content:center;margin-top:4px}
.note{font-size:12.5px;color:var(--faint);text-align:center}
.msg{font-size:13.5px;padding:10px 12px;border-radius:10px;display:none}
.msg.show{display:block}
.msg.err{background:rgba(255,90,90,.1);color:#ffb1b1;border:1px solid rgba(255,90,90,.3)}
.msg.ok{background:rgba(122,240,208,.1);color:var(--good);border:1px solid rgba(122,240,208,.3)}
</style>
</head>
<body>
<!-- NAV -->
<nav>
<div class="container nav-in">
<a class="brand" href="/">
<svg class="mark" viewBox="0 0 48 48" fill="none" aria-hidden="true">
<defs><linearGradient id="g" x1="0" y1="0" x2="48" y2="48"><stop offset="0" stop-color="#5b8cff"/><stop offset="1" stop-color="#7af0d0"/></linearGradient></defs>
<path d="M24 5 6 15v18l18 10 18-10V15L24 5Z" stroke="url(#g)" stroke-width="2.2" stroke-linejoin="round"/>
<path d="M16 22.5 24 27l8-4.5M24 27v9.5M24 18.5V27" stroke="url(#g)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span>AkurAI Drive<small>Hosted in Iceland</small></span>
</a>
<div class="nav-links">
<a class="txt" href="#features">Features</a>
<a class="txt" href="#pricing">Pricing</a>
<a class="txt" href="#how">How it works</a>
<a class="txt" id="signin-link" href="#">Sign in</a>
<button class="btn btn-primary btn-sm" data-open-create>Get your Drive</button>
</div>
</div>
</nav>
<!-- HERO -->
<header class="hero">
<div class="container">
<span class="eyebrow"><span class="dot"></span> Early access · built on the AkurAI platform</span>
<h1>Your private cloud,<br><span class="grad">hosted in Iceland.</span></h1>
<p class="lede">AkurAI Drive gives businesses and teams a private file cloud — single sign-on with your
AkurAI account, S3-backed storage that scales without limits, and your data on infrastructure you control.</p>
<div class="btn-row">
<button class="btn btn-primary" data-open-create>Get your Drive
<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M5 12h14M13 6l6 6-6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<a class="btn btn-ghost" id="signin-cta" href="#">Sign in with AkurAI</a>
</div>
<div class="hero-meta">
<span><b>SSO</b> via AkurAI ID</span>
<span><b>S3</b> object storage</span>
<span><b>🇮🇸</b> Icelandic data residency</span>
<span><b>No</b> third-party gatekeeper</span>
</div>
</div>
</header>
<!-- TRUST -->
<div class="trust">
<div class="trust-in">
<span><svg viewBox="0 0 24 24" fill="none"><path d="M12 2 4 6v6c0 5 3.4 8 8 10 4.6-2 8-5 8-10V6l-8-4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg> End-to-edge TLS</span>
<span><svg viewBox="0 0 24 24" fill="none"><rect x="4" y="10" width="16" height="11" rx="2" stroke="currentColor" stroke-width="1.8"/><path d="M8 10V7a4 4 0 0 1 8 0v3" stroke="currentColor" stroke-width="1.8"/></svg> SSO + group roles</span>
<span><svg viewBox="0 0 24 24" fill="none"><path d="M3 7h18M3 7l2-3h14l2 3M5 7v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg> Unlimited storage</span>
<span><svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.8"/><path d="M3 12h18M12 3c2.5 2.7 2.5 15 0 18" stroke="currentColor" stroke-width="1.6"/></svg> Your region, your rules</span>
</div>
</div>
<!-- FEATURES -->
<section class="block" id="features">
<div class="container">
<div class="sec-head">
<div class="kicker">Why AkurAI Drive</div>
<h2>A cloud that works for <span class="grad">your business</span>, not against it</h2>
<p>Built on the AkurAI platform — the same identity, the same infrastructure, the same Icelandic-first principles.</p>
</div>
<div class="grid g4">
<article class="card">
<svg class="ico" viewBox="0 0 24 24" fill="none"><path d="M12 2 4 6v6c0 5 3.4 8 8 10 4.6-2 8-5 8-10V6l-8-4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="m9 12 2 2 4-4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
<h3>One identity</h3>
<p>Sign in with your AkurAI account. One login across mail, drive, and every AkurAI service — with group-based roles.</p>
</article>
<article class="card">
<svg class="ico" viewBox="0 0 24 24" fill="none"><ellipse cx="12" cy="6" rx="8" ry="3" stroke="currentColor" stroke-width="1.8"/><path d="M4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3" stroke="currentColor" stroke-width="1.8"/></svg>
<h3>Unlimited storage</h3>
<p>Files stream directly to S3 over signed links — the server never holds your bytes, so capacity simply isn't a ceiling.</p>
</article>
<article class="card">
<svg class="ico" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.8"/><path d="M3 12h18M12 3c2.5 2.7 2.5 15 0 18M12 3C9.5 5.7 9.5 18 12 21" stroke="currentColor" stroke-width="1.6"/></svg>
<h3>Data residency</h3>
<p>Your organisation's data stays on infrastructure you control — real Icelandic-first residency, not a checkbox.</p>
</article>
<article class="card">
<svg class="ico" viewBox="0 0 24 24" fill="none"><path d="M13 2 3 14h7l-1 8 10-12h-7l1-8Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
<h3>Instant provisioning</h3>
<p>Pick a plan and your storage is created on demand — a dedicated, isolated bucket per organisation, ready in seconds.</p>
</article>
</div>
</div>
</section>
<!-- HOW IT WORKS -->
<section class="block" id="how" style="padding-top:10px">
<div class="container">
<div class="sec-head">
<div class="kicker">Onboarding</div>
<h2>From zero to your own Drive in three steps</h2>
</div>
<div class="grid g3 steps">
<div class="step"><h3>Sign in with AkurAI</h3><p>Use your AkurAI ID — or create one. Single sign-on means no new password to remember.</p></div>
<div class="step"><h3>Choose a plan & create storage</h3><p>Pick the size that fits. We provision a private, S3-backed bucket for your organisation instantly.</p></div>
<div class="step"><h3>Upload & share</h3><p>Drag in your files, organise into folders, and share with your team by role. Everything stays in your region.</p></div>
</div>
</div>
</section>
<!-- PRICING -->
<section class="block" id="pricing">
<div class="container">
<div class="sec-head">
<div class="kicker">Buy hosting</div>
<h2>Simple plans, <span class="grad">no surprises</span></h2>
<p>Pay for the space you need. Every plan includes SSO, role-based sharing, and Icelandic data residency.</p>
</div>
<div class="grid g3 price-grid">
<div class="plan">
<h3>Starter</h3>
<div class="price">2.490 kr<span>/mo</span></div>
<div class="sub">For individuals and small teams getting started.</div>
<ul>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> 100 GB storage</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Up to 5 members</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> SSO + role sharing</li>
</ul>
<button class="btn btn-ghost" data-open-create data-plan="starter">Choose Starter</button>
</div>
<div class="plan feat">
<h3>Pro</h3>
<div class="price">6.990 kr<span>/mo</span></div>
<div class="sub">For growing teams that live in their files.</div>
<ul>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> 1 TB storage</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Up to 25 members</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Versioning + audit log</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Priority support</li>
</ul>
<button class="btn btn-primary" data-open-create data-plan="pro">Choose Pro</button>
</div>
<div class="plan">
<h3>Business</h3>
<div class="price">Custom</div>
<div class="sub">Dedicated capacity, residency guarantees, SLAs.</div>
<ul>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Unlimited storage</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Unlimited members</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Dedicated bucket + region</li>
<li><svg viewBox="0 0 24 24" fill="none"><path d="m5 13 4 4 10-10" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg> Onboarding & SLA</li>
</ul>
<a class="btn btn-ghost" href="mailto:olibuijr@olibuijr.com?subject=AkurAI%20Drive%20Business">Talk to us</a>
</div>
</div>
</div>
</section>
<!-- SECURITY BAND -->
<section class="block" style="padding-top:10px">
<div class="container">
<div class="band">
<div class="band-grid">
<div>
<div class="kicker">Security & trust</div>
<h2>Built so your bytes never touch our servers</h2>
<p>Uploads and downloads go straight from your browser to S3 over signed links. The application plane only
issues those links and tracks metadata — so there's no central pile of your files to breach, and capacity is effectively unlimited.</p>
<div class="chips">
<span class="chip">TLS everywhere</span><span class="chip">Argon2 + SSO</span>
<span class="chip">Per-org isolation</span><span class="chip">Signed direct-to-S3</span>
<span class="chip">Audit trail</span><span class="chip">Icelandic residency</span>
</div>
</div>
<div>
<article class="card" style="background:rgba(255,255,255,.03)">
<svg class="ico" viewBox="0 0 24 24" fill="none" style="width:30px;height:30px"><rect x="3" y="11" width="18" height="10" rx="2" stroke="currentColor" stroke-width="1.8"/><path d="M7 11V7a5 5 0 0 1 10 0v4" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="16" r="1.6" fill="currentColor"/></svg>
<h3>Your data plane is separate from ours</h3>
<p>The browser is the bridge between you and your storage. We hold the keys to the door, never the contents of the room.</p>
</article>
</div>
</div>
</div>
</div>
</section>
<!-- FINAL CTA -->
<section class="block" style="padding-top:0">
<div class="container">
<div class="final">
<h2>Ready for a cloud that's <span class="grad">actually yours</span>?</h2>
<p>Create your AkurAI Drive in under a minute. Sign in, pick a plan, and your private storage is ready.</p>
<div class="btn-row" style="justify-content:center">
<button class="btn btn-primary" data-open-create>Get your Drive</button>
<a class="btn btn-ghost" id="signin-cta2" href="#">Sign in</a>
</div>
</div>
</div>
</section>
<footer>
<div class="container foot-in">
<span>© AkurAI — akurai-drive.olibuijr.com · powered by AkurAI Framework</span>
<span><a href="https://auth.olibuijr.com">Account</a> · <a href="https://auth.olibuijr.com/health">Status</a> · <a href="https://github.com/olibuijr/AkurAI">AkurAI</a></span>
</div>
</footer>
<!-- CREATE STORAGE MODAL -->
<div class="modal" id="create-modal" role="dialog" aria-modal="true" aria-labelledby="cm-title">
<div class="sheet">
<div class="sheet-h">
<div>
<h3 id="cm-title">Create your Drive storage</h3>
<p>Sign in with AkurAI, choose a plan, and we'll provision a private bucket for your organisation.</p>
</div>
<button class="x" data-close-create aria-label="Close">×</button>
</div>
<form class="create" id="create-form" novalidate>
<div class="msg" id="cm-msg"></div>
<div class="field">
<label for="cm-org">Organisation name</label>
<input id="cm-org" name="org" type="text" placeholder="Acme ehf." required autocomplete="organization">
</div>
<div class="field">
<label for="cm-email">Work email</label>
<input id="cm-email" name="email" type="email" placeholder="you@company.is" required autocomplete="email">
</div>
<div class="field">
<label for="cm-plan">Plan</label>
<select id="cm-plan" name="plan">
<option value="starter">Starter — 100 GB</option>
<option value="pro" selected>Pro — 1 TB</option>
<option value="business">Business — custom</option>
</select>
</div>
<div class="field gate">
<label for="cm-gate">Access code <span style="font-weight:400">(early access)</span></label>
<input id="cm-gate" name="gate" type="password" placeholder="Enter the access code" autocomplete="off" required>
<div class="hint">AkurAI Drive is in early access. Storage creation is gated while we onboard the first organisations.</div>
</div>
<button class="btn btn-primary" type="submit" id="cm-submit">Create my storage</button>
<div class="note">By creating storage you agree to AkurAI's terms. You can delete it anytime.</div>
</form>
</div>
</div>
<script type="module">
// Every "sign in" + "Get your Drive" + "Choose plan" CTA routes through the
// backend OIDC login (/auth/login owns the OAuth state). Storage is created on
// the authenticated dashboard (/app), so guests sign in first.
const LOGIN = "/auth/login";
for (const id of ["signin-link","signin-cta","signin-cta2"]) {
const el = document.getElementById(id); if (el) el.href = LOGIN;
}
document.querySelectorAll("[data-open-create]").forEach(b =>
b.addEventListener("click", () => { location.href = LOGIN; }));
const planSel = { value: "" }; // retained: pricing CTAs pass data-plan; dashboard handles plan
// --- Submit: POST to the gated storage endpoint. The access code travels as a header
// (X-Drive-Access-Code); nginx enforces it server-side, then proxies the {org,email,plan}
// body to the framework's `storage` collection. The raw auto-API is blocked, so the gate
// cannot be bypassed by posting directly. ---
const STORAGE_ENDPOINT = "/api/storage";
const form = document.getElementById("create-form");
const msg = document.getElementById("cm-msg");
const submit = document.getElementById("cm-submit");
const showMsg = (text, kind) => { msg.textContent = text; msg.className = "msg show " + kind; };
form.addEventListener("submit", async (e) => {
e.preventDefault();
msg.className = "msg";
const code = form.gate.value;
const body = { org: form.org.value.trim(), email: form.email.value.trim(), plan: form.plan.value };
if (!body.org || !body.email || !code) { showMsg("Please fill in every field.", "err"); return; }
submit.disabled = true; submit.textContent = "Creating…";
try {
const res = await fetch(STORAGE_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Drive-Access-Code": code },
body: JSON.stringify(body)
});
if (res.ok) {
showMsg("Storage request accepted — we're provisioning your bucket. Check your email.", "ok");
form.reset();
} else if (res.status === 401 || res.status === 403) {
showMsg("That access code isn't valid. AkurAI Drive is in early access.", "err");
} else {
const t = await res.text().catch(() => "");
showMsg("Couldn't create storage right now. " + (t.slice(0, 120) || "Please try again."), "err");
}
} catch (err) {
showMsg("Network error — please try again.", "err");
} finally {
submit.disabled = false; submit.textContent = "Create my storage";
}
});
</script>
</body>
</html>