import { useState } from "react"; import { Instagram, Youtube, Facebook, Twitter, Check, ChevronRight, ChevronLeft, ArrowRight, FolderOpen, Cloud, Smartphone, RefreshCw, FileText, Sparkles, Code2, UtensilsCrossed, Lightbulb, Lock, Infinity as Inf, Download, X, FolderPlus, Folder, Plus, ShieldCheck, TrendingUp, CornerDownRight } from "lucide-react"; const CSS = ` @import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Hanken+Grotesk:wght@400;500;600;700&display=swap'); :root{ --bg:#0B0E0C; --bg2:#11140F; --panel:#15191400; --card:#161A16; --card2:#1C211C; --line:rgba(255,255,255,.07); --line2:rgba(255,255,255,.12); --txt:#EDEFEC; --mut:#8B938B; --dim:#5C645C; --green:#14452F; --green2:#1E5C3F; --bright:#3FA77E; --brightT:rgba(63,167,126,.16); } *{box-sizing:border-box;-webkit-tap-highlight-color:transparent} .sift-root{font-family:'Hanken Grotesk',sans-serif;background:var(--bg);min-height:100vh; display:flex;justify-content:center;color:var(--txt)} .serif{font-family:'Fraunces',serif;font-weight:500;letter-spacing:-.01em} .app{position:relative;width:100%;max-width:440px;height:100vh;height:100dvh; background:var(--bg);overflow:hidden} .screen{position:absolute;inset:0;padding:44px 26px 30px;display:flex;flex-direction:column; overflow:hidden;animation:slide .42s cubic-bezier(.22,1,.36,1)} .screen.scroll{overflow-y:auto} .screen::-webkit-scrollbar{display:none} @keyframes slide{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}} @keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}} @keyframes pulse{0%,100%{opacity:.5}50%{opacity:1}} @keyframes spin{to{transform:rotate(360deg)}} @keyframes glow{0%,100%{box-shadow:0 0 40px rgba(63,167,126,.25)}50%{box-shadow:0 0 70px rgba(63,167,126,.45)}} .bg-orb{position:absolute;width:340px;height:340px;border-radius:50%; background:radial-gradient(circle,var(--green2),transparent 68%);filter:blur(40px); opacity:.45;top:-90px;right:-110px;z-index:0;pointer-events:none} .brand-mark{width:64px;height:64px;border-radius:19px;display:flex;align-items:center; justify-content:center;background:linear-gradient(145deg,var(--green2),var(--green)); box-shadow:0 12px 40px rgba(20,69,47,.6);animation:glow 4s ease-in-out infinite} .logo-row{display:flex;align-items:center;gap:11px} .logo-name{font-size:23px;font-weight:600;letter-spacing:-.02em} h1.title{font-size:32px;line-height:1.08;margin:0 0 12px;font-weight:500} .sub{color:var(--mut);font-size:15px;line-height:1.5;margin:0 0 26px} .eyebrow{color:var(--bright);font-size:12.5px;font-weight:600;letter-spacing:.13em; text-transform:uppercase;margin-bottom:14px} .btn{width:100%;border:none;border-radius:16px;padding:17px;font-family:inherit;font-size:16px; font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px; transition:transform .15s,filter .15s} .btn:active{transform:scale(.975)} .btn-primary{background:linear-gradient(135deg,var(--bright),var(--green2));color:#04140C} .btn-primary:hover{filter:brightness(1.08)} .btn-ghost{background:var(--card);color:var(--txt);border:1px solid var(--line2)} .btn-ghost:hover{background:var(--card2)} .field{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:15px 16px; margin-bottom:13px} .field label{display:block;font-size:11.5px;color:var(--dim);font-weight:600;letter-spacing:.05em; text-transform:uppercase;margin-bottom:5px} .field input{width:100%;background:none;border:none;outline:none;color:var(--txt);font-size:16px; font-family:inherit} .field input::placeholder{color:var(--dim)} .field:focus-within{border-color:var(--bright)} .choice{display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--line); border-radius:16px;padding:18px;margin-bottom:12px;cursor:pointer;text-align:left;width:100%; font-family:inherit;color:var(--txt);transition:.18s;animation:rise .5s both} .choice:hover{border-color:var(--line2);background:var(--card2)} .choice.sel{border-color:var(--bright);background:var(--brightT)} .ic-wrap{width:44px;height:44px;border-radius:12px;background:var(--bg2);display:flex; align-items:center;justify-content:center;flex-shrink:0;border:1px solid var(--line)} .choice .ti{font-size:15.5px;font-weight:600} .choice .de{font-size:13px;color:var(--mut);margin-top:2px;line-height:1.35} .step-checklist{display:flex;flex-direction:column;gap:12px;margin:8px 0 24px} .check-item{display:flex;gap:14px;align-items:flex-start;background:var(--card); border:1px solid var(--line);border-radius:15px;padding:15px 16px;animation:rise .5s both} .num{width:27px;height:27px;border-radius:50%;background:var(--green2);color:#04140C;font-weight:700; font-size:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0} .num.done{background:var(--bright)} .check-item .ti{font-size:14.5px;font-weight:600} .check-item .de{font-size:12.5px;color:var(--mut);line-height:1.4;margin-top:3px} .grid2{display:grid;grid-template-columns:1fr 1fr;gap:11px} .src{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:15px; cursor:pointer;transition:.18s;animation:rise .5s both} .src:hover{border-color:var(--line2)} .src.on{border-color:var(--bright);background:var(--brightT)} .src .srow{display:flex;align-items:center;justify-content:space-between} .src .pname{font-size:14px;font-weight:600;margin-top:11px} .dot{width:22px;height:22px;border-radius:50%;border:1.5px solid var(--line2);display:flex; align-items:center;justify-content:center} .dot.on{background:var(--bright);border-color:var(--bright)} .progress{display:flex;gap:6px;margin-bottom:26px} .progress span{height:3px;flex:1;border-radius:2px;background:var(--line)} .progress span.a{background:var(--bright)} .back{position:absolute;top:40px;left:22px;width:38px;height:38px;border-radius:50%; background:var(--card);border:1px solid var(--line);display:flex;align-items:center; justify-content:center;cursor:pointer;z-index:30;color:var(--txt)} .back:hover{background:var(--card2)} .vault-card{background:linear-gradient(150deg,var(--card2),var(--card));border:1px solid var(--line2); border-radius:20px;padding:20px;display:flex;align-items:center;gap:15px;margin-bottom:14px} .vault-card .vc-ic{width:48px;height:48px;border-radius:13px;background:var(--brightT); display:flex;align-items:center;justify-content:center;color:var(--bright)} /* plan */ .plan{border:1px solid var(--line);border-radius:20px;padding:22px;margin-bottom:14px;background:var(--card)} .plan.pro{border-color:var(--bright);background:linear-gradient(160deg,var(--brightT),var(--card)); position:relative;overflow:hidden} .plan.pro::after{content:'';position:absolute;width:160px;height:160px;border-radius:50%; background:radial-gradient(circle,rgba(63,167,126,.35),transparent 70%);top:-60px;right:-50px} .plan .pl-name{font-size:14px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--mut)} .plan.pro .pl-name{color:var(--bright)} .plan .price{font-size:34px;font-weight:600;margin:6px 0 2px} .plan .price small{font-size:15px;color:var(--mut);font-weight:500} .feat{display:flex;align-items:center;gap:10px;font-size:13.5px;margin-top:11px;color:var(--txt)} .feat svg{color:var(--bright);flex-shrink:0} /* dashboard */ .dash-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px} .proBadge{font-size:10.5px;font-weight:700;letter-spacing:.08em;color:#04140C; background:linear-gradient(135deg,var(--bright),var(--green2));padding:4px 9px;border-radius:7px} .statbar{display:flex;gap:10px;margin:16px 0 18px} .stat{flex:1;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:13px 14px} .stat .n{font-size:21px;font-weight:600;font-family:'Fraunces',serif} .stat .l{font-size:11px;color:var(--mut);margin-top:2px} .post{display:flex;gap:13px;align-items:center;background:var(--card);border:1px solid var(--line); border-radius:15px;padding:13px;margin-bottom:10px;animation:rise .5s both} .post .p-ic{width:40px;height:40px;border-radius:11px;display:flex;align-items:center; justify-content:center;flex-shrink:0} .post .p-t{font-size:14px;font-weight:600;line-height:1.25} .post .p-meta{display:flex;gap:7px;align-items:center;margin-top:5px} .tag{font-size:10.5px;font-weight:600;padding:3px 8px;border-radius:6px;display:inline-flex; align-items:center;gap:4px} .tag.code{background:rgba(99,160,255,.14);color:#7FB2FF} .tag.food{background:rgba(255,170,90,.14);color:#FFB36B} .tag.insp{background:rgba(63,167,126,.16);color:var(--bright)} .status{font-size:11px;color:var(--mut);display:flex;align-items:center;gap:5px;margin-left:auto; white-space:nowrap} .status.sync{color:var(--bright)} .spin{animation:spin 1s linear infinite} .tip{background:var(--bg2);border:1px solid var(--line);border-radius:14px;padding:14px 15px; font-size:12.5px;color:var(--mut);line-height:1.5;display:flex;gap:10px;margin-bottom:14px} .tip svg{color:var(--bright);flex-shrink:0;margin-top:1px} .spacer{flex:1;min-height:14px} .center{text-align:center;align-items:center;justify-content:center} /* smart-sort sheet */ .smart-btn{display:flex;align-items:center;gap:11px;width:100%;text-align:left;font-family:inherit; background:linear-gradient(135deg,var(--brightT),var(--card));border:1px solid rgba(63,167,126,.3); border-radius:15px;padding:13px 14px;color:var(--txt);cursor:pointer;margin:8px 0 16px} .smart-btn:hover{border-color:var(--bright)} .smart-btn .sb-ic{width:36px;height:36px;border-radius:10px;background:var(--bright);color:#04140C; display:flex;align-items:center;justify-content:center;flex-shrink:0} .smart-btn .ti{font-size:13.5px;font-weight:600} .smart-btn .de{font-size:11.5px;color:var(--mut)} .scrim{position:absolute;inset:0;z-index:60;background:rgba(4,7,5,.6);backdrop-filter:blur(3px); animation:fade .25s both} @keyframes fade{from{opacity:0}to{opacity:1}} .sheet{position:absolute;left:0;right:0;bottom:0;z-index:61;background:var(--bg2); border-top:1px solid var(--line2);border-radius:26px 26px 46px 46px;padding:14px 22px 30px; box-shadow:0 -20px 60px rgba(0,0,0,.6);animation:sheetUp .42s cubic-bezier(.22,1,.36,1) both; max-height:86%;overflow-y:auto} .sheet::-webkit-scrollbar{display:none} @keyframes sheetUp{from{transform:translateY(100%)}to{transform:none}} .handle{width:38px;height:4px;border-radius:3px;background:var(--line2);margin:2px auto 16px} .sheet-ey{color:var(--bright);font-size:11.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase; display:flex;align-items:center;gap:7px;margin-bottom:10px} .sheet h2{font-size:21px;font-weight:600;letter-spacing:-.01em;margin-bottom:6px;font-family:'Fraunces',serif} .sheet .lead{font-size:13.5px;color:var(--mut);line-height:1.5;margin-bottom:16px} .detect{display:flex;gap:12px;align-items:center;background:var(--card);border:1px solid var(--line); border-radius:14px;padding:13px;margin-bottom:14px} .detect .d-ic{width:38px;height:38px;border-radius:10px;background:var(--bg);border:1px solid var(--line); display:flex;align-items:center;justify-content:center;flex-shrink:0} .newpill{font-size:9.5px;font-weight:700;letter-spacing:.06em;color:#04140C;background:var(--bright); padding:3px 7px;border-radius:6px;margin-left:auto;flex-shrink:0} .catrow{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line); border-radius:13px;padding:13px 14px;margin-bottom:9px;cursor:pointer;width:100%;font-family:inherit; color:var(--txt);text-align:left;transition:.16s;animation:rise .4s both} .catrow:hover{border-color:var(--line2);background:var(--card2)} .catrow.sel{border-color:var(--bright);background:var(--brightT)} .catrow .c-ic{color:var(--bright)} .catrow .ti{font-size:14px;font-weight:600} .catrow .de{font-size:11.5px;color:var(--mut);margin-top:1px} .tree{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;line-height:1.9;color:var(--mut); background:var(--card);border:1px solid var(--line);border-radius:13px;padding:14px 16px;margin-bottom:16px} .tree .root{color:var(--txt)} .tree .new{color:var(--bright);font-weight:600} .chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px} .chip{font-family:inherit;font-size:12.5px;font-weight:500;padding:8px 13px;border-radius:100px; border:1px solid var(--line2);background:var(--card);color:var(--txt);cursor:pointer;display:flex;align-items:center;gap:6px} .chip:hover,.chip.sel{border-color:var(--bright);background:var(--brightT);color:var(--bright)} .perm-note{font-size:11.5px;color:var(--dim);display:flex;gap:8px;align-items:flex-start;margin-top:6px;line-height:1.45} .perm-note svg{flex-shrink:0;margin-top:1px;color:var(--bright)} .sheet-actions{display:flex;gap:10px;margin-top:6px} .sheet-actions .btn{flex:1;padding:15px} .done-ic{width:64px;height:64px;border-radius:20px;margin:6px auto 16px;display:flex;align-items:center; justify-content:center;background:linear-gradient(145deg,var(--bright),var(--green2)); animation:glow 3s ease-in-out infinite} `; // minimal brand glyphs not in lucide const TikTok = ({ s = 20, c = "#fff" }) => ( ); const Snap = ({ s = 20, c = "#fff" }) => ( ); const PLATFORMS = [ { id: "ig", name: "Instagram", color: "#E1306C", Icon: (p) => }, { id: "tt", name: "TikTok", color: "#fff", Icon: (p) => }, { id: "yt", name: "YouTube", color: "#FF0033", Icon: (p) => }, { id: "x", name: "X", color: "#fff", Icon: (p) => }, { id: "fb", name: "Facebook", color: "#1877F2", Icon: (p) => }, { id: "sc", name: "Snapchat", color: "#FFFC00", Icon: (p) => }, ]; export default function SiftApp() { const [step, setStep] = useState(0); const [usesObsidian, setUsesObsidian] = useState(null); const [acct, setAcct] = useState({ name: "", email: "" }); const [vaultMethod, setVaultMethod] = useState(null); const [vaultConnected, setVaultConnected] = useState(false); const [sources, setSources] = useState({ ig: true, tt: true, yt: false, x: false, fb: false, sc: false }); const [plan, setPlan] = useState(null); const [sheet, setSheet] = useState(null); // null | detect | created | choose | sub | done const [chosenCat, setChosenCat] = useState(null); const [subPick, setSubPick] = useState(null); const openSheet = () => { setSheet("detect"); setChosenCat(null); setSubPick(null); }; const closeSheet = () => setSheet(null); const go = (n) => setStep(n); const toggleSrc = (id) => setSources((s) => ({ ...s, [id]: !s[id] })); const Bar = ({ n, total = 6 }) => (
{Array.from({ length: total }).map((_, i) => )}
); const Back = ({ to }) => (
go(to)}>
); const screens = { // 0 — welcome 0: (
Sift

Save anything you watch. We turn it into clean Markdown, straight into your Obsidian vault.

), // 1 — account wizard p1 1: (
Create account · 1 of 2

