Skip to content

Commit 7dcf3f5

Browse files
committed
feat: update starter frame with counter + state example
1 parent 3875369 commit 7dcf3f5

File tree

5 files changed

+59
-86
lines changed

5 files changed

+59
-86
lines changed

.changeset/tidy-cheetahs-cover.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"framesjs-starter": patch
3+
---
4+
5+
feat: update starter frame to use the new api
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createFrames } from "frames.js/next";
2+
3+
export const frames = createFrames({
4+
basePath: "/frames",
5+
initialState: { totalButtonPresses: 0 },
6+
});

examples/framesjs-starter/app/frames/route.ts

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* eslint-disable react/jsx-key */
2+
import { Button } from "frames.js/next";
3+
import { frames } from "./frames";
4+
5+
const frameHandler = frames(async (ctx) => {
6+
const counter = ctx.message ? ctx.searchParams.op === "+" ? ctx.state.totalButtonPresses + 1 : ctx.state.totalButtonPresses - 1 : ctx.state.totalButtonPresses
7+
8+
return {
9+
image: <div tw="flex flex-col">
10+
{ctx.message?.inputText && <div tw="flex">
11+
{`Input: ${ctx.message.inputText}`}
12+
</div>}
13+
<div tw="flex">Counter {counter}</div></div>,
14+
textInput: "Say something",
15+
buttons: [
16+
<Button action="post" target={{pathname: "/", query: {op: "+"}}}>
17+
Increment
18+
</Button>,
19+
<Button action="post" target={{pathname: "/", query: {op: "-"}}}>
20+
Decrement
21+
</Button >,
22+
<Button action="link" target={`https://www.google.com`}>
23+
External
24+
</Button>
25+
],
26+
state: { totalButtonPresses: counter}
27+
}
28+
})
29+
30+
export const GET = frameHandler;
31+
export const POST = frameHandler;
+17-85
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,37 @@
11
import {
2-
FrameButton,
3-
FrameContainer,
4-
FrameImage,
5-
FrameInput,
6-
FrameReducer,
7-
NextServerPageProps,
8-
getFrameMessage,
9-
getPreviousFrame,
10-
useFramesReducer,
2+
NextServerPageProps
113
} from "frames.js/next/server";
124
import Link from "next/link";
13-
import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "./debug";
145
import { currentURL } from "./utils";
156

167
type State = {
178
active: string;
189
total_button_presses: number;
1910
};
2011

21-
const initialState = { active: "1", total_button_presses: 0 };
12+
import { fetchMetadata } from "frames.js/next";
13+
import type { Metadata } from "next";
14+
import { createDebugUrl } from "./debug";
15+
import { vercelURL } from "./utils";
2216

23-
const reducer: FrameReducer<State> = (state, action) => {
17+
export async function generateMetadata(): Promise<Metadata> {
2418
return {
25-
total_button_presses: state.total_button_presses + 1,
26-
active: action.postBody?.untrustedData.buttonIndex
27-
? String(action.postBody?.untrustedData.buttonIndex)
28-
: "1",
19+
title: "frames.js starter",
20+
description: "This is a frames.js starter template",
21+
other: {
22+
...(await fetchMetadata(
23+
new URL(
24+
"/frames",
25+
vercelURL() || "http://localhost:3000"
26+
)
27+
)),
28+
},
2929
};
30-
};
30+
}
3131

3232
// This is a react server component only
3333
export default async function Home({ searchParams }: NextServerPageProps) {
3434
const url = currentURL("/");
35-
const previousFrame = getPreviousFrame<State>(searchParams);
36-
37-
const frameMessage = await getFrameMessage(previousFrame.postBody, {
38-
hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL,
39-
});
40-
41-
if (frameMessage && !frameMessage?.isValid) {
42-
throw new Error("Invalid frame payload");
43-
}
44-
45-
const [state, dispatch] = useFramesReducer<State>(
46-
reducer,
47-
initialState,
48-
previousFrame
49-
);
50-
51-
// Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want.
52-
// example: load the users credentials & check they have an NFT
53-
54-
console.log("info: state is:", state);
5535

5636
// then, when done, return next frame
5737
return (
@@ -65,54 +45,6 @@ export default async function Home({ searchParams }: NextServerPageProps) {
6545
<Link href="/examples" className="underline">
6646
other examples
6747
</Link>
68-
<FrameContainer
69-
postUrl="/frames"
70-
pathname="/"
71-
state={state}
72-
previousFrame={previousFrame}
73-
>
74-
{/* <FrameImage src="https://framesjs.org/og.png" /> */}
75-
<FrameImage aspectRatio="1.91:1">
76-
<div tw="w-full h-full bg-slate-700 text-white justify-center items-center flex flex-col">
77-
<div tw="flex flex-row">
78-
{frameMessage?.inputText ? frameMessage.inputText : "Hello world"}
79-
</div>
80-
{frameMessage && (
81-
<div tw="flex flex-col">
82-
<div tw="flex">
83-
Requester is @{frameMessage.requesterUserData?.username}{" "}
84-
</div>
85-
<div tw="flex">
86-
Requester follows caster:{" "}
87-
{frameMessage.requesterFollowsCaster ? "true" : "false"}
88-
</div>
89-
<div tw="flex">
90-
Caster follows requester:{" "}
91-
{frameMessage.casterFollowsRequester ? "true" : "false"}
92-
</div>
93-
<div tw="flex">
94-
Requester liked cast:{" "}
95-
{frameMessage.likedCast ? "true" : "false"}
96-
</div>
97-
<div tw="flex">
98-
Requester recasted cast:{" "}
99-
{frameMessage.recastedCast ? "true" : "false"}
100-
</div>
101-
</div>
102-
)}
103-
</div>
104-
</FrameImage>
105-
<FrameInput text="put some text here" />
106-
<FrameButton>
107-
{state?.active === "1" ? "Active" : "Inactive"}
108-
</FrameButton>
109-
<FrameButton>
110-
{state?.active === "2" ? "Active" : "Inactive"}
111-
</FrameButton>
112-
<FrameButton action="link" target={`https://www.google.com`}>
113-
External
114-
</FrameButton>
115-
</FrameContainer>
11648
</div>
11749
);
11850
}

0 commit comments

Comments
 (0)