Skip to content

Commit bf0f4f6

Browse files
committed
docs: update all pages of docs to be iikanji
1 parent 9f19dcf commit bf0f4f6

5 files changed

Lines changed: 146 additions & 181 deletions

File tree

packages/docs/src/components/Sidebar/Sidebar.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,28 @@ interface NavSection {
1313
const navigation: NavSection[] = [
1414
{
1515
title: "Getting Started",
16-
items: [{ label: "Introduction", href: "/getting-started" }],
16+
items: [
17+
{ label: "Introduction", href: "/funstack-static/getting-started" },
18+
],
1719
},
1820
{
1921
title: "API Reference",
2022
items: [
21-
{ label: "funstackStatic()", href: "/api/funstack-static" },
22-
{ label: "defer()", href: "/api/defer" },
23+
{
24+
label: "funstackStatic()",
25+
href: "/funstack-static/api/funstack-static",
26+
},
27+
{ label: "defer()", href: "/funstack-static/api/defer" },
2328
],
2429
},
2530
{
2631
title: "Concepts",
27-
items: [{ label: "React Server Components", href: "/concepts/rsc" }],
32+
items: [
33+
{
34+
label: "React Server Components",
35+
href: "/funstack-static/concepts/rsc",
36+
},
37+
],
2838
},
2939
];
3040

packages/docs/src/pages/GettingStarted.mdx

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,44 @@ The Root component:
6868

6969
### 3. Create Your App Component
7070

71-
The App component defines what comes into the `children` of the Root.
71+
The App component defines what comes into the `children` of the Root. This is the entrypoint of your SPA.
7272

73-
This is the entrypoint of your SPA and you can do anything you want. If you want routing, you can bring your favorite SPA router. Here, we use `@funstack/router` as an example:
73+
Since the App component is a server component, for interactivity you can import and use client components inside it.
74+
75+
```tsx
76+
// src/App.tsx
77+
import Counter from "./Counter";
78+
79+
export default function App() {
80+
return (
81+
<main>
82+
<h1>Welcome to my site!</h1>
83+
<Counter />
84+
</main>
85+
);
86+
}
87+
```
88+
89+
```tsx
90+
// src/Counter.tsx
91+
"use client";
92+
93+
import { useState } from "react";
94+
95+
export default function Counter() {
96+
const [count, setCount] = useState(0);
97+
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
98+
}
99+
```
100+
101+
The App component:
102+
103+
- is a server component
104+
- **CAN** import client components and use them within the app
105+
106+
### 4. Add Routing (Optional)
107+
108+
If you want routing, you can bring your favorite SPA router. Here, we use `@funstack/router` as an example:
74109

75110
```tsx
76111
// src/App.tsx
@@ -93,27 +128,24 @@ export default function App() {
93128
}
94129
```
95130

96-
The App component:
97-
98-
- is a server component
99-
- **CAN** import client components and use them within the app
100-
101-
### 4. Start Development Server
131+
### 5. Start Development Server
102132

103133
```bash
104134
npm run dev
105135
```
106136

107137
Your site is now running at `http://localhost:5173`!
108138

109-
### 5. Build for Production
139+
### 6. Build for Production
110140

111141
```bash
112142
npm run build
113143
```
114144

115145
Your SPA is pre-rendered to static files in the `dist/public` directory, ready to deploy to any static hosting provider.
116146

147+
Since FUNSTACK Static is built on top of Vite, any Vite configurations and plugins should work seamlessly.
148+
117149
## Project Structure
118150

119151
A typical FUNSTACK Static project looks like this:
@@ -133,6 +165,6 @@ Only two files are required: `Root.tsx` and `App.tsx`. The paths to these files
133165

134166
## What's Next?
135167

136-
- Learn about the [funstackStatic() API](/api/funstack-static) for configuration options
137-
- Understand [defer()](/api/defer) for streaming content
138-
- Dive into [React Server Components](/concepts/rsc) concepts
168+
- Learn about the [funstackStatic() Plugin API](/funstack-static/api/funstack-static) for configuration options
169+
- Understand [defer()](/funstack-static/api/defer) for Server Component chunk splitting
170+
- Dive into [React Server Components](/funstack-static/concepts/rsc) concepts
Lines changed: 51 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,92 @@
11
# defer()
22

3-
The `defer()` function enables deferred rendering for React Server Components, allowing content to be streamed progressively to the client.
3+
The `defer()` function enables deferred rendering for React Server Components, reducing initial data load.
4+
5+
You can think of this as React's `lazy` API but for Server Components.
46

57
## Import
68

79
```typescript
10+
// @funstack/static/server is where utilities for server components live
811
import { defer } from "@funstack/static/server";
912
```
1013

1114
## Usage
1215

1316
```tsx
1417
import { defer } from "@funstack/static/server";
15-
import { route } from "@funstack/router/server";
16-
import HeavyComponent from "./HeavyComponent";
18+
import { HeavyServerComponent } from "./HeavyServerComponent";
1719

18-
const routes = [
19-
route({
20-
path: "/",
21-
component: defer(HeavyComponent),
22-
}),
23-
];
24-
```
25-
26-
## Signature
27-
28-
```typescript
29-
function defer<T extends React.ComponentType<any>>(
30-
Component: T,
31-
): React.ReactNode;
20+
function Page() {
21+
return (
22+
<details>
23+
<summary>Very long description</summary>
24+
<Suspense fallback={<p>Loading...</p>}>
25+
{defer(HeavyServerComponent)}
26+
</Suspense>
27+
</details>
28+
);
29+
}
3230
```
3331

34-
### Parameters
32+
By using `defer()`, the `HeavyServerComponent` will still be rendered on the server (during build), but its data will be sent to the client as a separate RSC payload.
3533

36-
- **Component:** A React component to render with deferred streaming.
34+
This means that:
3735

38-
### Returns
36+
- Client can start rendering the rest of the page without waiting for `HeavyServerComponent`'s data
37+
- When the `defer(HeavyServerComponent)` part is rendered on the client, it will fetch the separate RSC payload and show the content.
3938

40-
A React node that will stream its content when rendered.
39+
The key point is that `HeavyServerComponent` is still a Server Component, so only the rendered HTML (and usage of Client Components inside it) is sent to the client, not the component code itself.
4140

42-
## When to Use defer()
41+
**Note:** you cannot pass any props to the component wrapped with `defer()`. This limitation may be lifted in the future.
4342

44-
Use `defer()` when you have components that:
45-
46-
- Fetch data asynchronously (e.g., from APIs or databases)
47-
- Perform expensive computations
48-
- Include large amounts of content
49-
- Have children that can be rendered independently
43+
**Note:** `defer()` must be used inside a `Suspense` boundary since the content will be streamed in later.
5044

51-
```tsx
52-
// Async component that fetches data
53-
async function BlogPosts() {
54-
const posts = await fetchPosts(); // Slow API call
55-
56-
return (
57-
<ul>
58-
{posts.map((post) => (
59-
<li key={post.id}>{post.title}</li>
60-
))}
61-
</ul>
62-
);
63-
}
45+
## Signature
6446

65-
// Wrap with defer() to stream
66-
route({
67-
path: "/blog",
68-
component: defer(BlogPosts),
69-
});
47+
```typescript
48+
export function defer(component: FC<{}>): React.ReactNode;
7049
```
7150

72-
## How It Works
51+
### Parameters
7352

74-
1. **Without defer():** The entire page waits for all components to render before sending any HTML.
53+
- **component:** A server component to render with deferred loading.
7554

76-
2. **With defer():**
77-
- The page shell renders immediately
78-
- A placeholder is inserted for the deferred content
79-
- The deferred content streams in once ready
80-
- The placeholder is replaced with the actual content
55+
### Returns
8156

82-
## Example: Mixing Static and Deferred Content
57+
A React Node that will stream its content separately from the main entry point.
8358

84-
```tsx
85-
import { defer } from "@funstack/static/server";
86-
87-
// Fast, static header
88-
function Header() {
89-
return (
90-
<header>
91-
<h1>My Blog</h1>
92-
</header>
93-
);
94-
}
95-
96-
// Slow, data-fetching component
97-
async function RecentPosts() {
98-
const posts = await fetchRecentPosts();
99-
return <PostList posts={posts} />;
100-
}
59+
## When to Use defer()
10160

102-
// Page component
103-
function BlogPage() {
104-
return (
105-
<div>
106-
<Header /> {/* Renders immediately */}
107-
{defer(RecentPosts)} {/* Streams when ready */}
108-
</div>
109-
);
110-
}
111-
```
61+
Use `defer()` when you have components that:
11262

113-
## MDX Integration
63+
- Renders large HTML content
64+
- Is not immediately visible on page load (e.g., inside a collapsed section)
11465

115-
`defer()` works seamlessly with MDX files:
66+
Typically, you will want to wrap route components with `defer()` to improve initial load performance. Otherwise, user needs to wait for contents for all pages to arrive before seeing anything.
11667

11768
```tsx
11869
import { defer } from "@funstack/static/server";
119-
import BlogPost from "./BlogPost.mdx";
70+
import HomePage from "./HomePage";
71+
import AboutPage from "./AboutPage";
12072

121-
route({
122-
path: "/blog/post",
123-
component: defer(BlogPost),
124-
});
73+
const routes = [
74+
route({
75+
path: "/",
76+
component: defer(HomePage),
77+
}),
78+
route({
79+
path: "/about",
80+
component: defer(AboutPage),
81+
}),
82+
// ...
83+
];
12584
```
12685

127-
## Best Practices
86+
## How It Works
12887

129-
1. **Defer at the route level** for pages with async data fetching
130-
2. **Don't over-defer** - only use it when you have genuinely slow components
131-
3. **Consider user experience** - streaming can cause layout shifts; design accordingly
132-
4. **Test without defer** first to understand baseline performance
88+
By default, FUNSTACK Static puts the entire app (`<App />`) into one RSC payload (`/.funstack/index.rsc`). The client fetches this payload to render your SPA.
13389

134-
## See Also
90+
When you use `defer(Component)`, FUNSTACK Static creates **additional RSC payloads** for the rendering result of `<Component />`. This results in an additional emit of RSC payload files like `/.funstack/rsc/fun:rsc-payload/b5698be72eea3c37`.
13591

136-
- [funstackStatic()](/api/funstack-static) - Main plugin configuration
137-
- [React Server Components](/concepts/rsc) - Understanding async components
92+
In the main RSC payload, the `defer` call is replaced with a client component `<ClientWrapper moduleId="fun:rsc-payload/b5698be72eea3c37" />`. This component is responsible for fetching the additional RSC payload from client and renders it when it's ready.

packages/docs/src/pages/api/FunstackStatic.mdx

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ The `funstackStatic()` function is the main Vite plugin that enables React Serve
55
## Import
66

77
```typescript
8-
import { funstackStatic } from "@funstack/static";
8+
import funstackStatic from "@funstack/static";
99
```
1010

1111
## Usage
1212

1313
```typescript
1414
// vite.config.ts
15-
import { funstackStatic } from "@funstack/static";
15+
import funstackStatic from "@funstack/static";
1616
import { defineConfig } from "vite";
1717

1818
export default defineConfig({
@@ -61,7 +61,7 @@ export default function Root({ children }: { children: React.ReactNode }) {
6161

6262
**Type:** `string`
6363

64-
Path to the app component file. This component defines your application's routes and content.
64+
Path to the app component file. This component defines your application's content.
6565

6666
```typescript
6767
funstackStatic({
@@ -70,23 +70,21 @@ funstackStatic({
7070
});
7171
```
7272

73-
The app component typically uses the Router to define routes:
74-
7573
```tsx
7674
// src/App.tsx
77-
import { Router } from "@funstack/router";
78-
import { route } from "@funstack/router/server";
79-
80-
const routes = [
81-
route({ path: "/", component: <HomePage /> }),
82-
route({ path: "/about", component: <AboutPage /> }),
83-
];
8475

8576
export default function App() {
86-
return <Router routes={routes} />;
77+
return (
78+
<div>
79+
<h1>Welcome to My Site</h1>
80+
{/* Your fantastic application goes here */}
81+
</div>
82+
);
8783
}
8884
```
8985

86+
**Note:** if your app has multiple pages, you can use a routing library here just like in a traditional SPA.
87+
9088
### publicOutDir (optional)
9189

9290
**Type:** `string`
@@ -120,18 +118,16 @@ export default defineConfig({
120118
});
121119
```
122120

123-
## How It Works
121+
## Vite Commands
124122

125-
1. **Development:** The plugin starts a development server with hot module replacement. Server Components run on-demand, and Client Components hot-reload instantly.
123+
You can use the same Vite commands you would use in a normal Vite project:
126124

127-
2. **Build:** During production build, the plugin:
128-
- Discovers all routes defined in your app
129-
- Pre-renders each route using React Server Components
130-
- Bundles Client Components for hydration
131-
- Outputs static files to `publicOutDir` that hydrate into a full SPA
125+
- `vite dev` - Starts the development server
126+
- `vite build` - Builds the static files
127+
- `vite preview` - Previews the built static files locally
132128

133129
## See Also
134130

135-
- [Getting Started](/getting-started) - Quick start guide
136-
- [defer()](/api/defer) - Deferred rendering for streaming
137-
- [React Server Components](/concepts/rsc) - Understanding RSC
131+
- [Getting Started](/funstack-static/getting-started) - Quick start guide
132+
- [defer()](/funstack-static/api/defer) - Deferred rendering for streaming
133+
- [React Server Components](/funstack-static/concepts/rsc) - Understanding RSC

0 commit comments

Comments
 (0)