From 424b0eadd0de67572b495705c3aa83b261dd1b10 Mon Sep 17 00:00:00 2001
From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com>
Date: Thu, 4 Apr 2024 18:02:44 +0200
Subject: [PATCH 1/3] feat: cast actions support
---
.changeset/brown-walls-thank.md | 5 +++
.changeset/tasty-panthers-protect.md | 5 +++
docs/pages/guides/cast-actions.mdx | 12 +++++++
docs/vocs.config.tsx | 4 +++
.../new-api-cast-actions/frames/frames.ts | 5 +++
.../new-api-cast-actions/frames/route.tsx | 31 +++++++++++++++++
.../examples/new-api-cast-actions/page.tsx | 33 +++++++++++++++++++
.../examples/new-api-cast-actions/utils.ts | 30 +++++++++++++++++
packages/frames.js/src/core/types.ts | 2 +-
9 files changed, 126 insertions(+), 1 deletion(-)
create mode 100644 .changeset/brown-walls-thank.md
create mode 100644 .changeset/tasty-panthers-protect.md
create mode 100644 docs/pages/guides/cast-actions.mdx
create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts
create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx
create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx
create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts
diff --git a/.changeset/brown-walls-thank.md b/.changeset/brown-walls-thank.md
new file mode 100644
index 000000000..da0aae82c
--- /dev/null
+++ b/.changeset/brown-walls-thank.md
@@ -0,0 +1,5 @@
+---
+"frames.js": patch
+---
+
+feat: allow arbitrary response in frames handler
diff --git a/.changeset/tasty-panthers-protect.md b/.changeset/tasty-panthers-protect.md
new file mode 100644
index 000000000..ac915b809
--- /dev/null
+++ b/.changeset/tasty-panthers-protect.md
@@ -0,0 +1,5 @@
+---
+"framesjs-starter": patch
+---
+
+feat: cast actions example
diff --git a/docs/pages/guides/cast-actions.mdx b/docs/pages/guides/cast-actions.mdx
new file mode 100644
index 000000000..daebe0d2a
--- /dev/null
+++ b/docs/pages/guides/cast-actions.mdx
@@ -0,0 +1,12 @@
+---
+title: "Cast Actions"
+description: "A guide to demonstrate how to create cast actions with Frames.js"
+---
+
+# Cast Actions
+
+The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specifiction lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js.
+
+## Example
+
+[See the example on GitHub](https://github.com/framesjs/frames.js/tree/main/examples/framesjs-starter/app/examples/new-api-cast-actions)
diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx
index 404777612..7f03651c6 100644
--- a/docs/vocs.config.tsx
+++ b/docs/vocs.config.tsx
@@ -58,6 +58,10 @@ const sidebar = [
text: "Open Frames",
link: "/guides/open-frames",
},
+ {
+ text: "Cast Actions",
+ link: "/guides/cast-actions",
+ },
],
},
{
diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts
new file mode 100644
index 000000000..1ccb72618
--- /dev/null
+++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts
@@ -0,0 +1,5 @@
+import { createFrames } from "frames.js/next";
+
+export const frames = createFrames({
+ basePath: "/examples/new-api-cast-actions/frames",
+});
diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx
new file mode 100644
index 000000000..9db3008b3
--- /dev/null
+++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx
@@ -0,0 +1,31 @@
+/* eslint-disable react/jsx-key */
+import { Button } from "frames.js/next";
+import { frames } from "./frames";
+import { constructCastActionUrl } from "../utils";
+
+export const GET = frames(async (ctx) => {
+ const currentUrl = new URL(ctx.url.toString());
+ currentUrl.pathname = "/examples/new-api-cast-actions/frames";
+
+ const installActionUrl = constructCastActionUrl({
+ actionType: "post",
+ icon: "number",
+ name: "Check FID",
+ postUrl: currentUrl.toString(),
+ });
+
+ return {
+ image:
FID Action
,
+ buttons: [
+ ,
+ ],
+ };
+});
+
+export const POST = frames(async (ctx) => {
+ return Response.json({
+ message: `The user's FID is ${ctx.message?.castId?.fid}`,
+ });
+});
diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx b/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx
new file mode 100644
index 000000000..82f4048b0
--- /dev/null
+++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx
@@ -0,0 +1,33 @@
+import Link from "next/link";
+import { currentURL, vercelURL } from "../../utils";
+import { createDebugUrl } from "../../debug";
+import type { Metadata } from "next";
+import { fetchMetadata } from "frames.js/next";
+
+export async function generateMetadata(): Promise {
+ return {
+ title: "New api example",
+ description: "This is a new api example",
+ other: {
+ ...(await fetchMetadata(
+ new URL(
+ "/examples/new-api-cast-actions/frames",
+ vercelURL() || "http://localhost:3000"
+ )
+ )),
+ },
+ };
+}
+
+export default async function Home() {
+ const url = currentURL("/examples/new-api-cast-actions");
+
+ return (
+
+ New api cast actions example.{" "}
+
+ Debug
+
+
+ );
+}
diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts b/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts
new file mode 100644
index 000000000..2bba8d0f4
--- /dev/null
+++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts
@@ -0,0 +1,30 @@
+type CastActionParams = {
+ /** The action name. Must be less than 30 characters. */
+ name: string;
+ /** An [Octicons](https://primer.style/foundations/icons) icon name. */
+ icon: string;
+ /** The action type. (Same type options as frame buttons). Only post is accepted in V1. */
+ actionType: "post";
+ postUrl: string;
+};
+export function constructCastActionUrl(params: CastActionParams): string {
+ // Validate the input parameters
+ if (params.name.length > 30) {
+ throw new Error("The action name must be less than 30 characters.");
+ }
+
+ if (params.actionType.toLowerCase() !== "post") {
+ throw new Error('The action type must be "post" in V1.');
+ }
+
+ // Construct the URL
+ const baseUrl = "https://warpcast.com/~/add-cast-action";
+ const urlParams = new URLSearchParams({
+ name: params.name,
+ icon: params.icon,
+ actionType: params.actionType,
+ postUrl: params.postUrl,
+ });
+
+ return `${baseUrl}?${urlParams.toString()}`;
+}
diff --git a/packages/frames.js/src/core/types.ts b/packages/frames.js/src/core/types.ts
index 9d4b22e3f..b4c97a026 100644
--- a/packages/frames.js/src/core/types.ts
+++ b/packages/frames.js/src/core/types.ts
@@ -110,7 +110,7 @@ export type FrameRedirect = {
export type FramesHandlerFunctionReturnType<
TState extends JsonValue | undefined,
-> = FrameDefinition | FrameRedirect;
+> = FrameDefinition | FrameRedirect | Response;
type FramesMiddlewareNextFunction<
TState extends JsonValue | undefined,
From b026ebced1fda97c755527bf0591f532f5339368 Mon Sep 17 00:00:00 2001
From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com>
Date: Fri, 5 Apr 2024 09:04:39 +0200
Subject: [PATCH 2/3] Update docs/pages/guides/cast-actions.mdx
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Michal Kvasničák
---
docs/pages/guides/cast-actions.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/pages/guides/cast-actions.mdx b/docs/pages/guides/cast-actions.mdx
index daebe0d2a..f561fe227 100644
--- a/docs/pages/guides/cast-actions.mdx
+++ b/docs/pages/guides/cast-actions.mdx
@@ -5,7 +5,7 @@ description: "A guide to demonstrate how to create cast actions with Frames.js"
# Cast Actions
-The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specifiction lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js.
+The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specification lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js.
## Example
From 9962b8301d3f4e097b350aa49047c796b881ff3c Mon Sep 17 00:00:00 2001
From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com>
Date: Fri, 5 Apr 2024 11:47:21 +0200
Subject: [PATCH 3/3] fix: changeset minor
---
.changeset/brown-walls-thank.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/brown-walls-thank.md b/.changeset/brown-walls-thank.md
index da0aae82c..e71364dd9 100644
--- a/.changeset/brown-walls-thank.md
+++ b/.changeset/brown-walls-thank.md
@@ -1,5 +1,5 @@
---
-"frames.js": patch
+"frames.js": minor
---
feat: allow arbitrary response in frames handler