[dyad] Added system detection tab - wrote 4 file(s)
This commit is contained in:
@@ -28,6 +28,10 @@ export interface LinkData {
|
|||||||
rel: string;
|
rel: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DetectedSystem {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export async function extractMetaData(url: string, keyword?: string) {
|
export async function extractMetaData(url: string, keyword?: string) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return { error: "URL is required." };
|
return { error: "URL is required." };
|
||||||
@@ -225,6 +229,60 @@ export async function extractMetaData(url: string, keyword?: string) {
|
|||||||
links.push({ href: absoluteUrl, text, type, rel });
|
links.push({ href: absoluteUrl, text, type, rel });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const detectedSystems: DetectedSystem[] = [];
|
||||||
|
const htmlContent = $.html();
|
||||||
|
const uniqueSystems = new Set<string>();
|
||||||
|
|
||||||
|
// WordPress
|
||||||
|
if (
|
||||||
|
$('meta[name="generator"][content*="WordPress"]').length > 0 ||
|
||||||
|
htmlContent.includes("/wp-content/") ||
|
||||||
|
htmlContent.includes("/wp-includes/")
|
||||||
|
) {
|
||||||
|
uniqueSystems.add("WordPress");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shopify
|
||||||
|
if (
|
||||||
|
htmlContent.includes("cdn.shopify.com") ||
|
||||||
|
htmlContent.includes("Shopify.theme")
|
||||||
|
) {
|
||||||
|
uniqueSystems.add("Shopify");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next.js
|
||||||
|
if ($("#__next").length > 0) {
|
||||||
|
uniqueSystems.add("Next.js");
|
||||||
|
uniqueSystems.add("React"); // Next.js uses React
|
||||||
|
}
|
||||||
|
|
||||||
|
// React (generic)
|
||||||
|
if ($("#root").length > 0) {
|
||||||
|
uniqueSystems.add("React");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webflow
|
||||||
|
if (
|
||||||
|
$('meta[name="generator"][content="Webflow"]').length > 0 ||
|
||||||
|
htmlContent.includes("<!-- This site was created in Webflow.")
|
||||||
|
) {
|
||||||
|
uniqueSystems.add("Webflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wix
|
||||||
|
if ($('meta[name="generator"][content*="Wix.com"]').length > 0) {
|
||||||
|
uniqueSystems.add("Wix");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Squarespace
|
||||||
|
if (htmlContent.includes("static1.squarespace.com")) {
|
||||||
|
uniqueSystems.add("Squarespace");
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueSystems.forEach((system) => {
|
||||||
|
detectedSystems.push({ name: system });
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
@@ -241,6 +299,7 @@ export async function extractMetaData(url: string, keyword?: string) {
|
|||||||
keywordCount,
|
keywordCount,
|
||||||
images: imageAltData.length > 0 ? imageAltData : null,
|
images: imageAltData.length > 0 ? imageAltData : null,
|
||||||
links: links.length > 0 ? links : null,
|
links: links.length > 0 ? links : null,
|
||||||
|
systems: detectedSystems.length > 0 ? detectedSystems : null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { MetaFormInputs } from "./meta-form-inputs";
|
|||||||
import { AnalysisTab } from "./analysis-tab";
|
import { AnalysisTab } from "./analysis-tab";
|
||||||
import { SocialTab } from "./social-tab";
|
import { SocialTab } from "./social-tab";
|
||||||
import { LinksDisplay } from "./links-display";
|
import { LinksDisplay } from "./links-display";
|
||||||
|
import { SystemDisplay } from "./system-display";
|
||||||
import type { MetaData } from "@/lib/types";
|
import type { MetaData } from "@/lib/types";
|
||||||
|
|
||||||
export function MetaForm() {
|
export function MetaForm() {
|
||||||
@@ -125,6 +126,10 @@ export function MetaForm() {
|
|||||||
schemaColor = "green";
|
schemaColor = "green";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System Tab
|
||||||
|
const systemColor: IndicatorColor =
|
||||||
|
metaData.systems && metaData.systems.length > 0 ? "green" : "gray";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
analysis: analysisColor,
|
analysis: analysisColor,
|
||||||
headlines: headlinesColor,
|
headlines: headlinesColor,
|
||||||
@@ -133,6 +138,7 @@ export function MetaForm() {
|
|||||||
links: linksColor,
|
links: linksColor,
|
||||||
faq: faqColor,
|
faq: faqColor,
|
||||||
schema: schemaColor,
|
schema: schemaColor,
|
||||||
|
system: systemColor,
|
||||||
};
|
};
|
||||||
}, [metaData, editableTitle, editableDescription]);
|
}, [metaData, editableTitle, editableDescription]);
|
||||||
|
|
||||||
@@ -218,18 +224,24 @@ export function MetaForm() {
|
|||||||
Social
|
Social
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
{metaData.faq && metaData.faq.length > 0 && (
|
|
||||||
<TabsTrigger value="faq">
|
|
||||||
{tabColors && <TabIndicator color={tabColors.faq} />}
|
|
||||||
FAQ
|
|
||||||
</TabsTrigger>
|
|
||||||
)}
|
|
||||||
{metaData.schema && metaData.schema.length > 0 && (
|
{metaData.schema && metaData.schema.length > 0 && (
|
||||||
<TabsTrigger value="schema">
|
<TabsTrigger value="schema">
|
||||||
{tabColors && <TabIndicator color={tabColors.schema} />}
|
{tabColors && <TabIndicator color={tabColors.schema} />}
|
||||||
Schema
|
Schema
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
|
{metaData.systems && metaData.systems.length > 0 && (
|
||||||
|
<TabsTrigger value="system">
|
||||||
|
{tabColors && <TabIndicator color={tabColors.system} />}
|
||||||
|
System
|
||||||
|
</TabsTrigger>
|
||||||
|
)}
|
||||||
|
{metaData.faq && metaData.faq.length > 0 && (
|
||||||
|
<TabsTrigger value="faq">
|
||||||
|
{tabColors && <TabIndicator color={tabColors.faq} />}
|
||||||
|
FAQ
|
||||||
|
</TabsTrigger>
|
||||||
|
)}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="analysis">
|
<TabsContent value="analysis">
|
||||||
@@ -313,6 +325,12 @@ export function MetaForm() {
|
|||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{metaData.systems && metaData.systems.length > 0 && (
|
||||||
|
<TabsContent value="system">
|
||||||
|
<SystemDisplay systems={metaData.systems} />
|
||||||
|
</TabsContent>
|
||||||
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
98
src/components/system-display.tsx
Normal file
98
src/components/system-display.tsx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import type { DetectedSystem } from "@/app/actions";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import {
|
||||||
|
Code,
|
||||||
|
Server,
|
||||||
|
ShoppingCart,
|
||||||
|
Square,
|
||||||
|
PenTool,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
|
interface SystemDisplayProps {
|
||||||
|
systems: DetectedSystem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemInfo: {
|
||||||
|
[key: string]: { icon: React.ElementType; description: string };
|
||||||
|
} = {
|
||||||
|
WordPress: {
|
||||||
|
icon: Code,
|
||||||
|
description: "A popular open-source content management system.",
|
||||||
|
},
|
||||||
|
Shopify: {
|
||||||
|
icon: ShoppingCart,
|
||||||
|
description: "An e-commerce platform for online stores.",
|
||||||
|
},
|
||||||
|
"Next.js": {
|
||||||
|
icon: Server,
|
||||||
|
description: "A React framework for building full-stack web applications.",
|
||||||
|
},
|
||||||
|
React: {
|
||||||
|
icon: Code,
|
||||||
|
description: "A JavaScript library for building user interfaces.",
|
||||||
|
},
|
||||||
|
Webflow: {
|
||||||
|
icon: PenTool,
|
||||||
|
description: "A visual web development platform.",
|
||||||
|
},
|
||||||
|
Wix: { icon: Square, description: "A cloud-based web development platform." },
|
||||||
|
Squarespace: {
|
||||||
|
icon: Square,
|
||||||
|
description: "A website builder and hosting service.",
|
||||||
|
},
|
||||||
|
Default: {
|
||||||
|
icon: Code,
|
||||||
|
description: "A detected web technology or framework.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SystemDisplay({ systems }: SystemDisplayProps) {
|
||||||
|
return (
|
||||||
|
<Card className="w-full shadow-lg rounded-lg">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>System Analysis</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Technologies and frameworks detected on the page.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{systems && systems.length > 0 ? (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{systems.map((system, index) => {
|
||||||
|
const info = systemInfo[system.name] || systemInfo["Default"];
|
||||||
|
const Icon = info.icon;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex items-start gap-4 p-4 border rounded-lg bg-muted/50"
|
||||||
|
>
|
||||||
|
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-primary text-primary-foreground">
|
||||||
|
<Icon className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="font-semibold text-lg">{system.name}</h4>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{info.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-8 text-muted-foreground">
|
||||||
|
<p>No specific frameworks or CMS detected.</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
import type { HeadlineNode, ImageAltData, LinkData } from "@/app/actions";
|
import type {
|
||||||
|
HeadlineNode,
|
||||||
|
ImageAltData,
|
||||||
|
LinkData,
|
||||||
|
DetectedSystem,
|
||||||
|
} from "@/app/actions";
|
||||||
|
|
||||||
export interface OpenGraphData {
|
export interface OpenGraphData {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -33,4 +38,5 @@ export interface MetaData {
|
|||||||
openGraph?: OpenGraphData;
|
openGraph?: OpenGraphData;
|
||||||
twitter?: TwitterData;
|
twitter?: TwitterData;
|
||||||
links?: LinkData[] | null;
|
links?: LinkData[] | null;
|
||||||
|
systems?: DetectedSystem[] | null;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user