feat: add copy button to terminal, expand Why Choose, add pricing section, reorder nav

This commit is contained in:
ashim-hq
2026-04-24 00:04:25 +08:00
parent 6e6c268910
commit afdd9fd165
5 changed files with 146 additions and 11 deletions
+2
View File
@@ -5,6 +5,7 @@ import { Hero } from "@/components/hero";
import { HowItWorks } from "@/components/how-it-works";
import { Navbar } from "@/components/navbar";
import { OpenSource } from "@/components/open-source";
import { Pricing } from "@/components/pricing";
import { WhyChoose } from "@/components/why-choose";
export default function Home() {
@@ -17,6 +18,7 @@ export default function Home() {
<WhyChoose />
<BentoGrid />
<Enterprise />
<Pricing />
<OpenSource />
</main>
<Footer />
+31 -8
View File
@@ -1,6 +1,21 @@
"use client";
import { Check, Copy } from "lucide-react";
import { useState } from "react";
import { FadeIn } from "./fade-in";
const command = "docker run -d -p 1349:1349 ghcr.io/ashim-hq/ashim";
export function HowItWorks() {
const [copied, setCopied] = useState(false);
function copyCommand() {
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
return (
<section id="how-it-works" className="bg-background-alt px-6 py-20 md:py-28">
<div className="mx-auto max-w-2xl text-center">
@@ -13,17 +28,25 @@ export function HowItWorks() {
<FadeIn delay={0.1}>
<div className="mt-8 overflow-hidden rounded-xl border border-border bg-[#1e1e1e] shadow-lg">
<div className="flex items-center gap-2 border-b border-white/10 px-4 py-2.5">
<div className="h-2.5 w-2.5 rounded-full bg-[#ff5f57]" />
<div className="h-2.5 w-2.5 rounded-full bg-[#febc2e]" />
<div className="h-2.5 w-2.5 rounded-full bg-[#28c840]" />
<div className="flex items-center justify-between border-b border-white/10 px-4 py-2.5">
<div className="flex items-center gap-2">
<div className="h-2.5 w-2.5 rounded-full bg-[#ff5f57]" />
<div className="h-2.5 w-2.5 rounded-full bg-[#febc2e]" />
<div className="h-2.5 w-2.5 rounded-full bg-[#28c840]" />
</div>
<button
type="button"
onClick={copyCommand}
className="text-white/40 transition-colors hover:text-white/80"
aria-label="Copy command"
>
{copied ? <Check size={14} /> : <Copy size={14} />}
</button>
</div>
<div className="px-5 py-4 text-left font-mono text-sm">
<div className="overflow-x-auto whitespace-nowrap px-5 py-4 text-left font-mono text-sm">
<p className="text-white">
<span className="text-green-400">$</span>{" "}
<span className="select-all">
docker run -d -p 1349:1349 -v snapotter-data:/data ghcr.io/ashim-hq/ashim:latest
</span>
<span className="select-all">{command}</span>
</p>
</div>
</div>
+2 -2
View File
@@ -4,9 +4,9 @@ import { Github, Menu, Star, X } from "lucide-react";
import { useState } from "react";
const links = [
{ label: "Features", href: "#features" },
{ label: "Download", href: "#how-it-works" },
{ label: "Pricing", href: "#enterprise" },
{ label: "Features", href: "#features" },
{ label: "Pricing", href: "#pricing" },
{ label: "Docs", href: "https://docs.snapotter.com" },
{ label: "Contact", href: "/contact" },
];
+84
View File
@@ -0,0 +1,84 @@
import { Check } from "lucide-react";
import { FadeIn } from "./fade-in";
const plans = [
{
name: "Free",
price: "Free",
subtitle: "For everyone",
features: [
"All 40+ tools included",
"Unlimited usage",
"Self-host anywhere",
"Community support",
"Open source (AGPL-3.0)",
],
cta: "Get Started",
href: "#how-it-works",
highlighted: false,
},
{
name: "Enterprise",
price: "Custom",
subtitle: "For organizations",
features: [
"Everything in Free",
"Commercial license (no AGPL)",
"Priority support",
"Deployment assistance",
"Custom integrations",
],
cta: "Contact Us",
href: "/contact",
highlighted: true,
},
];
export function Pricing() {
return (
<section id="pricing" className="bg-background-alt px-6 py-24 md:py-36">
<div className="mx-auto max-w-4xl">
<FadeIn>
<h2 className="text-center text-3xl font-bold tracking-tight md:text-4xl">
Simple pricing
</h2>
<p className="mx-auto mt-4 max-w-xl text-center text-lg text-muted">
Free for everyone. Enterprise support when you need it.
</p>
</FadeIn>
<div className="mt-16 grid gap-6 md:grid-cols-2">
{plans.map((plan, i) => (
<FadeIn key={plan.name} delay={i * 0.1}>
<div className="flex h-full flex-col rounded-2xl border border-border bg-background p-8">
<p className="text-sm font-medium text-muted">{plan.subtitle}</p>
<p className="mt-2 text-3xl font-bold">{plan.price}</p>
<ul className="mt-8 flex-1 space-y-3">
{plan.features.map((feature) => (
<li key={feature} className="flex items-center gap-2 text-sm">
<Check size={16} className="shrink-0 text-accent" />
<span>{feature}</span>
</li>
))}
</ul>
<a
href={plan.href}
className={`mt-8 block rounded-lg px-4 py-2.5 text-center text-sm font-medium transition-colors ${
plan.highlighted
? "bg-accent text-accent-foreground hover:bg-accent-hover"
: "border border-border hover:bg-background-alt"
}`}
>
{plan.cta}
</a>
</div>
</FadeIn>
))}
</div>
</div>
</section>
);
}
+27 -1
View File
@@ -1,4 +1,15 @@
import { BadgeCheck, CircleDollarSign, Layers, ShieldCheck, UserRoundX, Zap } from "lucide-react";
import {
BadgeCheck,
CircleDollarSign,
Code,
Layers,
Plug,
ShieldCheck,
UserRoundX,
Workflow,
Zap,
} from "lucide-react";
import { FadeIn } from "./fade-in";
const benefits = [
@@ -32,6 +43,21 @@ const benefits = [
description: "Powered by Sharp. Process images instantly.",
icon: Zap,
},
{
title: "Open Source",
description: "AGPL-3.0 licensed. Inspect every line of code.",
icon: Code,
},
{
title: "REST API",
description: "Every tool accessible via HTTP. Full OpenAPI docs.",
icon: Plug,
},
{
title: "Pipeline Automation",
description: "Chain tools together. Automate your workflows.",
icon: Workflow,
},
];
export function WhyChoose() {