Let's set up
your profile

Your vault stays yours — Sift only writes the notes you send it.

setAcct({ ...acct, name: e.target.value })} />
setAcct({ ...acct, email: e.target.value })} />
), // 2 — account wizard p2 2: (
Create account · 2 of 2

Secure it

Use a passkey for sign-in — no password to remember.

), // 3 — obsidian question (the branch) 3: (
Onboarding

Do you already
use Obsidian?

This tailors the next steps. No wrong answer.

), // 4 — adapted steps 4: usesObsidian ? (
Connect vault

Three quick taps

Sift writes notes into a folder your vault already syncs.

{[ ["Pick your storage", "iCloud Drive, On-device, or Obsidian Sync.", true], ["Point Sift at the vault folder", "Choose the folder Obsidian opens as your vault.", false], ["Confirm a Sift subfolder", "We create /Sift Inbox so nothing else is touched.", false], ].map(([t, d, done], i) => (
{done ? : i + 1}
{t}
{d}
))}
) : (
Set up Obsidian first

No problem —
here's the plan

Obsidian is a free notes app. Five minutes and you're set.

{[ ["Download Obsidian", "Free on the App Store. Tap to open the listing."], ["Create a vault", "Name it anything — e.g. \"Brain\". Store it in iCloud Drive."], ["Come back to Sift", "We'll detect the vault and link it automatically."], ].map(([t, d], i) => (
{i + 1}
{t}
{d}
))}
), // 5 — vault connect 5: (
Connect vault

