import { useMemo, useState } from "react"; import { Link, useParams } from "react-router-dom"; import SkyCanvas from "../components/SkyCanvas"; import { PublicFooter, PublicNav } from "../components/PublicChrome"; import { getTool, tools, toolsHub, type ToolDef } from "../content/tools"; import { useAuth } from "../hooks/useAuth"; import { buildPodcastScript, scriptToText } from "../lib/podcastScript"; import { Inline, useMeta } from "./Blog"; import "../styles/blog.css"; import "../styles/tools.css"; const pathTitle = (path: string) => { const tool = tools.find((t) => `/tools/${t.slug}` === path); if (tool) return tool.heroTitle; if (path === "/notebooklm-alternative") return "Notestack vs NotebookLM"; return path.replace(/^\/blogs\//, "").replace(/-/g, " ").replace(/^./, (c) => c.toUpperCase()); }; export function ToolsHub() { useMeta(toolsHub.metaTitle, toolsHub.description); return (

Free tools

{toolsHub.heroTitle}

{toolsHub.heroDescription}

{tools.map((t) => (

{t.heroTitle}

{t.description}

))}
); } /** Every free tool requires sign in: signed out visitors see the pitch and a sign in link that returns them here. */ function SignInGate({ tool }: { tool: ToolDef }) { const next = encodeURIComponent(`/tools/${tool.slug}`); return (

Sign in to use the {tool.eyebrow.toLowerCase()}

It is free. Create an account in seconds and come straight back to this tool.

Sign up free Sign in
); } function PodcastScriptWidget({ tool }: { tool: ToolDef }) { const [text, setText] = useState(""); const [copied, setCopied] = useState(false); const script = useMemo(() => buildPodcastScript(text), [text]); const inputWords = text.trim() ? text.trim().split(/\s+/).length : 0; const copy = async () => { if (!script) return; await navigator.clipboard.writeText(scriptToText(script)); setCopied(true); setTimeout(() => setCopied(false), 1500); }; const download = () => { if (!script) return; const url = URL.createObjectURL(new Blob([scriptToText(script)], { type: "text/plain" })); const a = document.createElement("a"); a.href = url; a.download = `${tool.slug}-script.txt`; a.click(); URL.revokeObjectURL(url); }; return (