Skip to content

Commit db8e612

Browse files
committed
fix: make button docs more visible, multi-page docs
1 parent 22ad585 commit db8e612

File tree

3 files changed

+172
-50
lines changed

3 files changed

+172
-50
lines changed

docs/pages/guides/create-frame.mdx

+15-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ description: "Frames.js is the react based framework for making frames. Debugger
88
This guide shows you how to add frames rendering to your next.js + tailwind app using frames.js.
99

1010
## Steps
11+
1112
::::steps
13+
1214
### Create a new repo
1315

1416
Create a new Next.js app
@@ -24,7 +26,6 @@ Add `frames.js` to your project
2426
yarn add frames.js
2527
```
2628

27-
2829
### Create your Frames app
2930

3031
```tsx [./app/frames/frames.ts]
@@ -34,6 +35,7 @@ export const frames = createFrames();
3435
```
3536

3637
### Create a route
38+
3739
```tsx [./app/frames/route.tsx]
3840
/* eslint-disable react/jsx-key */
3941
import { Button } from "frames.js/next";
@@ -49,10 +51,10 @@ const handleRequest = frames(async (ctx) => {
4951
</span>
5052
),
5153
buttons: [
52-
<Button action="post" target={{ query: { value: "Yes" }}}>
54+
<Button action="post" target={{ query: { value: "Yes" } }}>
5355
Say Yes
5456
</Button>,
55-
<Button action="post" target={{ query: { value: "No" }}}>
57+
<Button action="post" target={{ query: { value: "No" } }}>
5658
Say No
5759
</Button>,
5860
],
@@ -73,7 +75,12 @@ export async function generateMetadata() {
7375
title: "My Page",
7476
// provide a full URL to your /frames endpoint
7577
other: await fetchMetadata(
76-
new URL("/frames", process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000")
78+
new URL(
79+
"/frames",
80+
process.env.VERCEL_URL
81+
? `https://${process.env.VERCEL_URL}`
82+
: "http://localhost:3000"
83+
)
7784
),
7885
};
7986
}
@@ -88,3 +95,7 @@ export default function Page() {
8895
### Done! 🎉
8996

9097
::::
98+
99+
## Next Steps
100+
101+
- Read the [`createFrames`](/reference/core/createFrames) and [`Button`](/reference/core/Button) documentation

docs/pages/guides/multiple-frames.mdx

+143-42
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,168 @@ description: ""
55

66
# Multi-Page Frames
77

8-
You will want to connect multiple frames together.
9-
There's two different ways of navigating between frames.
8+
Frames.js can be used to create multi-page applications by defining multiple Frames that are linked together.
109

11-
The first way is by defining the `state` prop of a `Button`, and using that state to return a different Frame in the handler. See below
10+
## Creating a Multi-Page Application
1211

13-
```tsx
14-
/* eslint-disable react/jsx-key */
15-
import { createFrames, Button } from "frames.js/next";
12+
Frames are connected by [`Button`](/reference/core/Button) targets, similar to how Next.js `Link` components work.
13+
14+
:::steps
15+
16+
### Create your frames app
17+
18+
We create a new directory `./frames` with a `frames.ts` file to export our frames application from because it needs to be used from multiple routes.
1619

17-
const totalPages = 5;
20+
```tsx [frames.ts]
21+
import { createFrames } from "frames.js/next";
1822

19-
const frames = createFrames({
20-
basePath: "/examples/new-api/frames",
21-
initialState: {
22-
pageIndex: 0,
23-
},
23+
export const frames = createFrames({
24+
basePath: "/frames",
2425
});
26+
```
27+
28+
### Define your initial route
2529

26-
const handleRequest = frames(async (ctx) => {
27-
const pageIndex = Number(ctx.searchParams.pageIndex || 0);
30+
The first frame is always fetched via a GET request and is typically included alongside existing OpenGraph data via the [`generateMetadata`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata) function in Next.js if you have an existing site.
2831

29-
const imageUrl = `https://picsum.photos/seed/frames.js-${pageIndex}/300/200`;
32+
#### Define the initial frame
3033

34+
Create a `./frames/route.tsx` file that contains your initial frame. This frame will include buttons to navigate to other frames.
35+
36+
```tsx [route.tsx]
37+
/* eslint-disable react/jsx-key */
38+
import { frames } from "./frames";
39+
import { Button } from "frames.js/next";
40+
41+
export const GET = frames(async () => {
3142
return {
32-
image: (
33-
<div tw="flex flex-col">
34-
<img width={300} height={200} src={imageUrl} alt="Image" />
35-
<div tw="flex">
36-
This is slide {pageIndex + 1} / {totalPages}
37-
</div>
38-
</div>
39-
),
43+
image: <div tw="flex">Welcome</div>,
4044
buttons: [
45+
// With query params
4146
<Button
4247
action="post"
43-
target={{
44-
query: { pageIndex: (pageIndex - 1) % totalPages },
45-
}}
48+
target={{ pathname: "/frames/route1", query: { foo: "bar" } }}
4649
>
47-
50+
Go to route 1
4851
</Button>,
49-
<Button
50-
action="post"
51-
target={{
52-
query: { pageIndex: (pageIndex + 1) % totalPages },
53-
}}
54-
>
55-
52+
// Without query params
53+
<Button action="post" target="/frames/route2">
54+
Go to route 2
5655
</Button>,
5756
],
58-
textInput: "Type something!",
5957
};
6058
});
59+
```
60+
61+
#### Export the initial frame metadata
62+
63+
In your `page.tsx` file, fetch the initial frame's metadata and include it alongside your existing page's metadata.
6164

62-
export const GET = handleRequest;
63-
export const POST = handleRequest;
65+
`fetchMetadata` is a helper function that fetches the metadata for a frame from the frames.js handler and formats it for use in the `generateMetadata` function.
66+
67+
```tsx [page.tsx]
68+
import { fetchMetadata } from "frames.js/next";
69+
70+
export async function generateMetadata() {
71+
return {
72+
title: "My Page",
73+
// provide a full URL to your /frames endpoint
74+
other: await fetchMetadata(
75+
new URL(
76+
"/frames",
77+
process.env.VERCEL_URL
78+
? `https://${process.env.VERCEL_URL}`
79+
: "http://localhost:3000"
80+
)
81+
),
82+
};
83+
}
84+
85+
export default function Page() {
86+
return <span>My existing page</span>;
87+
}
6488
```
6589

66-
The second way to navigate between frames is by defining a `Button` with `type`, `post`, with a `target` that points at another Frame.
67-
This can be a Frame on the same domain, or a Frame on another website entirely. In order to link between Frames in the same project, you need to set up a frames.js handler on the `POST` route of the path defined in the target.
90+
### Create the other routes
91+
92+
Create additional frames in the `./frames` directory.
93+
94+
#### Route 1
95+
96+
Create a directory `./frames/route1/route.tsx` with a `POST` handler that returns the frame content.
97+
98+
```tsx [route1.tsx]
99+
/* eslint-disable react/jsx-key */
100+
import { frames } from "../frames";
101+
import { Button } from "frames.js/next";
102+
103+
export const POST = frames(async (ctx) => {
104+
const foo = ctx.searchParams.foo;
105+
106+
return {
107+
image: <div tw="flex">Route 1 foo: {foo}</div>, // foo: bar
108+
buttons: [
109+
<Button action="post" target="/frames/route2">
110+
Go to route 2
111+
</Button>,
112+
],
113+
};
114+
});
115+
```
116+
117+
#### Route 2
118+
119+
Create a directory `./frames/route2/route.tsx` with a `POST` handler that returns the frame content.
120+
121+
```tsx [route2.tsx]
122+
/* eslint-disable react/jsx-key */
123+
import { frames } from "../frames";
124+
import { Button } from "frames.js/next";
125+
126+
export const POST = frames(async () => {
127+
return {
128+
image: <div tw="flex">Route 2</div>,
129+
buttons: [
130+
<Button action="post" target="/frames/route1">
131+
Go to route 1
132+
</Button>,
133+
],
134+
};
135+
});
136+
```
137+
138+
### (Optional) Navigate back to the initial frame
68139

69-
{/*
70-
TODO: Link to examples
71-
*/}
140+
If you want to navigate back to the initial frame you need to export a `POST` handler for the initial route. You may want to refactor the initial frame handler into a `frameHandler` variable that is exported as both `GET` and `POST`
141+
142+
```tsx [route.tsx]
143+
import { frames } from "./frames";
144+
145+
const frameHandler = frames(async () => {
146+
return {
147+
image: <div tw="flex">Welcome</div>
148+
buttons: [
149+
<Button action="post" target="/frames/route1">Go to route 1</Button>,
150+
<Button action="post" target="/frames/route2">Go to route 2</Button>,
151+
],
152+
};
153+
});
154+
155+
export const GET = frameHandler;
156+
export const POST = frameHandler;
157+
```
158+
159+
You can then navigate back to the initial frame by linking to the initial route.
160+
161+
```tsx
162+
<Button action="post" target="/frames">
163+
Go back
164+
</Button>
165+
```
166+
167+
:::
168+
169+
## Notes
170+
171+
The second way to navigate between frames is by defining a [`Button`](/reference/core/Button) with `type`, `post`, with a `target` that points at another Frame.
172+
This can be a Frame on the same domain, or a Frame on another website entirely. In order to link between Frames in the same project, you need to set up a frames.js handler on the `POST` route of the path defined in the target.

docs/pages/reference/core/Button.mdx

+14-4
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,22 @@ This button sends a request to a URL on which it was rendered. If you want to na
2020

2121
The `target` path will be resolved relatively to current URL.
2222

23-
### Passing state when button is clicked using query parameters
23+
### Passing state between frames
2424

2525
```tsx
26-
<Button action="post" target={{ query: { foo: "bar" }, pathname: "/next-route"}}>
26+
<Button
27+
action="post"
28+
target={{ query: { foo: "bar" }, pathname: "/next-route" }}
29+
>
2730
Click me
2831
</Button>
2932
```
3033

31-
The state will be available in handler `ctx.pressedButton.state`.
34+
The state will be available in the frame handler via `ctx.searchParams` e.g.
35+
36+
```ts
37+
ctx.searchParams.foo; // bar
38+
```
3239

3340
## Post Redirect Button
3441

@@ -39,7 +46,10 @@ It accepts same props as `post` button.
3946
```tsx
4047
import { Button } from "frames.js/core";
4148

42-
<Button action="post_redirect" target={{ query: { foo: "bar" }, pathname: "/next-route"}}>
49+
<Button
50+
action="post_redirect"
51+
target={{ query: { foo: "bar" }, pathname: "/next-route" }}
52+
>
4353
Click me
4454
</Button>;
4555
```

0 commit comments

Comments
 (0)