Where's your vault?

Pick how your vault is stored so Sift can sync to it.

{[ ["icloud", Cloud, "iCloud Drive", "Recommended — syncs across all your devices."], ["local", Smartphone, "On my iPhone", "Stored locally in the Files app."], ["sync", RefreshCw, "Obsidian Sync", "Use your existing Obsidian Sync remote."], ].map(([id, Ic, t, d], i) => ( ))} {vaultConnected && (
Brain / Sift Inbox
Connected & writable
)}
), // 6 — sources 6: (
Sources

What do you
save from?

Toggle the apps you use. You can change this anytime.

{PLATFORMS.map((p, i) => ( ))}
To save a post, just tap Share → Sift inside any of these apps. The note appears in your vault seconds later.
), // 7 — pro plan 7: (
Plans

Save without limits

Start free. Go Pro when your brain gets hungry.

setPlan("free")} style={{ borderColor: plan === "free" ? "var(--line2)" : "var(--line)" }}>
Free
€0
20 Markdown conversions / month
1 vault, all 6 platforms
setPlan("pro")} style={{ outline: plan === "pro" ? "1px solid var(--bright)" : "none" }}>
Sift Pro
€6,99 / month
Unlimited conversions
Auto-tagging & smart categories
Full transcripts + on-screen text (OCR)
Multiple vaults & custom templates
), // 8 — dashboard 8: (
Sift
{plan === "pro" ? PRO : Free · 14 left}
Synced to Brain / Sift Inbox
128
Notes saved
6
Sources
{plan === "pro" ? "∞" : "14"}
Left
Recent
{[ { p: "ig", t: "Next.js server actions pattern", tag: "code", st: "Saved", icon: }, { p: "tt", t: "30-min high-protein ramen", tag: "food", st: "sync", icon: }, { p: "yt", t: "Local LLM agents with Ollama", tag: "code", st: "Saved", icon: }, { p: "x", t: "Thread: founder positioning", tag: "insp", st: "Saved", icon: }, ].map((it, i) => (
{it.icon}
{it.t}
{it.tag === "code" && } {it.tag === "food" && } {it.tag === "insp" && } {it.tag === "code" ? "Coding" : it.tag === "food" ? "Recipe" : "Inspiration"}
{it.st === "sync" ?
Converting
:
.md
}
))}
), }; const CATS = [ { id: "coding", name: "Coding", icon: , subs: ["Next.js", "Prisma", "AI Agents"], suggest: ["React", "DevOps"] }, { id: "recipes", name: "Recipes", icon: , subs: ["Quick", "High-protein"], suggest: ["Asian", "Baking"] }, { id: "inspiration", name: "Inspiration", icon: , subs: ["Founder", "Design"], suggest: ["Marketing", "Quotes"] }, { id: "trading", name: "Trading", icon: , subs: ["Strategies"], suggest: ["Backtesting", "Risk"] }, ]; const cat = CATS.find((c) => c.id === chosenCat); const PermNote = () => (
Sift never changes your vault structure without asking. You're the admin.
); const Sheet = () => { if (!sheet) return null; return ( <>
{sheet === "detect" && (<>
Smart Sort

New category detected

Sift analysed your latest save and it doesn't fit any existing folder.

Optuna Bayesian tuning
suggested: Algorithmic Trading
NEW

Create a folder “Algorithmic Trading” in your vault?

)} {sheet === "created" && (<>
Folder created

“Algorithmic Trading”

Added to your vault. Want a matching subfolder for finer sorting?

📂 Brain
  └ 📂 Sift Inbox
    └ 📂 Algorithmic Trading ✦
{subPick &&
      └ 📂 {subPick} ✦
}
Suggested subfolder
{["Backtesting", "Optuna", "Strategies"].map((s) => ( ))}
)} {sheet === "choose" && (<>
Choose existing

Pick a category

Sift will file this save into a folder you already have.

{CATS.map((c, i) => ( ))} )} {sheet === "sub" && cat && (<>
{cat.icon} {cat.name}

Save into {cat.name}

Drop it here, or create a new subcategory (a subfolder in Obsidian).

📂 {cat.name}
{cat.subs.map((s) =>
  └ 📂 {s}
)} {subPick &&
  └ 📂 {subPick} ✦
}
New subcategory
{cat.suggest.map((s) => ( ))}
)} {sheet === "done" && (<>

Filed away

Your note is saved and the folders exist as real subfolders in Obsidian.

{chosenCat ? (<>
📂 {cat.name}
  └ 📂 {subPick || cat.subs[0]}{subPick ? " ✦" : ""}
    └ 📄 optuna-tuning.md
) : (<>
📂 Algorithmic Trading
{subPick &&
  └ 📂 {subPick} ✦
}
{subPick ? "\u00A0\u00A0\u00A0\u00A0" : "\u00A0\u00A0"}└ 📄 optuna-tuning.md
)}
)}
); }; return (
{screens[step]} {step === 8 && }
); }