Skip to content

Commit

Permalink
feat: update starter frame with counter + state example
Browse files Browse the repository at this point in the history
  • Loading branch information
stephancill committed Mar 28, 2024
1 parent 3875369 commit 0c525ae
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 86 deletions.
5 changes: 5 additions & 0 deletions .changeset/tidy-cheetahs-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"framesjs-starter": patch
---

feat: update starter frame to use the new api
6 changes: 6 additions & 0 deletions examples/framesjs-starter/app/frames/frames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createFrames } from "frames.js/next";

export const frames = createFrames({
basePath: "/frames",
initialState: { counter: 0 },
});
1 change: 0 additions & 1 deletion examples/framesjs-starter/app/frames/route.ts

This file was deleted.

32 changes: 32 additions & 0 deletions examples/framesjs-starter/app/frames/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable react/jsx-key */
import { Button } from "frames.js/next";
import { frames } from "./frames";

const frameHandler = frames(async (ctx) => {
const counter = ctx.message ? ctx.searchParams.op === "+" ? ctx.state.counter + 1 : ctx.state.counter - 1 : ctx.state.counter

return {
image: <div tw="flex flex-col">
<div tw="flex">frames.js starter</div>
{ctx.message?.inputText && <div tw="flex">
{`Input: ${ctx.message.inputText}`}
</div>}
<div tw="flex">Counter {counter}</div></div>,
textInput: "Say something",
buttons: [
<Button action="post" target={{pathname: "/", query: {op: "+"}}}>
Increment
</Button>,
<Button action="post" target={{pathname: "/", query: {op: "-"}}}>
Decrement
</Button >,
<Button action="link" target={`https://www.google.com`}>
External
</Button>
],
state: { counter: counter}
}
})

export const GET = frameHandler;
export const POST = frameHandler;
102 changes: 17 additions & 85 deletions examples/framesjs-starter/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,37 @@
import {
FrameButton,
FrameContainer,
FrameImage,
FrameInput,
FrameReducer,
NextServerPageProps,
getFrameMessage,
getPreviousFrame,
useFramesReducer,
NextServerPageProps
} from "frames.js/next/server";
import Link from "next/link";
import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "./debug";
import { currentURL } from "./utils";

type State = {
active: string;
total_button_presses: number;
};

const initialState = { active: "1", total_button_presses: 0 };
import { fetchMetadata } from "frames.js/next";
import type { Metadata } from "next";
import { createDebugUrl } from "./debug";
import { vercelURL } from "./utils";

const reducer: FrameReducer<State> = (state, action) => {
export async function generateMetadata(): Promise<Metadata> {
return {
total_button_presses: state.total_button_presses + 1,
active: action.postBody?.untrustedData.buttonIndex
? String(action.postBody?.untrustedData.buttonIndex)
: "1",
title: "frames.js starter",
description: "This is a frames.js starter template",
other: {
...(await fetchMetadata(
new URL(
"/frames",
vercelURL() || "http://localhost:3000"
)
)),
},
};
};
}

// This is a react server component only
export default async function Home({ searchParams }: NextServerPageProps) {
const url = currentURL("/");
const previousFrame = getPreviousFrame<State>(searchParams);

const frameMessage = await getFrameMessage(previousFrame.postBody, {
hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL,
});

if (frameMessage && !frameMessage?.isValid) {
throw new Error("Invalid frame payload");
}

const [state, dispatch] = useFramesReducer<State>(
reducer,
initialState,
previousFrame
);

// Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want.
// example: load the users credentials & check they have an NFT

console.log("info: state is:", state);

// then, when done, return next frame
return (
Expand All @@ -65,54 +45,6 @@ export default async function Home({ searchParams }: NextServerPageProps) {
<Link href="/examples" className="underline">
other examples
</Link>
<FrameContainer
postUrl="/frames"
pathname="/"
state={state}
previousFrame={previousFrame}
>
{/* <FrameImage src="https://framesjs.org/og.png" /> */}
<FrameImage aspectRatio="1.91:1">
<div tw="w-full h-full bg-slate-700 text-white justify-center items-center flex flex-col">
<div tw="flex flex-row">
{frameMessage?.inputText ? frameMessage.inputText : "Hello world"}
</div>
{frameMessage && (
<div tw="flex flex-col">
<div tw="flex">
Requester is @{frameMessage.requesterUserData?.username}{" "}
</div>
<div tw="flex">
Requester follows caster:{" "}
{frameMessage.requesterFollowsCaster ? "true" : "false"}
</div>
<div tw="flex">
Caster follows requester:{" "}
{frameMessage.casterFollowsRequester ? "true" : "false"}
</div>
<div tw="flex">
Requester liked cast:{" "}
{frameMessage.likedCast ? "true" : "false"}
</div>
<div tw="flex">
Requester recasted cast:{" "}
{frameMessage.recastedCast ? "true" : "false"}
</div>
</div>
)}
</div>
</FrameImage>
<FrameInput text="put some text here" />
<FrameButton>
{state?.active === "1" ? "Active" : "Inactive"}
</FrameButton>
<FrameButton>
{state?.active === "2" ? "Active" : "Inactive"}
</FrameButton>
<FrameButton action="link" target={`https://www.google.com`}>
External
</FrameButton>
</FrameContainer>
</div>
);
}

0 comments on commit 0c525ae

Please sign in to comment.