mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
chore: remove dead landing components and a stale vitest exclude
Remove 3 unreferenced landing components (HowItWorks, ModalityExplorer, TerminalBlock) and a stale vitest exclude.
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
---
|
||||
import SectionHeading from "./SectionHeading.astro";
|
||||
|
||||
const steps = [
|
||||
{
|
||||
number: "01",
|
||||
title: "Deploy",
|
||||
description:
|
||||
"Run a single Docker command. Everything bundled: database, queue, AI models, media tools.",
|
||||
},
|
||||
{
|
||||
number: "02",
|
||||
title: "Open",
|
||||
description: "Navigate to localhost:1349. No accounts needed. No configuration required.",
|
||||
},
|
||||
{
|
||||
number: "03",
|
||||
title: "Process",
|
||||
description:
|
||||
"Upload files, pick a tool, download results. Or automate everything via the REST API.",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section class="px-6 py-20 md:py-28">
|
||||
<SectionHeading
|
||||
title="Operational in minutes, not months."
|
||||
subtitle="No lengthy procurement. No vendor onboarding. Deploy and start processing."
|
||||
/>
|
||||
|
||||
<div class="mx-auto grid max-w-5xl gap-12 md:grid-cols-3 md:gap-8">
|
||||
{steps.map((step, i) => (
|
||||
<div
|
||||
class:list={[
|
||||
"reveal",
|
||||
`reveal-delay-${i + 1}`,
|
||||
i < steps.length - 1 && "step-connector",
|
||||
]}
|
||||
>
|
||||
<span class="font-display text-5xl md:text-6xl font-extrabold text-primary/20">
|
||||
{step.number}
|
||||
</span>
|
||||
<h3 class="font-display text-xl font-bold mt-2">{step.title}</h3>
|
||||
<p class="text-sm text-muted mt-2 leading-relaxed">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
import { TOOLS } from "@snapotter/shared";
|
||||
import SectionHeading from "./SectionHeading.astro";
|
||||
|
||||
interface ModalityCard {
|
||||
id: string;
|
||||
name: string;
|
||||
count: number;
|
||||
icon: string;
|
||||
color: string;
|
||||
topTools: string[];
|
||||
}
|
||||
|
||||
const modalityMeta: Record<string, { name: string; icon: string; color: string }> = {
|
||||
image: { name: "Image", icon: "image", color: "#E07832" },
|
||||
video: { name: "Video", icon: "video", color: "#3B82F6" },
|
||||
audio: { name: "Audio", icon: "headphones", color: "#8B5CF6" },
|
||||
document: { name: "Documents", icon: "file-text", color: "#EF4444" },
|
||||
file: { name: "Data", icon: "database", color: "#F59E0B" },
|
||||
};
|
||||
|
||||
const modalities: ModalityCard[] = Object.entries(modalityMeta).map(([id, meta]) => {
|
||||
const tools = TOOLS.filter((t) => t.modality === id);
|
||||
return {
|
||||
id,
|
||||
name: meta.name,
|
||||
count: tools.length,
|
||||
icon: meta.icon,
|
||||
color: meta.color,
|
||||
topTools: tools.slice(0, 4).map((t) => t.name),
|
||||
};
|
||||
});
|
||||
|
||||
const svgIcons: Record<string, string> = {
|
||||
image:
|
||||
'<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/>',
|
||||
video:
|
||||
'<polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>',
|
||||
headphones:
|
||||
'<path d="M3 18v-6a9 9 0 0 1 18 0v6"/><path d="M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z"/>',
|
||||
"file-text":
|
||||
'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/>',
|
||||
database:
|
||||
'<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>',
|
||||
};
|
||||
---
|
||||
|
||||
<section class="bg-background-alt px-6 py-20 md:py-28" id="features">
|
||||
<SectionHeading
|
||||
title="Every file format. One platform."
|
||||
subtitle="Process images, video, audio, documents, and data files with 157 self-hosted tools."
|
||||
/>
|
||||
|
||||
<div class="mx-auto grid max-w-5xl gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
||||
{modalities.map((mod, i) => (
|
||||
<a
|
||||
href="/tools"
|
||||
class:list={["reveal card-hover block rounded-xl border border-border bg-surface p-5", `reveal-delay-${i + 1}`]}
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-10 w-10 items-center justify-center rounded-lg" style={`background: ${mod.color}15;`}>
|
||||
<svg class="h-5 w-5" style={`color: ${mod.color};`} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" set:html={svgIcons[mod.icon]} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-display text-base font-semibold">{mod.name}</h3>
|
||||
<p class="text-sm text-muted">{mod.count} tools</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="mt-4 space-y-1.5">
|
||||
{mod.topTools.map((tool) => (
|
||||
<li class="text-xs text-muted">{tool}</li>
|
||||
))}
|
||||
</ul>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
interface Props {
|
||||
command: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
const { command, label = "terminal" } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="reveal rounded-xl border border-border/50 bg-terminal-bg p-1 shadow-xl">
|
||||
<!-- Terminal chrome -->
|
||||
<div class="flex items-center gap-2 px-4 py-2.5">
|
||||
<span class="h-3 w-3 rounded-full" style="background: #ff5f57;"></span>
|
||||
<span class="h-3 w-3 rounded-full" style="background: #febc2e;"></span>
|
||||
<span class="h-3 w-3 rounded-full" style="background: #28c840;"></span>
|
||||
<span class="ml-2 text-xs text-terminal-muted">{label}</span>
|
||||
</div>
|
||||
<!-- Command -->
|
||||
<div class="group relative rounded-lg bg-terminal-bg px-5 py-4">
|
||||
<code class="block text-sm leading-relaxed text-terminal-fg md:text-base">
|
||||
<span class="text-terminal-green">$</span>{" "}
|
||||
<span>{command}</span>
|
||||
<span class="cursor-blink"></span>
|
||||
</code>
|
||||
<button
|
||||
class="absolute right-3 top-3 rounded-md border border-terminal-muted/30 px-2 py-1 text-xs text-terminal-muted opacity-0 transition-opacity hover:text-terminal-fg group-hover:opacity-100"
|
||||
data-copy={command}
|
||||
aria-label="Copy command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script is:inline>
|
||||
document.querySelectorAll("[data-copy]").forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
var text = btn.getAttribute("data-copy");
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
btn.textContent = "Copied!";
|
||||
setTimeout(function () { btn.textContent = "Copy"; }, 2000);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user