feat: SEO audit export, default Vibe Architect, /vibe route (v2.0.0)

This commit is contained in:
admin
2026-03-18 21:34:13 +00:00
Unverified
parent 0e22495ff7
commit fcb3c04bbc
5 changed files with 300 additions and 4 deletions

View File

@@ -1,10 +1,11 @@
"use client";
import React, { useState, useEffect, useRef, memo } from "react";
import { downloadSeoReport } from "@/lib/seo-report";
import {
MessageSquare, Send, Code2, Palette, Search,
Trash2, Copy, Monitor, StopCircle, X, Zap, Ghost,
Wand2, LayoutPanelLeft, Play, Orbit, Plus, Key, ShieldCheck, Wrench
Wand2, LayoutPanelLeft, Play, Orbit, Plus, Key, ShieldCheck, Wrench, FileText
} from "lucide-react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
@@ -520,6 +521,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
const [deviceSize, setDeviceSize] = useState<"full" | "desktop" | "tablet" | "mobile">("full");
const deviceWidths: Record<string, string> = { full: "100%", desktop: "1280px", tablet: "768px", mobile: "375px" };
const [isModifying, setIsModifying] = useState(false);
const [seoAuditData, setSeoAuditData] = useState<any>(null);
const [abortController, setAbortController] = useState<AbortController | null>(null);
// Agent suggestion state
@@ -711,6 +713,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
const auditRes = await fetch("/api/fetch-url?url=" + encodeURIComponent(url));
if (auditRes.ok) {
const d = await auditRes.json();
setSeoAuditData(d);
enrichedInput += "\n\n[COMPREHENSIVE SEO AUDIT - " + url + "]\n";
enrichedInput += "== OVERALL SCORE: " + (d.scores?.overall || "?") + "/100 ==\n";
enrichedInput += "Technical: " + (d.scores?.technical || "?") + " | Content: " + (d.scores?.content || "?") + " | Performance: " + (d.scores?.performance || "?") + " | Social: " + (d.scores?.social || "?") + "\n\n";
@@ -911,6 +914,11 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
setIsProcessing(false);
}
};
const exportSeoReport = (format: "html" | "pdf") => {
if (!seoAuditData) return;
downloadSeoReport(seoAuditData, format);
};
const clearHistory = () => {
updateActiveTab({
@@ -1338,6 +1346,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
{/* Post-coding action buttons */}
{msg.role === "assistant" && assistStep === "preview" && i === aiAssistHistory.length - 1 && !isProcessing && (
<>
<div className="mt-4 grid grid-cols-3 gap-2 animate-in zoom-in-95 duration-300">
<Button
onClick={() => { setShowCanvas(true); setViewMode(isPreviewRenderable(previewData as PreviewData) ? "preview" : "code"); }}
@@ -1361,6 +1370,25 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
<LayoutPanelLeft className="h-3.5 w-3.5 mr-1" /> <span className="truncate">Modify</span>
</Button>
</div>
{currentAgent === "seo" && seoAuditData && (
<div className="mt-2 flex gap-2 animate-in zoom-in-95 duration-300">
<Button
onClick={() => exportSeoReport("html")}
variant="outline"
className="flex-1 bg-emerald-500/10 hover:bg-emerald-500/20 border-emerald-500/20 text-emerald-300 font-black uppercase text-[9px] tracking-wider py-3 rounded-xl min-w-0"
>
<Download className="h-3.5 w-3.5 mr-1" /> <span className="truncate">Export HTML</span>
</Button>
<Button
onClick={() => exportSeoReport("pdf")}
variant="outline"
className="flex-1 bg-amber-500/10 hover:bg-amber-500/20 border-amber-500/20 text-amber-300 font-black uppercase text-[9px] tracking-wider py-3 rounded-xl min-w-0"
>
<FileText className="h-3.5 w-3.5 mr-1" /> <span className="truncate">Export PDF</span>
</Button>
</div>
)}
</>
)}
</div>