Skip to content

Commit 37eb72a

Browse files
committed
docs structure
1 parent 157da93 commit 37eb72a

32 files changed

+648
-33
lines changed

docs/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@
1111
"lint": "eslint ."
1212
},
1313
"dependencies": {
14+
"@tanstack/react-router": "^1.134.15",
1415
"react": "^19.2.0",
1516
"react-dom": "^19.2.0",
16-
"react-icons": "^5.3.0"
17+
"react-icons": "^5.3.0",
18+
"react-markdown": "^10.1.0",
19+
"rehype-highlight": "^7.0.2",
20+
"remark-gfm": "^4.0.1"
1721
},
1822
"devDependencies": {
1923
"@tailwindcss/postcss": "^4.1.16",
2024
"@types/node": "^20.11.30",
2125
"@types/react": "^19.0.6",
2226
"@types/react-dom": "^19.0.3",
27+
"@types/react-syntax-highlighter": "^15.5.13",
2328
"@typescript-eslint/eslint-plugin": "^7.0.0",
2429
"@typescript-eslint/parser": "^7.0.0",
2530
"@vitejs/plugin-react": "^4.3.1",

docs/src/App.tsx

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { useState } from "react";
1+
import React from "react";
22
import { FiChevronRight } from "react-icons/fi";
3-
import { FaGithub, FaXTwitter } from "react-icons/fa6";
3+
import { Link } from "@tanstack/react-router";
4+
import { Navbar } from "./components/Navbar";
45
import { TechCard } from "./components/TechCard";
56
import type { TechCardProps } from "./components/TechCard";
67

@@ -71,7 +72,7 @@ const technologies = [
7172
] as const satisfies TechCardProps[];
7273

7374
export function App() {
74-
const [copied, setCopied] = useState(false);
75+
const [copied, setCopied] = React.useState(false);
7576
const command = "bun create thunder-app@latest";
7677

7778
const handleCopy = async () => {
@@ -84,26 +85,7 @@ export function App() {
8485

8586
return (
8687
<main className="relative flex flex-1 flex-col items-center gap-32 justify-start px-4 py-12">
87-
<div className="fixed top-8 right-8 flex items-center gap-4 text-white/80">
88-
<a
89-
aria-label="Open GitHub repository"
90-
className="hover:text-white transition-colors duration-200"
91-
href="https://github.com/acrichards3/thunder-cli"
92-
rel="noopener noreferrer"
93-
target="_blank"
94-
>
95-
<FaGithub className="h-10 w-10 drop-shadow" />
96-
</a>
97-
<a
98-
aria-label="Open X profile"
99-
className="hover:text-white transition-colors duration-200"
100-
href="https://x.com/Acricha3"
101-
rel="noopener noreferrer"
102-
target="_blank"
103-
>
104-
<FaXTwitter className="h-10 w-10 drop-shadow" />
105-
</a>
106-
</div>
88+
<Navbar hideLogo />
10789
<div className="flex flex-col items-center gap-6">
10890
<img
10991
alt="Thunder App Logo"
@@ -114,23 +96,25 @@ export function App() {
11496
Build <span className="text-cyan-400">lightning fast</span> full-stack
11597
TypeScript apps with Bun
11698
</h1>
117-
<a
99+
<Link
118100
aria-label="View documentation"
119101
className="group inline-flex items-center gap-2 text-cyan-300 hover:text-cyan-200 text-base sm:text-lg font-semibold tracking-wide transition-colors duration-200"
120-
href="https://www.npmjs.com/package/create-thunder-app"
121-
rel="noopener noreferrer"
122-
target="_blank"
102+
to="/introduction"
123103
>
124104
View documentation
125105
<FiChevronRight
126106
aria-hidden="true"
127107
className="h-5 w-5 transition-transform duration-200 group-hover:translate-x-0.5"
128108
/>
129-
</a>
109+
</Link>
130110
<div className="flex items-center gap-3 bg-white/5 border border-cyan-500/20 rounded-lg px-4 py-3 max-w-2xl w-full group hover:border-cyan-400/40 transition-colors duration-200">
131111
<code className="text-white text-lg font-mono flex-1">{command}</code>
132112
<button
133-
className="px-4 py-2 bg-cyan-500/20 hover:bg-cyan-500/30 border border-cyan-500/40 rounded text-cyan-300 text-sm font-semibold transition-colors duration-200 cursor-pointer shrink-0"
113+
className={`px-4 py-2 rounded text-sm font-semibold transition-colors duration-200 cursor-pointer shrink-0 ${
114+
copied
115+
? "bg-green-500/30 hover:bg-green-500/40 border border-green-400 text-green-200"
116+
: "bg-cyan-500/20 hover:bg-cyan-500/30 border border-cyan-500/40 text-cyan-300"
117+
}`}
134118
onClick={handleCopy}
135119
type="button"
136120
>
@@ -144,7 +128,8 @@ export function App() {
144128
Build fast. <span className="text-cyan-400">Run faster.</span>
145129
</h2>
146130
<p className="text-gray-400 text-lg">
147-
A lean TypeScript stack tuned for runtime speed and developer speed
131+
A lean TypeScript stack tuned for runtime speed and developer
132+
experience
148133
</p>
149134
</div>
150135
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl w-full">
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from "react";
2+
import { Navbar } from "./Navbar";
3+
import { Sidebar } from "./Sidebar";
4+
5+
interface DocsContainerProps {
6+
children: React.ReactNode;
7+
}
8+
9+
export const DocsContainer: React.FC<DocsContainerProps> = ({ children }) => {
10+
return (
11+
<main className="relative flex min-h-screen flex-col">
12+
<Navbar />
13+
<div className="flex flex-1 pt-24">
14+
<Sidebar />
15+
<div className="flex flex-1 flex-col items-start gap-8 px-8 py-12">
16+
{children}
17+
</div>
18+
</div>
19+
</main>
20+
);
21+
};

docs/src/components/Markdown.tsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from "react";
2+
import ReactMarkdown from "react-markdown";
3+
import remarkGfm from "remark-gfm";
4+
5+
interface MarkdownProps {
6+
content: string;
7+
}
8+
9+
export const Markdown: React.FC<MarkdownProps> = ({ content }) => {
10+
return (
11+
<div className="prose prose-invert prose-cyan max-w-none">
12+
<ReactMarkdown
13+
remarkPlugins={[remarkGfm]}
14+
components={{
15+
h1: ({ children }) => (
16+
<h1 className="text-5xl font-bold text-white drop-shadow-md mb-6 mt-8 first:mt-0">
17+
{children}
18+
</h1>
19+
),
20+
h2: ({ children }) => (
21+
<h2 className="text-4xl font-bold text-white drop-shadow-md mb-4 mt-8">
22+
{children}
23+
</h2>
24+
),
25+
h3: ({ children }) => (
26+
<h3 className="text-3xl font-bold text-white drop-shadow-md mb-3 mt-6">
27+
{children}
28+
</h3>
29+
),
30+
h4: ({ children }) => (
31+
<h4 className="text-2xl font-bold text-white drop-shadow-md mb-2 mt-4">
32+
{children}
33+
</h4>
34+
),
35+
p: ({ children }) => (
36+
<p className="text-gray-300 text-lg leading-relaxed mb-4">
37+
{children}
38+
</p>
39+
),
40+
ul: ({ children }) => (
41+
<ul className="list-disc list-inside text-gray-300 text-lg mb-4 space-y-2 ml-4">
42+
{children}
43+
</ul>
44+
),
45+
ol: ({ children }) => (
46+
<ol className="list-decimal list-inside text-gray-300 text-lg mb-4 space-y-2 ml-4">
47+
{children}
48+
</ol>
49+
),
50+
li: ({ children }) => (
51+
<li className="text-gray-300 text-lg">{children}</li>
52+
),
53+
code: ({ children, className }) => {
54+
const isInline = !className;
55+
return isInline ? (
56+
<code className="bg-white/10 text-cyan-300 px-1.5 py-0.5 rounded text-sm font-mono">
57+
{children}
58+
</code>
59+
) : (
60+
<code className="block bg-black/30 text-gray-200 p-4 rounded-lg overflow-x-auto mb-4 font-mono text-sm border border-cyan-500/20">
61+
{children}
62+
</code>
63+
);
64+
},
65+
pre: ({ children }) => <pre className="mb-4">{children}</pre>,
66+
a: ({ children, href }) => (
67+
<a
68+
className="text-cyan-400 hover:text-cyan-300 underline transition-colors"
69+
href={href}
70+
rel="noopener noreferrer"
71+
target="_blank"
72+
>
73+
{children}
74+
</a>
75+
),
76+
blockquote: ({ children }) => (
77+
<blockquote className="border-l-4 border-cyan-500/40 pl-4 italic text-gray-300 mb-4">
78+
{children}
79+
</blockquote>
80+
),
81+
hr: () => <hr className="border-cyan-500/20 my-8" />,
82+
}}
83+
>
84+
{content}
85+
</ReactMarkdown>
86+
</div>
87+
);
88+
};

docs/src/components/Navbar.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from "react";
2+
import { Link } from "@tanstack/react-router";
3+
import { FaGithub, FaXTwitter } from "react-icons/fa6";
4+
5+
interface NavbarProps {
6+
hideLogo?: boolean;
7+
}
8+
9+
export const Navbar: React.FC<NavbarProps> = ({ hideLogo }) => {
10+
return (
11+
<nav className="fixed top-8 left-8 right-8 z-50 flex items-center justify-between pointer-events-none">
12+
{hideLogo ? (
13+
<div className="h-15 w-15" />
14+
) : (
15+
<Link
16+
aria-label="Go to home"
17+
className="pointer-events-auto transition-opacity duration-200 hover:opacity-80"
18+
to="/"
19+
>
20+
<img
21+
alt="Thunder App Logo"
22+
className="h-15 w-15 drop-shadow-lg"
23+
src="/logos/thunder-app.png"
24+
/>
25+
</Link>
26+
)}
27+
<div className="flex items-center gap-4 text-white/80 pointer-events-auto">
28+
<a
29+
aria-label="Open GitHub repository"
30+
className="hover:text-white transition-colors duration-200"
31+
href="https://github.com/acrichards3/thunder-cli"
32+
rel="noopener noreferrer"
33+
target="_blank"
34+
>
35+
<FaGithub className="h-10 w-10 drop-shadow" />
36+
</a>
37+
<a
38+
aria-label="Open X profile"
39+
className="hover:text-white transition-colors duration-200"
40+
href="https://x.com/Acricha3"
41+
rel="noopener noreferrer"
42+
target="_blank"
43+
>
44+
<FaXTwitter className="h-10 w-10 drop-shadow" />
45+
</a>
46+
</div>
47+
</nav>
48+
);
49+
};

docs/src/components/Sidebar.tsx

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React from "react";
2+
import { Link, useLocation } from "@tanstack/react-router";
3+
4+
interface SidebarItem {
5+
items: Array<{
6+
href: string;
7+
title: string;
8+
}>;
9+
order: number;
10+
sectionTitle: string;
11+
}
12+
13+
const SIDEBAR_ITEMS = {
14+
deployment: {
15+
items: [
16+
{
17+
href: "/deployment",
18+
title: "Deployment",
19+
},
20+
],
21+
order: 3,
22+
sectionTitle: "Deployment",
23+
},
24+
thunderApp: {
25+
items: [
26+
{
27+
href: "/introduction",
28+
title: "Introduction",
29+
},
30+
{
31+
href: "/getting-started",
32+
title: "Getting Started",
33+
},
34+
{
35+
href: "/project-structure",
36+
title: "Project Structure",
37+
},
38+
{
39+
href: "/recommendations",
40+
title: "Recommendations",
41+
},
42+
],
43+
order: 1,
44+
sectionTitle: "Thunder App",
45+
},
46+
usage: {
47+
items: [
48+
{
49+
href: "/first-steps",
50+
title: "First Steps",
51+
},
52+
{
53+
href: "/typescript",
54+
title: "Typescript",
55+
},
56+
{
57+
href: "/vite",
58+
title: "Vite",
59+
},
60+
{
61+
href: "/bun",
62+
title: "Bun",
63+
},
64+
{
65+
href: "/drizzle",
66+
title: "Drizzle",
67+
},
68+
{
69+
href: "/authjs",
70+
title: "Auth.js",
71+
},
72+
],
73+
order: 2,
74+
sectionTitle: "Usage",
75+
},
76+
} as const satisfies Record<string, SidebarItem>;
77+
78+
export const Sidebar: React.FC = () => {
79+
const location = useLocation();
80+
const currentPath = location.pathname;
81+
82+
const sortedSections = Object.values(SIDEBAR_ITEMS).sort(
83+
(a, b) => a.order - b.order,
84+
);
85+
86+
return (
87+
<aside className="flex flex-col gap-8 w-64 py-8 px-4">
88+
{sortedSections.map((section) => (
89+
<div className="flex flex-col gap-2" key={section.sectionTitle}>
90+
<h3 className="mb-2 text-base font-semibold uppercase tracking-wide text-white">
91+
{section.sectionTitle}
92+
</h3>
93+
<nav className="flex flex-col gap-1">
94+
{section.items.map((item) => {
95+
const isActive = currentPath === item.href;
96+
return (
97+
<Link
98+
className={`relative flex items-center rounded-md px-3 py-2 text-sm transition-colors duration-200 ${
99+
isActive
100+
? "bg-white/10 font-semibold text-cyan-300"
101+
: "text-gray-300 hover:bg-white/5 hover:text-white"
102+
}`}
103+
key={item.href}
104+
to={item.href}
105+
>
106+
{isActive && (
107+
<div className="absolute left-0 top-0 bottom-0 w-1 bg-cyan-400 rounded-r" />
108+
)}
109+
<span className="pl-1">{item.title}</span>
110+
</Link>
111+
);
112+
})}
113+
</nav>
114+
</div>
115+
))}
116+
</aside>
117+
);
118+
};

0 commit comments

Comments
 (0)