create-puck-app 0.22.0-canary.f4f83ac1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/index.js +0 -4
  2. package/package.json +2 -2
  3. package/templates/next-ai/package.json.hbs +2 -2
  4. package/templates/react-router-ai/package.json.hbs +2 -2
  5. package/templates/gitignore +0 -8
  6. package/templates/next/.eslintrc.js +0 -4
  7. package/templates/next/README.md +0 -38
  8. package/templates/next/app/[...puckPath]/client.tsx +0 -9
  9. package/templates/next/app/[...puckPath]/page.tsx +0 -49
  10. package/templates/next/app/favicon.ico +0 -0
  11. package/templates/next/app/layout.tsx +0 -13
  12. package/templates/next/app/page.tsx +0 -1
  13. package/templates/next/app/puck/[...puckPath]/client.tsx +0 -20
  14. package/templates/next/app/puck/[...puckPath]/page.tsx +0 -44
  15. package/templates/next/app/puck/api/route.ts +0 -25
  16. package/templates/next/app/puck/page.tsx +0 -3
  17. package/templates/next/app/styles.css +0 -3
  18. package/templates/next/database.json +0 -1
  19. package/templates/next/gitignore +0 -34
  20. package/templates/next/lib/get-page.ts +0 -11
  21. package/templates/next/next-env.d.ts +0 -6
  22. package/templates/next/next.config.js +0 -3
  23. package/templates/next/proxy.ts +0 -27
  24. package/templates/next/puck.config.tsx +0 -25
  25. package/templates/next/tsconfig/base.json +0 -20
  26. package/templates/next/tsconfig/nextjs.json +0 -21
  27. package/templates/next/tsconfig.json +0 -8
  28. package/templates/next-ai/.env.example +0 -2
  29. package/templates/next-ai/.eslintrc.js +0 -4
  30. package/templates/next-ai/README.md +0 -60
  31. package/templates/next-ai/app/[...puckPath]/client.tsx +0 -9
  32. package/templates/next-ai/app/[...puckPath]/page.tsx +0 -49
  33. package/templates/next-ai/app/api/pages/route.ts +0 -26
  34. package/templates/next-ai/app/api/puck/[...all]/route.ts +0 -13
  35. package/templates/next-ai/app/layout.tsx +0 -13
  36. package/templates/next-ai/app/page.tsx +0 -1
  37. package/templates/next-ai/app/puck/[...puckPath]/client.tsx +0 -25
  38. package/templates/next-ai/app/puck/[...puckPath]/page.tsx +0 -45
  39. package/templates/next-ai/app/puck/page.tsx +0 -3
  40. package/templates/next-ai/app/styles.css +0 -3
  41. package/templates/next-ai/database.json +0 -1
  42. package/templates/next-ai/gitignore +0 -34
  43. package/templates/next-ai/lib/get-page.ts +0 -11
  44. package/templates/next-ai/next-env.d.ts +0 -6
  45. package/templates/next-ai/next.config.js +0 -3
  46. package/templates/next-ai/proxy.ts +0 -27
  47. package/templates/next-ai/public/favicon.ico +0 -0
  48. package/templates/next-ai/puck.config.tsx +0 -25
  49. package/templates/next-ai/tsconfig/base.json +0 -20
  50. package/templates/next-ai/tsconfig/nextjs.json +0 -21
  51. package/templates/next-ai/tsconfig.json +0 -8
  52. package/templates/react-router/README.md +0 -35
  53. package/templates/react-router/app/components/puck-render.tsx +0 -8
  54. package/templates/react-router/app/lib/pages.server.ts +0 -29
  55. package/templates/react-router/app/lib/resolve-puck-path.server.ts +0 -19
  56. package/templates/react-router/app/root.tsx +0 -65
  57. package/templates/react-router/app/routes/_index.tsx +0 -31
  58. package/templates/react-router/app/routes/puck-splat.tsx +0 -95
  59. package/templates/react-router/app/routes.ts +0 -7
  60. package/templates/react-router/database.json +0 -1
  61. package/templates/react-router/gitignore +0 -6
  62. package/templates/react-router/public/favicon.ico +0 -0
  63. package/templates/react-router/puck.config.tsx +0 -23
  64. package/templates/react-router/react-router.config.ts +0 -7
  65. package/templates/react-router/vite.config.ts +0 -7
  66. package/templates/react-router-ai/.env.example +0 -2
  67. package/templates/react-router-ai/README.md +0 -57
  68. package/templates/react-router-ai/app/components/puck-render.tsx +0 -8
  69. package/templates/react-router-ai/app/lib/pages.server.ts +0 -29
  70. package/templates/react-router-ai/app/lib/resolve-puck-path.server.ts +0 -19
  71. package/templates/react-router-ai/app/root.tsx +0 -65
  72. package/templates/react-router-ai/app/routes/_index.tsx +0 -31
  73. package/templates/react-router-ai/app/routes/api.puck.ts +0 -13
  74. package/templates/react-router-ai/app/routes/puck-splat.tsx +0 -101
  75. package/templates/react-router-ai/app/routes.ts +0 -8
  76. package/templates/react-router-ai/database.json +0 -1
  77. package/templates/react-router-ai/gitignore +0 -6
  78. package/templates/react-router-ai/public/favicon.ico +0 -0
  79. package/templates/react-router-ai/puck.config.tsx +0 -23
  80. package/templates/react-router-ai/react-router.config.ts +0 -7
  81. package/templates/react-router-ai/vite.config.ts +0 -7
  82. package/templates/remix/.eslintrc.cjs +0 -4
  83. package/templates/remix/README.md +0 -42
  84. package/templates/remix/app/entry.client.tsx +0 -18
  85. package/templates/remix/app/entry.server.tsx +0 -137
  86. package/templates/remix/app/models/page.server.ts +0 -27
  87. package/templates/remix/app/puck.config.tsx +0 -25
  88. package/templates/remix/app/root.tsx +0 -36
  89. package/templates/remix/app/routes/$puckPath.tsx +0 -2
  90. package/templates/remix/app/routes/$puckPath_.edit.tsx +0 -5
  91. package/templates/remix/app/routes/_index.tsx +0 -34
  92. package/templates/remix/app/routes/edit.tsx +0 -64
  93. package/templates/remix/app/styles/shared.css +0 -3
  94. package/templates/remix/database.json +0 -1
  95. package/templates/remix/gitignore +0 -6
  96. package/templates/remix/package.json.hbs +0 -35
  97. package/templates/remix/public/favicon.ico +0 -0
  98. package/templates/remix/remix.config.js +0 -12
  99. package/templates/remix/remix.env.d.ts +0 -2
  100. package/templates/remix/tsconfig.json +0 -22
  101. package/templates/remix-ai/.env.example +0 -2
  102. package/templates/remix-ai/.eslintrc.cjs +0 -4
  103. package/templates/remix-ai/README.md +0 -64
  104. package/templates/remix-ai/app/entry.client.tsx +0 -18
  105. package/templates/remix-ai/app/entry.server.tsx +0 -137
  106. package/templates/remix-ai/app/models/page.server.ts +0 -27
  107. package/templates/remix-ai/app/puck.config.tsx +0 -25
  108. package/templates/remix-ai/app/root.tsx +0 -36
  109. package/templates/remix-ai/app/routes/$puckPath.tsx +0 -2
  110. package/templates/remix-ai/app/routes/$puckPath_.edit.tsx +0 -2
  111. package/templates/remix-ai/app/routes/_index.tsx +0 -34
  112. package/templates/remix-ai/app/routes/api.puck.$.tsx +0 -13
  113. package/templates/remix-ai/app/routes/edit.tsx +0 -70
  114. package/templates/remix-ai/app/styles/shared.css +0 -3
  115. package/templates/remix-ai/database.json +0 -1
  116. package/templates/remix-ai/gitignore +0 -6
  117. package/templates/remix-ai/package.json.hbs +0 -37
  118. package/templates/remix-ai/public/favicon.ico +0 -0
  119. package/templates/remix-ai/remix.config.js +0 -12
  120. package/templates/remix-ai/remix.env.d.ts +0 -2
  121. package/templates/remix-ai/tsconfig.json +0 -22
package/index.js CHANGED
@@ -95,10 +95,6 @@ program
95
95
  name: "React Router",
96
96
  value: "react-router",
97
97
  },
98
- {
99
- name: "Remix",
100
- value: "remix",
101
- },
102
98
  ],
103
99
  },
104
100
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-puck-app",
3
- "version": "0.22.0-canary.f4f83ac1",
3
+ "version": "0.22.0",
4
4
  "author": "Chris Villa <chris@puckeditor.com>",
5
5
  "repository": "puckeditor/puck",
6
6
  "bugs": "https://github.com/puckeditor/puck/issues",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "commander": "^10.0.1",
26
- "glob": "^11.1.0",
26
+ "glob": "^12.0.0",
27
27
  "handlebars": "^4.7.7",
28
28
  "inquirer": "^9.2.7",
29
29
  "prettier": "^2.8.8"
@@ -9,8 +9,8 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "@puckeditor/core": "{{puckVersion}}",
12
- "@puckeditor/cloud-client": "^0.5.0",
13
- "@puckeditor/plugin-ai": "^0.5.0",
12
+ "@puckeditor/cloud-client": "^0.7.0",
13
+ "@puckeditor/plugin-ai": "^0.7.0",
14
14
  "classnames": "^2.3.2",
15
15
  "next": "^16.0.8",
16
16
  "react": "^19.2.1",
@@ -11,8 +11,8 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@puckeditor/core": "{{puckVersion}}",
14
- "@puckeditor/cloud-client": "^0.5.0",
15
- "@puckeditor/plugin-ai": "^0.5.0",
14
+ "@puckeditor/cloud-client": "^0.7.0",
15
+ "@puckeditor/plugin-ai": "^0.7.0",
16
16
  "@react-router/node": "^7.5.3",
17
17
  "@react-router/serve": "^7.5.3",
18
18
  "isbot": "^5",
@@ -1,8 +0,0 @@
1
- # # Ignore everything
2
- *.*
3
-
4
- # # Explicitly ignore gitignore without extension
5
- gitignore
6
-
7
- # # Except for handlebars files
8
- !*.hbs
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- extends: ["custom"],
4
- };
@@ -1,38 +0,0 @@
1
- # `next` recipe
2
-
3
- The `next` recipe showcases one of the most powerful ways to implement Puck using to provide an authoring tool for any route in your Next app.
4
-
5
- ## Demonstrates
6
-
7
- - Next.js App Router implementation
8
- - JSON database implementation with HTTP API
9
- - Catch-all routes to use puck for any route on the platform
10
- - Incremental static regeneration (ISR) for all Puck pages
11
-
12
- ## Usage
13
-
14
- Run the generator and enter `next` when prompted
15
-
16
- ```
17
- npx create-puck-app my-app
18
- ```
19
-
20
- Start the server
21
-
22
- ```
23
- yarn dev
24
- ```
25
-
26
- Navigate to the homepage at https://localhost:3000. To edit the homepage, access the Puck editor at https://localhost:3000/edit.
27
-
28
- You can do this for any route on the application, **even if the page doesn't exist**. For example, visit https://localhost:3000/hello/world and you'll receive a 404. You can author and publish a page by visiting https://localhost:3000/hello/world/edit. After publishing, go back to the original URL to see your page.
29
-
30
- ## Using this recipe
31
-
32
- To adopt this recipe you will need to:
33
-
34
- - **IMPORTANT** Add authentication to `/edit` routes. This can be done by modifying the example API routes in `/app/puck/api/route.ts` and server component in `/app/puck/[...puckPath]/page.tsx`. **If you don't do this, Puck will be completely public.**
35
- - Integrate your database into the API calls in `/app/puck/api/route.ts`
36
- - Implement a custom puck configuration in `puck.config.tsx`
37
-
38
- By default, this recipe will generate static pages by setting `dynamic` to [`force-static`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic) in the `/app/[...puckPath]/page.tsx`. This will strip headers and cookies. If you need dynamic pages, you can delete this.
@@ -1,9 +0,0 @@
1
- "use client";
2
-
3
- import type { Data } from "@puckeditor/core";
4
- import { Render } from "@puckeditor/core";
5
- import config from "../../puck.config";
6
-
7
- export function Client({ data }: { data: Data }) {
8
- return <Render config={config} data={data} />;
9
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * This file implements a catch-all route that renders the user-facing pages
3
- * generated by Puck. For any route visited (with exception of other hardcoded
4
- * pages in /app), it will check your database (via `getPage`) for a Puck page
5
- * and render it using <Render>.
6
- *
7
- * All routes produced by this page are statically rendered using incremental
8
- * static site generation. After the first visit, the page will be cached as
9
- * a static file. Subsequent visits will receive the cache. Publishing a page
10
- * will invalidate the cache as the page is written in /api/puck/route.ts
11
- */
12
-
13
- import { Client } from "./client";
14
- import { notFound } from "next/navigation";
15
- import { Metadata } from "next";
16
- import { getPage } from "../../lib/get-page";
17
-
18
- export async function generateMetadata({
19
- params,
20
- }: {
21
- params: Promise<{ puckPath: string[] }>;
22
- }): Promise<Metadata> {
23
- const { puckPath = [] } = await params;
24
- const path = `/${puckPath.join("/")}`;
25
-
26
- return {
27
- title: getPage(path)?.root.props?.title,
28
- };
29
- }
30
-
31
- export default async function Page({
32
- params,
33
- }: {
34
- params: Promise<{ puckPath: string[] }>;
35
- }) {
36
- const { puckPath = [] } = await params;
37
- const path = `/${puckPath.join("/")}`;
38
- const data = getPage(path);
39
-
40
- if (!data) {
41
- return notFound();
42
- }
43
-
44
- return <Client data={data} />;
45
- }
46
-
47
- // Force Next.js to produce static pages: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
48
- // Delete this if you need dynamic rendering, such as access to headers or cookies
49
- export const dynamic = "force-static";
Binary file
@@ -1,13 +0,0 @@
1
- import "./styles.css";
2
-
3
- export default function RootLayout({
4
- children,
5
- }: {
6
- children: React.ReactNode;
7
- }) {
8
- return (
9
- <html lang="en">
10
- <body>{children}</body>
11
- </html>
12
- );
13
- }
@@ -1 +0,0 @@
1
- export { default, generateMetadata } from "./[...puckPath]/page";
@@ -1,20 +0,0 @@
1
- "use client";
2
-
3
- import type { Data } from "@puckeditor/core";
4
- import { Puck } from "@puckeditor/core";
5
- import config from "../../../puck.config";
6
-
7
- export function Client({ path, data }: { path: string; data: Partial<Data> }) {
8
- return (
9
- <Puck
10
- config={config}
11
- data={data}
12
- onPublish={async (data) => {
13
- await fetch("/puck/api", {
14
- method: "post",
15
- body: JSON.stringify({ data, path }),
16
- });
17
- }}
18
- />
19
- );
20
- }
@@ -1,44 +0,0 @@
1
- /**
2
- * This file implements a *magic* catch-all route that renders the Puck editor.
3
- *
4
- * This route exposes /puck/[...puckPath], but is disabled by middleware.ts. The middleware
5
- * then rewrites all URL requests ending in `/edit` to this route, allowing you to visit any
6
- * page in your application and add /edit to the end to spin up a Puck editor.
7
- *
8
- * This approach enables public pages to be statically rendered whilst the /puck route can
9
- * remain dynamic.
10
- *
11
- * NB this route is public, and you will need to add authentication
12
- */
13
-
14
- import "@puckeditor/core/puck.css";
15
- import { Client } from "./client";
16
- import { Metadata } from "next";
17
- import { getPage } from "../../../lib/get-page";
18
-
19
- export async function generateMetadata({
20
- params,
21
- }: {
22
- params: Promise<{ puckPath: string[] }>;
23
- }): Promise<Metadata> {
24
- const { puckPath = [] } = await params;
25
- const path = `/${puckPath.join("/")}`;
26
-
27
- return {
28
- title: "Puck: " + path,
29
- };
30
- }
31
-
32
- export default async function Page({
33
- params,
34
- }: {
35
- params: Promise<{ puckPath: string[] }>;
36
- }) {
37
- const { puckPath = [] } = await params;
38
- const path = `/${puckPath.join("/")}`;
39
- const data = getPage(path);
40
-
41
- return <Client path={path} data={data || {}} />;
42
- }
43
-
44
- export const dynamic = "force-dynamic";
@@ -1,25 +0,0 @@
1
- import { revalidatePath } from "next/cache";
2
- import { NextResponse } from "next/server";
3
- import fs from "fs";
4
-
5
- export async function POST(request: Request) {
6
- const payload = await request.json();
7
-
8
- const existingData = JSON.parse(
9
- fs.existsSync("database.json")
10
- ? fs.readFileSync("database.json", "utf-8")
11
- : "{}"
12
- );
13
-
14
- const updatedData = {
15
- ...existingData,
16
- [payload.path]: payload.data,
17
- };
18
-
19
- fs.writeFileSync("database.json", JSON.stringify(updatedData));
20
-
21
- // Purge Next.js cache
22
- revalidatePath(payload.path);
23
-
24
- return NextResponse.json({ status: "ok" });
25
- }
@@ -1,3 +0,0 @@
1
- export { default, generateMetadata } from "./[...puckPath]/page";
2
-
3
- export const dynamic = "force-dynamic";
@@ -1,3 +0,0 @@
1
- body {
2
- margin: 0;
3
- }
@@ -1 +0,0 @@
1
- {"/":{"content":[{"type":"HeadingBlock","props":{"title":"Edit this page by adding /edit to the end of the URL","id":"HeadingBlock-1694032984497"}}],"root":{"props": {"title":""}}}}
@@ -1,34 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
-
3
- # dependencies
4
- /node_modules
5
- /.pnp
6
- .pnp.js
7
-
8
- # testing
9
- /coverage
10
-
11
- # next.js
12
- /.next/
13
- /out/
14
-
15
- # production
16
- /build
17
-
18
- # misc
19
- .DS_Store
20
- *.pem
21
-
22
- # debug
23
- npm-debug.log*
24
- yarn-debug.log*
25
- yarn-error.log*
26
-
27
- # local env files
28
- .env.local
29
- .env.development.local
30
- .env.test.local
31
- .env.production.local
32
-
33
- # vercel
34
- .vercel
@@ -1,11 +0,0 @@
1
- import { Data } from "@puckeditor/core";
2
- import fs from "fs";
3
-
4
- // Replace with call to your database
5
- export const getPage = (path: string) => {
6
- const allData: Record<string, Data> | null = fs.existsSync("database.json")
7
- ? JSON.parse(fs.readFileSync("database.json", "utf-8"))
8
- : null;
9
-
10
- return allData ? allData[path] : null;
11
- };
@@ -1,6 +0,0 @@
1
- /// <reference types="next" />
2
- /// <reference types="next/image-types/global" />
3
- import "./.next/dev/types/routes.d.ts";
4
-
5
- // NOTE: This file should not be edited
6
- // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- reactStrictMode: true,
3
- };
@@ -1,27 +0,0 @@
1
- import { NextResponse } from "next/server";
2
-
3
- import type { NextRequest } from "next/server";
4
-
5
- export async function proxy(req: NextRequest) {
6
- const res = NextResponse.next({ request: req });
7
-
8
- if (req.method === "GET") {
9
- // Rewrite routes that match "/[...puckPath]/edit" to "/puck/[...puckPath]"
10
- if (req.nextUrl.pathname.endsWith("/edit")) {
11
- const pathWithoutEdit = req.nextUrl.pathname.slice(
12
- 0,
13
- req.nextUrl.pathname.length - 5
14
- );
15
- const pathWithEditPrefix = `/puck${pathWithoutEdit}`;
16
-
17
- return NextResponse.rewrite(new URL(pathWithEditPrefix, req.url));
18
- }
19
-
20
- // Disable "/puck/[...puckPath]"
21
- if (req.nextUrl.pathname.startsWith("/puck")) {
22
- return NextResponse.redirect(new URL("/", req.url));
23
- }
24
- }
25
-
26
- return res;
27
- }
@@ -1,25 +0,0 @@
1
- import type { Config } from "@puckeditor/core";
2
-
3
- type Props = {
4
- HeadingBlock: { title: string };
5
- };
6
-
7
- export const config: Config<Props> = {
8
- components: {
9
- HeadingBlock: {
10
- fields: {
11
- title: { type: "text" },
12
- },
13
- defaultProps: {
14
- title: "Heading",
15
- },
16
- render: ({ title }) => (
17
- <div style={{ padding: 64 }}>
18
- <h1>{title}</h1>
19
- </div>
20
- ),
21
- },
22
- },
23
- };
24
-
25
- export default config;
@@ -1,20 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "display": "Default",
4
- "compilerOptions": {
5
- "composite": false,
6
- "declaration": true,
7
- "declarationMap": true,
8
- "esModuleInterop": true,
9
- "forceConsistentCasingInFileNames": true,
10
- "inlineSources": false,
11
- "isolatedModules": true,
12
- "moduleResolution": "node",
13
- "noUnusedLocals": false,
14
- "noUnusedParameters": false,
15
- "preserveWatchOutput": true,
16
- "skipLibCheck": true,
17
- "strict": true
18
- },
19
- "exclude": ["node_modules"]
20
- }
@@ -1,21 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "display": "Next.js",
4
- "extends": "./base.json",
5
- "compilerOptions": {
6
- "plugins": [{ "name": "next" }],
7
- "allowJs": true,
8
- "declaration": false,
9
- "declarationMap": false,
10
- "incremental": true,
11
- "jsx": "preserve",
12
- "lib": ["dom", "dom.iterable", "esnext"],
13
- "module": "esnext",
14
- "noEmit": true,
15
- "resolveJsonModule": true,
16
- "strict": false,
17
- "target": "es5"
18
- },
19
- "include": ["src", "next-env.d.ts"],
20
- "exclude": ["node_modules"]
21
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "./tsconfig/nextjs.json",
3
- "compilerOptions": {
4
- "plugins": [{ "name": "next" }]
5
- },
6
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
7
- "exclude": ["node_modules"]
8
- }
@@ -1,2 +0,0 @@
1
- # Add your key here, more information available at: https://puckeditor.com/docs/ai/getting-started#generate-an-api-key
2
- PUCK_API_KEY=
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- extends: ["custom"],
4
- };
@@ -1,60 +0,0 @@
1
- # `next-ai` recipe
2
-
3
- The `next-ai` recipe showcases one of the most powerful ways to combine Puck and [Puck AI](https://puckeditor.com/docs/ai/overview): providing an authoring tool with AI page generation capabilities for any route in your Next app.
4
-
5
- ## Demonstrates
6
-
7
- - Puck AI integration for generating pages with AI
8
- - Next.js App Router implementation
9
- - JSON database implementation with HTTP API
10
- - Catch-all routes to use puck for any route on the platform
11
- - Incremental static regeneration (ISR) for all Puck pages
12
-
13
- ## Usage
14
-
15
- Run the generator and select `Next.js` when prompted
16
-
17
- ```
18
- npx create-puck-app my-app
19
-
20
- ? Which recipe would you like to use?
21
- ❯ Next.js
22
- ```
23
-
24
- Confirm you want to use Puck AI
25
-
26
- ```
27
- ? Would you like to use Puck AI? (Y/n) Y
28
- ```
29
-
30
- Start the server
31
-
32
- ```
33
- cd my-app
34
- yarn dev
35
- ```
36
-
37
- ### Set up Puck AI
38
-
39
- Create a [Puck account](https://cloud.puckeditor.com) and [obtain an API key](https://cloud.puckeditor.com/api-keys).
40
-
41
- Create a `.env.local` file in the root of your project and add your API key:
42
-
43
- ```
44
- PUCK_API_KEY=your-api-key
45
- ```
46
-
47
- Navigate to the homepage at https://localhost:3000. To edit the homepage, access the Puck editor at https://localhost:3000/edit, and select the AI button in the left navigation bar to generate content for the page using Puck AI.
48
-
49
- You can do this for any route on the application, **even if the page doesn't exist**. For example, visit https://localhost:3000/hello/world and you'll receive a 404. You can author and publish a page by visiting https://localhost:3000/hello/world/edit. After publishing, go back to the original URL to see your page.
50
-
51
- ## Using this recipe
52
-
53
- To adopt this recipe you will need to:
54
-
55
- - **IMPORTANT** Add authentication to `/edit` routes. This can be done by modifying the example API routes in `/app/puck/api/route.ts` and server component in `/app/puck/[...puckPath]/page.tsx`. **If you don't do this, Puck will be completely public.**
56
- - Integrate your database into the API calls in `/app/puck/api/route.ts`
57
- - Implement a custom puck configuration in `puck.config.tsx`
58
- - Add business context for the AI generation in `/app/api/puck/[...all]/route.ts`
59
-
60
- By default, this recipe will generate static pages by setting `dynamic` to [`force-static`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic) in the `/app/[...puckPath]/page.tsx`. This will strip headers and cookies. If you need dynamic pages, you can delete this.
@@ -1,9 +0,0 @@
1
- "use client";
2
-
3
- import type { Data } from "@puckeditor/core";
4
- import { Render } from "@puckeditor/core";
5
- import config from "../../puck.config";
6
-
7
- export function Client({ data }: { data: Data }) {
8
- return <Render config={config} data={data} />;
9
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * This file implements a catch-all route that renders the user-facing pages
3
- * generated by Puck. For any route visited (with exception of other hardcoded
4
- * pages in /app), it will check your database (via `getPage`) for a Puck page
5
- * and render it using <Render>.
6
- *
7
- * All routes produced by this page are statically rendered using incremental
8
- * static site generation. After the first visit, the page will be cached as
9
- * a static file. Subsequent visits will receive the cache. Publishing a page
10
- * will invalidate the cache as the page is written in /api/puck/route.ts
11
- */
12
-
13
- import { Client } from "./client";
14
- import { notFound } from "next/navigation";
15
- import { Metadata } from "next";
16
- import { getPage } from "../../lib/get-page";
17
-
18
- export async function generateMetadata({
19
- params,
20
- }: {
21
- params: Promise<{ puckPath: string[] }>;
22
- }): Promise<Metadata> {
23
- const { puckPath = [] } = await params;
24
- const path = `/${puckPath.join("/")}`;
25
-
26
- return {
27
- title: getPage(path)?.root.props?.title,
28
- };
29
- }
30
-
31
- export default async function Page({
32
- params,
33
- }: {
34
- params: Promise<{ puckPath: string[] }>;
35
- }) {
36
- const { puckPath = [] } = await params;
37
- const path = `/${puckPath.join("/")}`;
38
- const data = getPage(path);
39
-
40
- if (!data) {
41
- return notFound();
42
- }
43
-
44
- return <Client data={data} />;
45
- }
46
-
47
- // Force Next.js to produce static pages: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
48
- // Delete this if you need dynamic rendering, such as access to headers or cookies
49
- export const dynamic = "force-static";
@@ -1,26 +0,0 @@
1
- import { revalidatePath } from "next/cache";
2
- import { NextResponse } from "next/server";
3
- import fs from "fs";
4
-
5
- // Saves page data to a JSON file, replace this with your own database logic
6
- export async function POST(request: Request) {
7
- const payload = await request.json();
8
-
9
- const existingData = JSON.parse(
10
- fs.existsSync("database.json")
11
- ? fs.readFileSync("database.json", "utf-8")
12
- : "{}"
13
- );
14
-
15
- const updatedData = {
16
- ...existingData,
17
- [payload.path]: payload.data,
18
- };
19
-
20
- fs.writeFileSync("database.json", JSON.stringify(updatedData));
21
-
22
- // Purge Next.js cache
23
- revalidatePath(payload.path);
24
-
25
- return NextResponse.json({ status: "ok" });
26
- }
@@ -1,13 +0,0 @@
1
- import { NextRequest } from "next/server";
2
- import { puckHandler } from "@puckeditor/cloud-client";
3
-
4
- // Handles all requests for Puck AI
5
- // Learn more: https://puckeditor.com/docs/ai/getting-started
6
- export const POST = (request: NextRequest) => {
7
- return puckHandler(request, {
8
- ai: {
9
- // Replace with your business context
10
- context: "We are Google. You create Google landing pages.",
11
- },
12
- });
13
- };
@@ -1,13 +0,0 @@
1
- import "./styles.css";
2
-
3
- export default function RootLayout({
4
- children,
5
- }: {
6
- children: React.ReactNode;
7
- }) {
8
- return (
9
- <html lang="en">
10
- <body>{children}</body>
11
- </html>
12
- );
13
- }
@@ -1 +0,0 @@
1
- export { default, generateMetadata } from "./[...puckPath]/page";