+
Error!
+
Server experienced an error processing your request.
+
+ ), {width: 600, height: 400})
+ }
+}
+`;
+ const imagesRoutePath = path.join(imagesDirPath, 'route.tsx');
+ fs.writeFileSync(imagesRoutePath, imagesRouteContent.trim());
+ console.log(`route.tsx created in ${imagesDirPath}`);
+
+ console.log(`🔲✅ fframe applet ${name} successfully generated ✅🔲\n`);
+}
+
+module.exports = { generateApplet };
diff --git a/bin/index.js b/bin/index.js
new file mode 100755
index 0000000..77deb4d
--- /dev/null
+++ b/bin/index.js
@@ -0,0 +1,35 @@
+#!/usr/bin/env node
+const fs = require('fs');
+const path = require('path');
+
+const { createProject } = require('./create-project');
+const { generateApplet } = require('./generate-applet');
+
+// manual argument parsing
+const args = process.argv.slice(2); // Remove node and script path
+
+let generateAppletFlag = false;
+let appletName = '';
+
+// loop through arguments
+for (let i = 0; i < args.length; i++) {
+ if (args[i] === '-g') {
+ if (!args[i + 1]) {
+ throw new Error('applet name is required');
+ }
+ generateAppletFlag = true;
+ appletName = args[i + 1];
+ // exit the loop if -g is found
+ break;
+ }
+}
+
+if (generateAppletFlag) {
+ // call generateApplet if -g is provided
+ console.log(`generating applet with name: ${appletName}`);
+ generateApplet(appletName);
+} else {
+ // default to createProject if no -g flag is found
+ console.log(`creating project with interactive cli`);
+ createProject();
+}
diff --git a/next.config.mjs b/next.config.mjs
new file mode 100644
index 0000000..4678774
--- /dev/null
+++ b/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e3b4568
--- /dev/null
+++ b/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "create-fframe-app",
+ "version": "1.0.0",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/fframes/create-fframe-app.git"
+ },
+ "license": "MIT",
+ "author": {
+ "name": "veganbeef",
+ "email": "veganbeef@protonmail.com",
+ "url": "https://github.com/veganbeef"
+ },
+ "keywords": ["farcaster", "frames", "nodejs", "node", "nextjs", "next", "typescript", "npx"],
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "lint:fix": "next lint --fix",
+ "generate-applet": "npx create-fframe-app -g"
+ },
+ "bin": {
+ "create-fframe-app": "bin/index.js"
+ },
+ "dependencies": {
+ "@coinbase/onchainkit": "^0.4.5",
+ "next": "14.1.0",
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "devDependencies": {
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "eslint": "^8",
+ "eslint-config-next": "14.1.0",
+ "typescript": "^5"
+ }
+}
diff --git a/src/app/api/example/constants.ts b/src/app/api/example/constants.ts
new file mode 100644
index 0000000..43c40e4
--- /dev/null
+++ b/src/app/api/example/constants.ts
@@ -0,0 +1,9 @@
+import { getBaseUrl } from '@/utils';
+
+
+export const EXAMPLE_APPLET_ID = 'example';
+export const EXAMPLE_APPLET_BASE_URL = `${getBaseUrl()}/api/${EXAMPLE_APPLET_ID}`;
+export enum FRAME_ID {
+ 'initial' = '0',
+ 'success' = '1',
+}
diff --git a/src/app/api/example/images/route.tsx b/src/app/api/example/images/route.tsx
new file mode 100644
index 0000000..52bd123
--- /dev/null
+++ b/src/app/api/example/images/route.tsx
@@ -0,0 +1,41 @@
+import { NextRequest } from 'next/server';
+import { FRAME_ID } from '@/app/api/example/constants';
+import { ImageResponse } from 'next/og';
+import { Property } from "csstype";
+
+
+const defaultStyles = {
+ display: 'flex',
+ flexDirection: 'column' as Property.FlexDirection,
+ backgroundColor: 'black',
+ width: '100%',
+ height: '100%',
+ padding: '20px',
+ justifyContent: 'center'
+};
+
+export async function GET(request: NextRequest): Promise