Skip to content

Commit 9b08341

Browse files
authored
docs: redesign (#2376)
* npm create fumadocs * design * base ui untouched * revert, proper untouched * add menu groups * add content * added docs pages and examples * eject docs layout * fix docs configuration * add pages and error boundaries * move pages * setup sentry * next config to ts * basic header / footer * auth * add examples * llms + readmes * add homepage * wip: metadata * fix og images and metadata * fix build * fix lint * missing files * fix validate links * add email docs * migrate directory + fix cardtable * remove generated files from git * small cleanup * fix / upgrade deps * update lockfile * merge fix * try fix tests * fix * fix search z-index * nav fixes * fix nav button dark * not found * fix og * misc fixes * fix shadcn * remove comments * fix lint * remove fonts + add analytics * fix * fix * add digital commons * i prove play button * pricing * add demo * wip * header * fix * fix build * pricing page cta * disable pro examples * disable dark mode * refactor / extract home elements * content fixes * fix demo * misc fixes * fix * small fixes * misc fixes * small fixes * fix lint * small fixes * fix * update next * fix
1 parent da82131 commit 9b08341

103 files changed

Lines changed: 21573 additions & 12642 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ next-env.d.ts
2929

3030
/content/examples/*/*
3131
/components/example/generated/
32-
sqlite.db
32+
sqlite.db
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"use client";
2+
import {
3+
AudioWaveform,
4+
ChevronRight,
5+
Code2,
6+
FileText,
7+
Heading,
8+
Image,
9+
List,
10+
ListOrdered,
11+
ListTodo,
12+
Minus,
13+
Pilcrow,
14+
Puzzle,
15+
Quote,
16+
Table,
17+
Video,
18+
} from "lucide-react";
19+
import React from "react";
20+
21+
const BlockCatalogItem: React.FC<{ name: string; icon: React.ReactNode }> = ({
22+
name,
23+
icon,
24+
}) => (
25+
<div className="group relative flex cursor-default flex-col items-center justify-center overflow-hidden rounded-xl border border-stone-100 bg-white p-3 transition-all duration-300 hover:-translate-y-1 hover:border-purple-200 hover:shadow-xl hover:shadow-purple-500/10">
26+
<div className="absolute inset-0 bg-gradient-to-br from-transparent to-purple-50/50 opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
27+
<div className="relative mb-2 flex h-9 w-9 items-center justify-center rounded-lg bg-stone-50 text-stone-400 transition-all duration-300 group-hover:scale-110 group-hover:bg-purple-100 group-hover:text-purple-600">
28+
{icon}
29+
</div>
30+
<span className="relative text-xs font-medium text-stone-500 transition-colors group-hover:text-stone-900">
31+
{name}
32+
</span>
33+
</div>
34+
);
35+
36+
export const BlockCatalog: React.FC = () => {
37+
return (
38+
<section className="relative overflow-hidden bg-gradient-to-b from-stone-50 via-white to-purple-50/30 py-32">
39+
{/* Subtle decorative elements */}
40+
<div className="pointer-events-none absolute inset-0 overflow-hidden">
41+
<div className="absolute -right-20 -top-20 h-96 w-96 rounded-full bg-purple-100/40 blur-3xl" />
42+
<div className="absolute -bottom-20 -left-20 h-96 w-96 rounded-full bg-amber-100/40 blur-3xl" />
43+
<div className="absolute left-1/2 top-1/2 h-[500px] w-[500px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-br from-purple-50/50 to-blue-50/50 blur-3xl" />
44+
</div>
45+
46+
<div className="relative mx-auto max-w-7xl px-6">
47+
<div className="mb-20 text-center">
48+
<div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-2xl border border-purple-100 bg-white/50 text-3xl shadow-sm backdrop-blur-sm">
49+
🧩
50+
</div>
51+
<h2 className="mb-6 font-serif text-4xl text-stone-900 md:text-6xl">
52+
Build anything, block by block.
53+
</h2>
54+
<p className="mx-auto max-w-2xl text-xl font-light leading-relaxed text-stone-600">
55+
Every BlockNote document is a collection of blocks—headings, lists,
56+
images, and more. Use the built-in blocks, customize them to fit
57+
your needs, or create entirely new ones.
58+
</p>
59+
</div>
60+
61+
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-6">
62+
<BlockCatalogItem
63+
name="Paragraph"
64+
icon={<Pilcrow className="h-4 w-4" />}
65+
/>
66+
<BlockCatalogItem
67+
name="Headings"
68+
icon={<Heading className="h-4 w-4" />}
69+
/>
70+
<BlockCatalogItem name="List" icon={<List className="h-4 w-4" />} />
71+
<BlockCatalogItem
72+
name="Ordered List"
73+
icon={<ListOrdered className="h-4 w-4" />}
74+
/>
75+
<BlockCatalogItem
76+
name="Checklist"
77+
icon={<ListTodo className="h-4 w-4" />}
78+
/>
79+
<BlockCatalogItem
80+
name="Toggle List"
81+
icon={<ChevronRight className="h-4 w-4" />}
82+
/>
83+
<BlockCatalogItem name="Code" icon={<Code2 className="h-4 w-4" />} />
84+
<BlockCatalogItem name="Quote" icon={<Quote className="h-4 w-4" />} />
85+
<BlockCatalogItem
86+
name="Divider"
87+
icon={<Minus className="h-4 w-4" />}
88+
/>
89+
<BlockCatalogItem name="Table" icon={<Table className="h-4 w-4" />} />
90+
<BlockCatalogItem name="Image" icon={<Image className="h-4 w-4" />} />
91+
<BlockCatalogItem name="Video" icon={<Video className="h-4 w-4" />} />
92+
<BlockCatalogItem
93+
name="Audio"
94+
icon={<AudioWaveform className="h-4 w-4" />}
95+
/>
96+
<BlockCatalogItem
97+
name="File"
98+
icon={<FileText className="h-4 w-4" />}
99+
/>
100+
<BlockCatalogItem
101+
name="Your Own"
102+
icon={<Puzzle className="h-4 w-4" />}
103+
/>
104+
</div>
105+
</div>
106+
</section>
107+
);
108+
};
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"use client";
2+
import Link from "next/link";
3+
import React, { useRef, useState } from "react";
4+
5+
export const DigitalCommons: React.FC = () => {
6+
const videoRef = useRef<HTMLVideoElement>(null);
7+
const [isPlaying, setIsPlaying] = useState(false);
8+
9+
const handlePlayPause = () => {
10+
if (videoRef.current) {
11+
if (isPlaying) {
12+
videoRef.current.pause();
13+
} else {
14+
videoRef.current.play();
15+
}
16+
setIsPlaying(!isPlaying);
17+
}
18+
};
19+
20+
return (
21+
<section className="relative overflow-hidden bg-[#1e1e2f] py-20">
22+
{/* Warm gradient overlay to harmonize with cream hero */}
23+
<div className="pointer-events-none absolute inset-0 bg-gradient-to-br from-amber-900/5 via-transparent to-purple-900/20" />
24+
{/* Top edge gradient for smoother transition */}
25+
<div className="pointer-events-none absolute inset-x-0 top-0 h-24 bg-gradient-to-b from-stone-200/10 to-transparent" />
26+
27+
<div className="relative mx-auto max-w-6xl px-6">
28+
{/* Asymmetric layout: content + video (vertically centered) */}
29+
<div className="flex flex-col items-center gap-12 lg:flex-row lg:items-center lg:gap-16">
30+
{/* Left: Editorial content */}
31+
<div className="flex-1 lg:max-w-md">
32+
{/* Eyebrow with EU flag only */}
33+
<div className="mb-6 flex items-center gap-3">
34+
<span className="text-xl">🇪🇺</span>
35+
<span className="text-xs font-bold uppercase tracking-widest text-amber-200/80">
36+
Digital Commons
37+
</span>
38+
</div>
39+
40+
{/* Headline - editorial style */}
41+
<h2 className="mb-6 font-serif text-3xl leading-tight text-white md:text-4xl">
42+
Three nations choose <br />
43+
<span className="bg-gradient-to-r from-purple-300 to-blue-300 bg-clip-text text-transparent">
44+
open source
45+
</span>{" "}
46+
to power
47+
<br />
48+
their digital future.
49+
</h2>
50+
51+
{/* Short punchy copy */}
52+
<p className="mb-8 text-base leading-relaxed text-stone-400">
53+
France, Germany, and the Netherlands partner to build{" "}
54+
<Link
55+
href="https://github.com/suitenumerique/docs"
56+
target="_blank"
57+
rel="noopener noreferrer"
58+
className="font-bold text-white decoration-purple-400 underline-offset-2 transition-colors hover:text-purple-300 hover:underline"
59+
>
60+
Docs
61+
</Link>
62+
, a collaborative writing tool for thousands of public servants.{" "}
63+
<strong className="text-white">BlockNote is the engine.</strong>
64+
</p>
65+
66+
{/* Compelling social proof - simpler */}
67+
<p className="mb-8 text-sm italic text-stone-500">
68+
&quot;Building Digital Commons means better tools, data
69+
sovereignty, and shared progress.&quot;
70+
</p>
71+
72+
{/* CTA */}
73+
<Link
74+
// href="https://lasuite.numerique.gouv.fr/en/produits/docs"
75+
href="/about"
76+
// target="_blank"
77+
// rel="noopener noreferrer"
78+
className="inline-flex items-center gap-2 text-sm font-medium text-purple-300 transition-colors hover:text-purple-200"
79+
>
80+
<span>Partner with us</span>
81+
<span></span>
82+
</Link>
83+
</div>
84+
85+
{/* Right: Video - vertically centered */}
86+
<div className="relative flex-1 lg:flex-[1.2]">
87+
{/* Glow effect */}
88+
<div className="absolute -inset-4 rounded-3xl bg-gradient-to-br from-purple-500/15 via-blue-500/10 to-amber-500/5 blur-2xl" />
89+
90+
<div className="relative overflow-hidden rounded-xl border border-white/10 shadow-2xl shadow-purple-900/20">
91+
<video
92+
ref={videoRef}
93+
className="aspect-video w-full cursor-pointer bg-[#2a2a3d] object-cover"
94+
poster="/video/docs-poster.png"
95+
onClick={handlePlayPause}
96+
onEnded={() => setIsPlaying(false)}
97+
playsInline
98+
preload="none"
99+
>
100+
<source src="/video/docs.mp4" type="video/mp4" />
101+
</video>
102+
103+
{/* Play button overlay */}
104+
{!isPlaying && (
105+
<button
106+
onClick={handlePlayPause}
107+
className="absolute inset-0 flex items-center justify-center bg-black/20 transition-all hover:bg-black/30"
108+
aria-label="Play video"
109+
>
110+
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-white shadow-xl transition-transform hover:scale-110">
111+
<svg
112+
className="ml-1 h-8 w-8 text-purple-600"
113+
fill="currentColor"
114+
viewBox="0 0 24 24"
115+
>
116+
<path d="M8 5v14l11-7z" />
117+
</svg>
118+
</div>
119+
</button>
120+
)}
121+
</div>
122+
</div>
123+
</div>
124+
</div>
125+
</section>
126+
);
127+
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React from "react";
2+
3+
const faqs = [
4+
{
5+
question: "Isn't it easier to use a Headless editor framework?",
6+
answer:
7+
"There are a number of really powerful headless text editor frameworks available. In fact, BlockNote is built on Prosemirror and TipTap. However, even when using a headless library, it takes several months and requires deep expertise to build a fully-featured editor with a polished UI that your users expect.",
8+
},
9+
{
10+
question: "Is BlockNote ready for production use?",
11+
answer:
12+
"BlockNote is used by dozens of companies in production, ranging from startups to large enterprises and public institutions. Also, we didn't reinvent the wheel. The core editor is built on top of Prosemirror - a battle tested framework that powers software from Atlassian, Gitlab, the New York Times, and many others.",
13+
},
14+
{
15+
question: "Can I add my own extensions to BlockNote?",
16+
answer:
17+
"BlockNote comes with lot of functionality out-of-the-box, but we understand that every use case is different. You can easily customize the built-in UI Components, or create your own custom Blocks, Inline Content, and Styles. If you want to go even further, you can extend the core editor with additional Prosemirror or TipTap plugins.",
18+
},
19+
{
20+
question: "Is BlockNote really free?",
21+
answer:
22+
"100% of BlockNote is open source. We offer consultancy, support services and commercial licenses for specific XL packages to help sustain BlockNote. Explore our pricing page for more details.",
23+
},
24+
];
25+
26+
export const FAQ: React.FC = () => {
27+
return (
28+
<section className="relative overflow-hidden border-t border-stone-100 bg-white py-24">
29+
<div className="mx-auto max-w-5xl px-6">
30+
<div className="mb-16">
31+
<h2 className="font-serif text-5xl font-medium tracking-tight text-stone-900 md:text-6xl">
32+
Questions?
33+
</h2>
34+
</div>
35+
36+
<div className="grid gap-x-12 gap-y-16 md:grid-cols-2">
37+
{faqs.map((faq, index) => (
38+
<div key={index} className="flex flex-col gap-4">
39+
<h3 className="font-sans text-xl font-bold leading-tight text-stone-900">
40+
{faq.question}
41+
</h3>
42+
<p className="font-sans text-base leading-relaxed text-stone-600">
43+
{faq.answer}
44+
</p>
45+
</div>
46+
))}
47+
</div>
48+
</div>
49+
</section>
50+
);
51+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"use client";
2+
import React, { useState } from "react";
3+
import { FeatureSection } from "./FeatureSection";
4+
import { ContentItem, FeatureWindow } from "./ui/FeatureWindow";
5+
6+
export const FeatureAI: React.FC = () => {
7+
const [activeTab, setActiveTab] = useState<"toolbar" | "models" | "human">(
8+
"toolbar",
9+
);
10+
11+
const content: Record<string, ContentItem> = {
12+
toolbar: {
13+
type: "video",
14+
src: "/video/ai-select.mp4",
15+
className: "px-4",
16+
},
17+
models: {
18+
type: "image",
19+
src: "/img/screenshots/home/any_model.png",
20+
alt: "Bring Any Model",
21+
},
22+
human: {
23+
type: "image",
24+
src: "/img/screenshots/home/human_in_the_loop.png",
25+
alt: "Human in the Loop",
26+
},
27+
};
28+
29+
const tabs = [
30+
{
31+
id: "toolbar",
32+
icon: <span></span>,
33+
label: "AI in the Editor",
34+
description:
35+
"Context-aware completions and edits directly in the document.",
36+
},
37+
{
38+
id: "models",
39+
icon: <span>🔌</span>,
40+
label: "Bring Any Model",
41+
description: "Connect OpenAI, Anthropic, or your own endpoints.",
42+
},
43+
{
44+
id: "human",
45+
icon: <span>🤝</span>,
46+
label: "Human in the Loop",
47+
description: "Users accept, reject, or refine AI suggestions.",
48+
},
49+
];
50+
51+
return (
52+
<FeatureSection
53+
title="Build for What's Next."
54+
description="Build the future of document editing. Let users co-author with AI. Connect any model and integrate RAG, tools, and agents: powered by the AI SDK."
55+
tabs={tabs}
56+
activeTabId={activeTab}
57+
onTabChange={(id) => setActiveTab(id as any)}
58+
reverse={true}
59+
>
60+
<FeatureWindow content={content[activeTab]} theme="light" />
61+
</FeatureSection>
62+
);
63+
};

0 commit comments

Comments
 (0)