mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-20 21:18:13 +02:00
feat(docs): enhance documentation & remove breadcrumbs
This commit is contained in:
parent
26a504f137
commit
5738bf0707
27 changed files with 631 additions and 401 deletions
|
|
@ -4,15 +4,6 @@ export default function BlogPostLoading() {
|
|||
return (
|
||||
<div className="min-h-screen relative pt-20">
|
||||
<div className="max-w-3xl mx-auto px-6 lg:px-10 pt-10 pb-20">
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-2 mb-8">
|
||||
<Skeleton className="h-4 w-10" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-10" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-40" />
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
<Skeleton className="h-6 w-16 rounded-full" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { Metadata } from "next";
|
|||
import Image from "next/image";
|
||||
import { notFound } from "next/navigation";
|
||||
import { blog } from "@/.source/server";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
import { ArticleJsonLd, FAQJsonLd } from "@/components/seo/json-ld";
|
||||
import { extractFaqFromBlogPost } from "@/lib/blog-faq";
|
||||
import { formatDate } from "@/lib/utils";
|
||||
|
|
@ -99,15 +98,6 @@ export default async function BlogPostPage(props: { params: Promise<{ slug: stri
|
|||
/>
|
||||
{faqEntries.length > 0 && <FAQJsonLd questions={faqEntries} />}
|
||||
<div className="max-w-3xl mx-auto px-6 lg:px-10 pt-10 pb-20">
|
||||
<BreadcrumbNav
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Blog", href: "/blog" },
|
||||
{ name: page.data.title, href: `/blog/${slug}` },
|
||||
]}
|
||||
className="mb-8"
|
||||
/>
|
||||
|
||||
{page.data.image && (
|
||||
<div className="relative aspect-2/1 overflow-hidden rounded-2xl mb-8">
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ function MagazineSearchGrid({
|
|||
type="search"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder="Search by title or topic…"
|
||||
placeholder="Search"
|
||||
className="w-full rounded-full bg-white py-3 pr-4 pl-12 text-sm text-neutral-800 shadow-sm ring-1 shadow-black/10 ring-black/10 transition outline-none placeholder:text-neutral-400 focus:border-neutral-400 focus:ring-2 focus:ring-neutral-200/80 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-500 dark:focus:border-neutral-500 dark:focus:ring-neutral-700/50"
|
||||
/>
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,6 @@ export default function ChangelogLoading() {
|
|||
<div className="max-w-5xl mx-auto relative">
|
||||
<div className="p-6 flex items-center justify-between">
|
||||
<div>
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Skeleton className="h-4 w-10" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-20" />
|
||||
</div>
|
||||
<Skeleton className="h-10 w-48 mb-2" />
|
||||
<Skeleton className="h-4 w-80" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { loader } from "fumadocs-core/source";
|
||||
import type { MDXComponents } from "mdx/types";
|
||||
import type { Metadata } from "next";
|
||||
import type { ComponentType } from "react";
|
||||
import { changelog } from "@/.source/server";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
import {
|
||||
ChangelogTimeline,
|
||||
type ChangelogTimelineEntry,
|
||||
} from "@/components/ui/changelog-timeline";
|
||||
import { formatDate } from "@/lib/utils";
|
||||
import { getMDXComponents } from "@/mdx-components";
|
||||
|
||||
|
|
@ -20,10 +25,10 @@ const source = loader({
|
|||
|
||||
interface ChangelogData {
|
||||
title: string;
|
||||
description: string;
|
||||
date: string;
|
||||
version?: string;
|
||||
tags?: string[];
|
||||
body: React.ComponentType<{ components?: Record<string, React.ComponentType> }>;
|
||||
body: ComponentType<{ components?: MDXComponents }>;
|
||||
}
|
||||
|
||||
interface ChangelogPageItem {
|
||||
|
|
@ -38,96 +43,27 @@ export default async function ChangelogPage() {
|
|||
const dateB = new Date(b.data.date).getTime();
|
||||
return dateB - dateA;
|
||||
});
|
||||
const entries: ChangelogTimelineEntry[] = sortedChangelogs.map((changelog) => {
|
||||
const MDX = changelog.data.body;
|
||||
const date = new Date(changelog.data.date);
|
||||
|
||||
return {
|
||||
version: changelog.data.version ? `Version ${changelog.data.version}` : "Release",
|
||||
date: formatDate(date),
|
||||
title: changelog.data.title,
|
||||
description: changelog.data.description,
|
||||
content: <MDX components={getMDXComponents()} />,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="min-h-screen relative pt-20">
|
||||
{/* Header */}
|
||||
<div className="border-b border-border/50">
|
||||
<div className="max-w-5xl mx-auto relative">
|
||||
<div className="p-6 flex items-center justify-between">
|
||||
<div>
|
||||
<BreadcrumbNav
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Changelog", href: "/changelog" },
|
||||
]}
|
||||
className="mb-4"
|
||||
/>
|
||||
<h1 className="text-4xl font-bold tracking-tight bg-gradient-to-r from-gray-900 to-gray-600 dark:from-white dark:to-gray-400 bg-clip-text text-transparent">
|
||||
Changelog
|
||||
</h1>
|
||||
<p className="text-muted-foreground mt-2">
|
||||
Stay up to date with the latest updates and improvements to SurfSense.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timeline */}
|
||||
<div className="max-w-5xl mx-auto px-6 lg:px-10 pt-10 pb-20">
|
||||
<div className="relative">
|
||||
{sortedChangelogs.map((changelog) => {
|
||||
const MDX = changelog.data.body;
|
||||
const date = new Date(changelog.data.date);
|
||||
const formattedDate = formatDate(date);
|
||||
|
||||
return (
|
||||
<div key={changelog.url} className="relative">
|
||||
<div className="flex flex-col md:flex-row gap-y-6">
|
||||
<div className="md:w-48 flex-shrink-0">
|
||||
<div className="md:sticky md:top-24 pb-10">
|
||||
<time className="text-sm font-medium text-muted-foreground block mb-3">
|
||||
{formattedDate}
|
||||
</time>
|
||||
|
||||
{changelog.data.version && (
|
||||
<div className="inline-flex relative z-10 items-center justify-center w-12 h-12 text-foreground border border-border rounded-xl text-sm font-bold bg-card shadow-sm">
|
||||
{changelog.data.version}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right side - Content */}
|
||||
<div className="flex-1 md:pl-8 relative pb-10">
|
||||
{/* Vertical timeline line */}
|
||||
<div className="hidden md:block absolute top-2 left-0 w-px h-full bg-border">
|
||||
{/* Timeline dot */}
|
||||
<div className="hidden md:block absolute -translate-x-1/2 size-3 bg-primary rounded-full z-10" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="relative z-10 flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-semibold tracking-tight text-balance">
|
||||
{changelog.data.title}
|
||||
</h2>
|
||||
|
||||
{/* Tags */}
|
||||
{changelog.data.tags && changelog.data.tags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{changelog.data.tags.map((tag: string) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="h-6 w-fit px-2.5 text-xs font-medium bg-muted text-muted-foreground rounded-full border flex items-center justify-center"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="prose dark:prose-invert max-w-none prose-headings:scroll-mt-8 prose-headings:font-semibold prose-a:no-underline prose-headings:tracking-tight prose-headings:text-balance prose-p:tracking-tight prose-p:text-balance prose-img:rounded-xl prose-img:shadow-lg">
|
||||
<MDX components={getMDXComponents()} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<ChangelogTimeline
|
||||
title="Changelog"
|
||||
description="Stay up to date with the latest updates and improvements to SurfSense."
|
||||
entries={entries}
|
||||
className="pt-12"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,15 +32,6 @@ export default function FreeModelLoading() {
|
|||
{/* SEO section skeleton */}
|
||||
<div className="border-t bg-background">
|
||||
<div className="container mx-auto px-4 py-10 max-w-3xl">
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Skeleton className="h-4 w-10" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-24" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-32" />
|
||||
</div>
|
||||
|
||||
<Skeleton className="h-7 w-3/4 mb-2" />
|
||||
<Skeleton className="h-4 w-full mb-1" />
|
||||
<Skeleton className="h-4 w-2/3 mb-8" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { Metadata } from "next";
|
|||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
import { FreeChatPage } from "@/components/free-chat/free-chat-page";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
import { FAQJsonLd, JsonLd } from "@/components/seo/json-ld";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
|
@ -192,15 +191,7 @@ export default async function FreeModelPage({ params }: PageProps) {
|
|||
{/* SEO content: in DOM for crawlers, clipped by parent overflow-hidden */}
|
||||
<div className="border-t bg-background">
|
||||
<article className="container mx-auto px-4 py-10 max-w-3xl">
|
||||
<BreadcrumbNav
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Free AI Chat", href: "/free" },
|
||||
{ name: model.name, href: `/free/${model.seo_slug}` },
|
||||
]}
|
||||
/>
|
||||
|
||||
<header className="mt-6 mb-6">
|
||||
<header className="mb-6">
|
||||
<h1 className="text-2xl font-bold mb-2">Chat with {model.name} Free, No Login</h1>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
Use <strong>{model.name}</strong> free online without login or sign-up. No account, no
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@ export default function FreeChatLoading() {
|
|||
return (
|
||||
<div className="min-h-screen pt-20">
|
||||
<article className="container mx-auto px-4 pb-20">
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-2 mb-8">
|
||||
<Skeleton className="h-4 w-10" />
|
||||
<Skeleton className="h-4 w-3" />
|
||||
<Skeleton className="h-4 w-24" />
|
||||
</div>
|
||||
|
||||
{/* Hero section */}
|
||||
<section className="mt-8 text-center max-w-3xl mx-auto space-y-4">
|
||||
<Skeleton className="h-12 w-3/4 mx-auto" />
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import Link from "next/link";
|
|||
import { AdUnit } from "@/components/ads/ad-unit";
|
||||
import { ADSENSE_SLOTS } from "@/components/ads/adsense-config";
|
||||
import { AdSenseScript } from "@/components/ads/adsense-script";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
import { FAQJsonLd, JsonLd } from "@/components/seo/json-ld";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -185,13 +184,6 @@ export default async function FreeHubPage() {
|
|||
<FAQJsonLd questions={FAQ_ITEMS} />
|
||||
|
||||
<article className="container mx-auto px-4 pb-20">
|
||||
<BreadcrumbNav
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Free AI Chat", href: "/free" },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Hero */}
|
||||
<section className="mt-8 text-center max-w-3xl mx-auto">
|
||||
<h1 className="text-4xl md:text-5xl font-bold tracking-tight">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type { Metadata } from "next";
|
||||
import PricingBasic from "@/components/pricing/pricing-section";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Pricing | SurfSense - Free AI Workspace, Automations & Agents",
|
||||
|
|
@ -14,14 +13,6 @@ export const metadata: Metadata = {
|
|||
const page = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="container mx-auto pt-24 px-4">
|
||||
<BreadcrumbNav
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Pricing", href: "/pricing" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<PricingBasic />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue