Version 2 of 2 · · razie via designer-86designer · Current version

Open the page

---
description: Creator project setup as a signed base d2 Page (P-1215): how you work at this level, then Members (no members, by invite, open) and the dashboard becomes home
tags: page, onboarding
---
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><meta name="color-scheme" content="light dark"><title>Ready to start imagining</title>
<style>
:root{--paper:#fbfaf7;--card:#fff;--ink:#1d1d1b;--soft:#6b6a66;--line:#e4e1da;--rose:#b23a48;--lv:#4fb3a9;--display:'Manrope',system-ui,-apple-system,'Segoe UI',sans-serif;--body:system-ui,-apple-system,'Segoe UI',sans-serif}
@media (prefers-color-scheme:dark){:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--rose:#f08a92}}
*{box-sizing:border-box}html,body{background:var(--paper);color:var(--ink);margin:0}body{font:calc(15px*var(--fz,1))/1.5 var(--body)}
.sp-wrap{max-width:900px;margin:0 auto;padding:6px clamp(12px,3vw,28px) 56px}
h1{font:800 calc(clamp(26px,4vw,34px)*var(--fz,1))/1.1 var(--display);letter-spacing:-.02em;margin:12px 0}
h2{font:800 22px/1.2 var(--display);margin:28px 0 8px}a{color:var(--lv)}.small{font-size:13px;color:var(--soft)}
.emb{margin:16px 0}ul{padding-left:20px}li{margin:4px 0}
.sp-last{border-top:1px solid var(--line);margin-top:28px}
.sp-opts{display:grid;gap:10px;margin:12px 0 16px;max-width:560px}
.sp-opt{display:flex;gap:10px;align-items:flex-start;cursor:pointer;background:color-mix(in srgb,var(--lv) 9%,var(--card));border:1px solid color-mix(in srgb,var(--lv) 35%,var(--line));border-radius:12px;padding:12px 14px}
.sp-opt input{width:20px;height:20px;margin:2px 0 0;accent-color:var(--lv);flex:none}.sp-opt b{display:block}.sp-opt span{color:var(--soft);font-size:14px}
.sp-go{border:0;cursor:pointer;padding:14px 30px;border-radius:999px;background:var(--lv);color:#111;font:800 1.3em/1.2 var(--body);box-shadow:0 2px 8px rgba(0,0,0,.18)}.sp-go:disabled{opacity:.6;cursor:default}
.sp-say{display:block;margin-top:8px;color:var(--rose);font-size:13px;min-height:1em}
</style>
</head><body><div class="sp-wrap">
<h1>Ready to start imagining</h1>
<p>At this level you and your designer agent build useful apps with a spec behind them. You say what you want; your AI writes it down, designs it, builds the app and checks it.</p>
<div class="emb"><style>

.w{--c:#4fb3a9;--ink:#e8e6e1;--mute:#9aa0a6;--line:#2e343c;--card:#1b1f24;--ok:#4caf6a;background:#121417;border-radius:14px;padding:20px 18px;font:13px/1.35 system-ui,-apple-system,'Segoe UI',sans-serif;color:var(--ink);display:grid;grid-template-columns:auto 34px auto 34px minmax(0,1fr) minmax(150px,auto);align-items:center;gap:10px;overflow:hidden}
@media (max-width:640px){.w{display:flex;flex-wrap:wrap;justify-content:center;row-gap:16px}.w .lk{width:28px;flex:none}.w .lk.l2{display:none}.w .docs,.w .tests{flex:1 1 100%}}
.who{display:grid;justify-items:center;gap:6px;text-align:center}
.av{width:52px;height:52px;border-radius:50%;display:grid;place-items:center;font-weight:800;font-size:15px}
.you .av{border:2px solid var(--c);color:var(--c);background:#1b1f24}
.lbl{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--mute)}
.bub{max-width:150px;min-height:34px;background:color-mix(in srgb,var(--c) 22%,#1b1f24);border-radius:12px 12px 12px 4px;padding:6px 9px;font-size:12px;text-align:left}
.bub i{display:inline-block;width:1px;height:12px;background:var(--ink);vertical-align:-2px;animation:blink .8s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
/* the designer: an agent circle */
.ag .av{position:relative;width:62px;height:62px;background:radial-gradient(circle at 35% 30%,color-mix(in srgb,var(--c) 70%,#fff) 0,var(--c) 45%,color-mix(in srgb,var(--c) 45%,#000) 100%);color:#0d1a19;font-size:22px;box-shadow:0 0 0 0 color-mix(in srgb,var(--c) 60%,transparent);transition:box-shadow .4s}
.ag .av::after{content:"";position:absolute;inset:-7px;border-radius:50%;border:2px dashed color-mix(in srgb,var(--c) 70%,transparent);opacity:.25;transition:opacity .4s}
.ag.busy .av{box-shadow:0 0 22px 4px color-mix(in srgb,var(--c) 45%,transparent)}
.ag.busy .av::after{opacity:1;animation:spin 3s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.dots{height:12px;display:flex;gap:3px;justify-content:center}.dots b{width:5px;height:5px;border-radius:50%;background:var(--c);opacity:0}
.ag.busy .dots b{animation:dot 1s infinite}.ag.busy .dots b:nth-child(2){animation-delay:.15s}.ag.busy .dots b:nth-child(3){animation-delay:.3s}
@keyframes dot{0%,100%{opacity:.2;transform:translateY(0)}50%{opacity:1;transform:translateY(-3px)}}
/* the links between them: a pulse runs along */
.lk{position:relative;height:2px;background:var(--line);border-radius:2px}
.lk::after{content:"";position:absolute;top:-3px;left:0;width:8px;height:8px;border-radius:50%;background:var(--c);opacity:0}
.lk.go::after{animation:run .7s ease-in forwards}
@keyframes run{0%{left:0;opacity:1}100%{left:calc(100% - 8px);opacity:1}}
/* the docs write themselves */
.docs{display:flex;gap:10px;min-width:0}
.doc{flex:1 1 0;min-width:0;max-width:130px;background:#f4f1ea;color:#2a2a28;border-radius:4px 12px 4px 4px;padding:8px 9px 10px;box-shadow:0 3px 10px rgba(0,0,0,.35);opacity:.3;transform:translateY(6px);transition:opacity .4s,transform .4s;position:relative}
.doc.on{opacity:1;transform:none}
.doc h4{margin:0 0 6px;font:800 11px system-ui;letter-spacing:.05em;text-transform:uppercase;color:#1f6f68}
.doc .ln{height:5px;border-radius:3px;background:#c9c3b6;margin:5px 0;width:0;transition:width .35s ease-out}
.doc .ln.h{background:#7fb9b3;height:6px}
.pen{position:absolute;width:10px;height:10px;font-size:11px;opacity:0;transition:top .3s,left .3s,opacity .2s}
.doc.writing .pen{opacity:1}
.app{background:#1b1f24;color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:0 0 8px;overflow:hidden}
.app .bar{display:flex;gap:3px;padding:5px 6px;background:#232830}.app .bar b{width:6px;height:6px;border-radius:50%;background:#4a515b}
.app h4{color:var(--c);margin:6px 8px 4px}
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:5px;padding:0 8px}
.tiles span{height:20px;border-radius:5px;background:color-mix(in srgb,var(--c) 35%,#232830);transform:scale(.4);opacity:0;transition:transform .3s cubic-bezier(.3,1.6,.6,1),opacity .3s}
.tiles span.on{transform:none;opacity:1}
/* tests: a checklist that goes green */
.tests{background:#1b1f24;border:1px solid var(--line);border-radius:10px;padding:9px 11px;opacity:.3;transition:opacity .4s}
.tests.on{opacity:1}
.tests h4{margin:0 0 6px;font:800 11px system-ui;letter-spacing:.05em;text-transform:uppercase;color:var(--mute)}
.tests ul{list-style:none;margin:0;padding:0;display:grid;gap:5px}
.tests li{display:flex;gap:7px;align-items:center;color:var(--mute);transition:color .3s;white-space:nowrap}
.tests li .bx{width:15px;height:15px;flex:none;border-radius:4px;border:1.5px solid #4a515b;display:grid;place-items:center;font-size:11px;font-weight:900;color:transparent;transition:all .3s}
.tests li.ok{color:var(--ink)}
.tests li.ok .bx{background:var(--ok);border-color:var(--ok);color:#0b1a0f;transform:scale(1.15)}
.tests li.ok .bx{animation:pop .35s}
@keyframes pop{0%{transform:scale(.6)}70%{transform:scale(1.25)}100%{transform:scale(1)}}
.tests .sum{margin-top:7px;font-size:11px;color:var(--ok);opacity:0;transition:opacity .4s}.tests.done .sum{opacity:1}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
</style>
<div class="w" id="w">
  <div class="who you"><div class="bub" id="bub"><span id="say"></span><i></i></div><div class="av">you</div></div>
  <div class="lk l1" id="l1"></div>
  <div class="who ag" id="ag"><div class="av">✦</div><div class="dots"><b></b><b></b><b></b></div><div class="lbl">your designer</div></div>
  <div class="lk l2" id="l2"></div>
  <div class="docs">
    <div class="doc" id="d1"><span class="pen">✎</span><h4>Spec</h4><div class="ln h"></div><div class="ln"></div><div class="ln"></div><div class="ln h"></div><div class="ln"></div><div class="ln"></div></div>
    <div class="doc" id="d2"><span class="pen">✎</span><h4>Design</h4><div class="ln h"></div><div class="ln"></div><div class="ln"></div><div class="ln"></div><div class="ln h"></div><div class="ln"></div></div>
    <div class="doc app" id="d3"><div class="bar"><b></b><b></b><b></b></div><h4>App</h4><div class="tiles"><span></span><span></span><span></span><span></span></div></div>
  </div>
  <div class="tests" id="ts"><h4>Tests</h4><ul>
    <li><span class="bx">✓</span>products have a price</li>
    <li><span class="bx">✓</span>an order lists its items</li>
    <li><span class="bx">✓</span>paid takes it off stock</li>
    <li><span class="bx">✓</span>shows what runs low</li>
  </ul><div class="sum">4 of 4 passing</div></div>
</div>
<script>
// you ask → your designer works → Spec and Design write themselves → the app assembles → the tests go green; then again
const $=id=>document.getElementById(id),W=[0.92,0.7,0.84,0.6,0.88,0.5],T=[];
const at=(ms,f)=>T.push(setTimeout(f,ms));
const say="Make me a shop app: products, orders, stock.";
function write(d,t0){const ls=[...d.querySelectorAll('.ln')],pen=d.querySelector('.pen');
  at(t0,()=>d.classList.add('on','writing'));
  ls.forEach((l,k)=>at(t0+200+k*170,()=>{const w=W[k%W.length]*100;l.style.width=w+'%';pen.style.top=(l.offsetTop-6)+'px';pen.style.left='calc('+w+'% - 2px)'}));
  at(t0+200+ls.length*170+150,()=>d.classList.remove('writing'))}
function run(){T.splice(0).forEach(clearTimeout);
  const w=$('w');w.querySelectorAll('.on,.ok,.go,.busy,.done,.writing').forEach(e=>e.classList.remove('on','ok','go','busy','done','writing'));
  w.querySelectorAll('.ln').forEach(l=>l.style.width='0');$('say').textContent='';
  [...say].forEach((c,k)=>at(80+k*32,()=>$('say').textContent+=c));
  const t1=80+say.length*32+200;
  at(t1,()=>$('l1').classList.add('go'));
  at(t1+600,()=>$('ag').classList.add('busy'));
  at(t1+1100,()=>$('l2').classList.add('go'));
  write($('d1'),t1+1500);write($('d2'),t1+2600);
  const ta=t1+3700;at(ta,()=>$('d3').classList.add('on'));
  $('d3').querySelectorAll('.tiles span').forEach((s,k)=>at(ta+250+k*180,()=>s.classList.add('on')));
  const tt=ta+1200;at(tt,()=>$('ts').classList.add('on'));
  $('ts').querySelectorAll('li').forEach((li,k)=>at(tt+350+k*420,()=>li.classList.add('ok')));
  at(tt+350+4*420,()=>{$('ts').classList.add('done');$('ag').classList.remove('busy')});
  at(tt+350+4*420+3200,run)}
if(matchMedia('(prefers-reduced-motion: reduce)').matches){$('say').textContent=say;document.querySelectorAll('.doc,.tests,.tiles span').forEach(e=>e.classList.add('on'));document.querySelectorAll('.ln').forEach((l,k)=>l.style.width=W[k%W.length]*100+'%');document.querySelectorAll('.tests li').forEach(l=>l.classList.add('ok'));$('ts').classList.add('done')}
else run();
</script></div>
<ul><li><b>You:</b> ideas, in plain words, typed or spoken. Use <a href="/thoughts" data-go>Thoughts</a> to collect them and send them in a batch.</li><li><b>Your designer:</b> keeps the <a href="/topics/Spec" data-go>Specification</a>, the model and the apps in step.</li><li><b>No pipeline here:</b> one AI, one conversation at a time. Need a team? That's Pro.</li></ul>
<h2>Start working</h2>
<section class="sp-last" id="members">
<h2>Will other people work here?</h2>
<p class="small">Your project stays closed until you choose. You can change this any time in Settings.</p>
<div class="sp-opts" role="radiogroup" aria-label="Members">
<label class="sp-opt"><input type="radio" name="join" value="none" checked><div><b>No members</b><span>Just you and your AI.</span></div></label>
<label class="sp-opt"><input type="radio" name="join" value="invite"><div><b>By invite only</b><span>People join when you invite them.</span></div></label>
<label class="sp-opt"><input type="radio" name="join" value="open"><div><b>Open join</b><span>Anyone with an account can join.</span></div></label>
</div>
<p>Start working: the <a href="/app/Dashboard" data-go>dashboard</a> becomes your home page.</p>
<p><button class="sp-go" id="sp-go" type="button">Start working →</button> <span class="sp-say" id="sp-say" role="status"></span></p>
</section>
<p>Your <a href="/domain/overview" data-go>model</a> and <a href="/dom" data-go>data</a> are one tap away from it.</p>
</div>
<script>
(()=>{const D2=window.d2||{},$=s=>document.querySelector(s),LEVEL="creator",PAGE="Page:"+"SetupCreator";
const api=(m,u,b)=>D2.api?Promise.resolve(D2.api(m,u,b)):Promise.reject(new Error("E_BRIDGE: open this page in d2"));
const go=u=>D2.go?D2.go(u):(location.href=u);
const msg=e=>String(e&&e.message||e).replace(/^E_[A-Z_]+: /,"");
document.addEventListener("click",e=>{const a=e.target.closest&&e.target.closest("a[data-go]");if(!a)return;e.preventDefault();go(a.getAttribute("href"))});
// this page is the project's home from the moment the owner lands on it, until the last button makes the dashboard home
// (Razie 2026-10-10, P-1215: a signed d2 page sets the project's properties as its viewer); refused quietly to a member
(async()=>{try{const t=await api("GET","/api/v2/topics/Settings:PROJECT?format=raw");const s=typeof t==="string"?t:(t&&t.text)||"";
  const m=/^home:\s*(.*)$/m.exec(s);const cur=m?m[1].trim():"";if(!s||/App:Dashboard$/.test(cur)||cur.endsWith(PAGE))return;
  const next=m?s.replace(/^home:.*$/m,"home: "+PAGE):s.replace(/^---\n/,"---\nhome: "+PAGE+"\n");
  await api("PUT","/api/v2/drafts/Settings:PROJECT?ver=none",next);await api("POST","/api/v2/drafts/Settings:PROJECT/publish")}catch(e){}})();
$("#sp-go").onclick=async()=>{const b=$("#sp-go"),say=$("#sp-say"),v=(document.querySelector("input[name=join]:checked")||{}).value||"none";
  b.disabled=true;say.textContent="";
  // who can join, then the dashboard becomes home (P-1216: PATCH /api/v2/project {join}; no members and by invite are both join invite)
  try{await api("PATCH","/api/v2/project",{join:v==="open"?"open":"invite"});await api("POST","/api/v2/project/home",{to:"dashboard"});go("/")}
  catch(e){say.textContent=msg(e);b.disabled=false}};
})();
</script>
</body></html>