diff --git a/vibn-frontend/app/api/design-systems/[id]/preview/route.ts b/vibn-frontend/app/api/design-systems/[id]/preview/route.ts index 9f07fd2..05874f6 100644 --- a/vibn-frontend/app/api/design-systems/[id]/preview/route.ts +++ b/vibn-frontend/app/api/design-systems/[id]/preview/route.ts @@ -12,19 +12,57 @@ export async function GET( return new NextResponse("Invalid design system ID", { status: 400 }); } - const htmlPath = path.join( + const systemPath = path.join( process.cwd(), "lib", "scaffold", "open-design", "design-systems", - id, - "components.html" + id ); + const htmlPath = path.join(systemPath, "components.html"); + try { + if (!fs.existsSync(systemPath)) { + return new NextResponse(`Design system not found for ${id}`, { status: 404 }); + } + if (!fs.existsSync(htmlPath)) { - return new NextResponse(`Preview not found for ${id}`, { status: 404 }); + // If there's no components.html, serve a beautiful fallback UI + // that explains this system only has Markdown guidelines for the AI + const fallbackHtml = ` + + + + + + ${id} — No preview available + + + +
+

Preview Not Available

+

The ${id} design system is a "Rules-Only" system.

+

It provides strict typographic, spacing, and layout instructions to the AI via its DESIGN.md, but it doesn't currently ship with a visual HTML preview gallery.

+
AI Guidelines Active
+
+ + + `; + return new NextResponse(fallbackHtml, { + status: 200, + headers: { + "Content-Type": "text/html; charset=utf-8", + "X-Frame-Options": "SAMEORIGIN", + }, + }); } const html = await fs.promises.readFile(htmlPath, "utf-8"); @@ -33,7 +71,6 @@ export async function GET( status: 200, headers: { "Content-Type": "text/html; charset=utf-8", - // Allow framing only from same origin for security "X-Frame-Options": "SAMEORIGIN", }, }); diff --git a/vibn-frontend/components/project/design-system-explorer.tsx b/vibn-frontend/components/project/design-system-explorer.tsx index 3e2032a..ddfb159 100644 --- a/vibn-frontend/components/project/design-system-explorer.tsx +++ b/vibn-frontend/components/project/design-system-explorer.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { useParams } from "next/navigation"; -import { Loader2, Check, Search, Eye, Sparkles } from "lucide-react"; +import { Loader2, Check, Search, Eye, Sparkles, LayoutTemplate } from "lucide-react"; import { toast } from "sonner"; import { STARTER_KITS } from "@/lib/design-kits/registry"; import { DEFAULT_DESIGN_KIT_ID } from "@/lib/design-kits/types"; @@ -88,7 +88,7 @@ export function DesignSystemExplorer() {
{/* LEFT SIDEBAR: Library & Search */} -
+

@@ -114,7 +114,7 @@ export function DesignSystemExplorer() {

-
+
{kit.name}
@@ -135,6 +135,12 @@ export function DesignSystemExplorer() { {kit.tagline || kit.id}
+ {/* Visual Indicator if it has an HTML preview */} + {kit.hasPreview && ( +
+ +
+ )} ); })} @@ -152,8 +158,11 @@ export function DesignSystemExplorer() {
- + Previewing: {previewKit.name} + {!previewKit.hasPreview && ( + Rules Only + )}
@@ -162,8 +171,8 @@ export function DesignSystemExplorer() { disabled={saving || isActive} className={`px-4 py-1.5 rounded-md text-sm font-medium transition-all flex items-center gap-2 ${ isActive - ? 'bg-zinc-100 text-zinc-400 cursor-default' - : 'bg-indigo-600 hover:bg-indigo-700 text-white shadow-sm' + ? 'bg-zinc-100 text-zinc-400 cursor-default shadow-inner' + : 'bg-indigo-600 hover:bg-indigo-700 text-white shadow-sm hover:shadow-md' }`} > {saving && } @@ -172,22 +181,22 @@ export function DesignSystemExplorer() {
{/* Live Iframe */} -
+
-
+
{previewKit.id}.design.preview