"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { JM } from "./modal-theme"; import { DEFAULT_DESIGN_KIT_ID } from "@/lib/design-kits/types"; import { SetupHeader, FieldLabel, TextInput, TextArea, AudienceSelector, DesignKitSelector, PrimaryButton, SecondaryButton, SegmentedTabs, StepDots, type SetupProps, type Audience, } from "./setup-shared"; /** * "Run an open source tool" — three-step setup. * Step 0: project name + audience. * Step 1: design system starter kit. * Step 2: either paste a link to the OSS repo (e.g. github.com/twentyhq/twenty) * OR describe the tool you want and let Vibn find one. * Both produce a free-text "what do you want to do with it?" seed * that we hand to the AI on first chat. */ export function OssSetup({ workspace, onClose, onBack }: SetupProps) { const router = useRouter(); const [step, setStep] = useState(0); const [name, setName] = useState(""); const [audience, setAudience] = useState("team"); const [designKitId, setDesignKitId] = useState(DEFAULT_DESIGN_KIT_ID); const [tab, setTab] = useState<"link" | "describe">("link"); const [repoUrl, setRepoUrl] = useState(""); const [needs, setNeeds] = useState(""); const [loading, setLoading] = useState(false); const totalSteps = 3; const canContinue0 = name.trim().length > 0; const isValidUrl = /^https?:\/\//i.test(repoUrl.trim()); const canCreate = (tab === "link" && isValidUrl) || (tab === "describe" && needs.trim().length > 4); const handleBack = () => { if (step === 0) onBack(); else setStep(step - 1); }; const handleCreate = async () => { if (!canCreate) return; setLoading(true); try { const seed = tab === "link" ? `Install and host this open-source project: ${repoUrl.trim()}` : `Find and install an open-source tool that fits this need: ${needs.trim()}`; const res = await fetch("/api/projects/create", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ projectName: name.trim(), projectType: "service", slug: name.toLowerCase().replace(/[^a-z0-9]+/g, "-"), vision: seed, product: { name: name.trim() }, audience, designKitId, creationMode: "oss", sourceData: { audience, designKitId, ...(tab === "link" ? { kind: "link", repoUrl: repoUrl.trim() } : { kind: "describe", description: needs.trim() }), }, }), }); if (!res.ok) { const err = await res.json(); toast.error(err.error || "Failed to create project"); return; } const data = await res.json(); onClose(); router.push(`/${workspace}/project/${data.projectId}/product`); } catch { toast.error("Something went wrong"); } finally { setLoading(false); } }; return (
{step === 0 && ( <> Project name { if (e.key === "Enter" && canContinue0) setStep(1); }} autoFocus /> setStep(1)} disabled={!canContinue0}> Next → } /> )} {step === 1 && ( <> setStep(0)}>← Back} primary={ setStep(2)}>Next →} /> )} {step === 2 && ( <> value={tab} onChange={setTab} options={[ { id: "link", label: "I have a link" }, { id: "describe", label: "Help me find one" }, ]} /> {tab === "link" ? ( <> Link to the open source project

Paste a GitHub link. Vibn will check it works and host it for you.

) : ( <> What kind of tool are you looking for?