import { createFileRoute } from "@tanstack/react-router"; import { useState } from "react"; import { SiteFooter } from "@/components/site-footer"; import { buildPageSeo } from "@/lib/seo"; const homeTitle = "OpenSEO - Open Source SEO Platform"; const homeDescription = "Own your SEO. OpenSEO helps teams manage keyword research, backlink analysis, competitor monitoring, and site audits without expensive monthly SEO software subscriptions."; export const Route = createFileRoute("/")({ head: () => buildPageSeo({ title: homeTitle, description: homeDescription, path: "/", imageAlt: "OpenSEO keyword research dashboard preview", }), component: Home, }); // ─── Shared ────────────────────────────────────────────────────────── function GitHubIcon({ size = 18 }: { size?: number }) { return ( ); } function useWaitlist() { const [email, setEmail] = useState(""); const [status, setStatus] = useState< "idle" | "loading" | "success" | "error" >("idle"); const [errorMessage, setErrorMessage] = useState(""); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setStatus("loading"); setErrorMessage(""); try { const res = await fetch("/api/subscribe", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email }), }); if (!res.ok) { const data = await res.json().catch(() => ({})); throw new Error( (data as { error?: string }).error || "Something went wrong", ); } setStatus("success"); setEmail(""); } catch (err) { setStatus("error"); setErrorMessage( err instanceof Error ? err.message : "Something went wrong", ); } }; return { email, setEmail, status, errorMessage, handleSubmit }; } // ─── Page ──────────────────────────────────────────────────────────── function Home() { const wl = useWaitlist(); return (
{/* Nav */} {/* Headline */}

Own your SEO

Open source alternative to Semrush and Ahrefs

{/* Features */} {/* Form */}
{wl.status === "success" ? (

You're on the list.

) : (
wl.setEmail(e.target.value)} placeholder="you@example.com" className="flex-1 min-w-0 h-10 px-3 text-sm border border-neutral-300 rounded-md bg-white placeholder:text-neutral-500 focus:outline-none focus:ring-1 focus:ring-neutral-900 transition-all" disabled={wl.status === "loading"} />
{wl.status === "error" && (

{wl.errorMessage}

)}
)}

Get notified when the managed version is ready and when we add new features.

Self-host today via Docker or Cloudflare

Bring your own DataForSEO API key. Pay by usage, not per month. 100% open source (MIT).

View on GitHub

If you don't want to self host or the DataForSEO minimum commitments are too high, sign up in the form above and we'll notify you when the managed version is released.

{/* Demo */}

Keyword research in OpenSEO

{/* Footer */}
); }