pagiera 0.2.0-alpha.33

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 (192) hide show
  1. package/README.md +528 -0
  2. package/dist/adapters.d.ts +89 -0
  3. package/dist/adapters.d.ts.map +1 -0
  4. package/dist/adapters.js +2 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/client.d.ts +22 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +33 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/data.js +210 -0
  11. package/dist/data.js.map +7 -0
  12. package/dist/document.d.ts +63 -0
  13. package/dist/document.d.ts.map +1 -0
  14. package/dist/document.js +25 -0
  15. package/dist/document.js.map +1 -0
  16. package/dist/editor.d.ts +14 -0
  17. package/dist/editor.d.ts.map +1 -0
  18. package/dist/editor.js +59 -0
  19. package/dist/editor.js.map +1 -0
  20. package/dist/full-editor.d.ts +53 -0
  21. package/dist/full-editor.js +11117 -0
  22. package/dist/full-editor.js.map +7 -0
  23. package/dist/full.css +3498 -0
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +7 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/internal/app/api/ai-design/route.d.ts +3 -0
  29. package/dist/internal/app/api/ai-design/route.d.ts.map +1 -0
  30. package/dist/internal/app/api/ai-design/route.js +165 -0
  31. package/dist/internal/app/api/ai-design/route.js.map +1 -0
  32. package/dist/internal/app/p/editor/ai-panel.d.ts +27 -0
  33. package/dist/internal/app/p/editor/ai-panel.d.ts.map +1 -0
  34. package/dist/internal/app/p/editor/ai-panel.js +77 -0
  35. package/dist/internal/app/p/editor/ai-panel.js.map +1 -0
  36. package/dist/internal/app/p/editor/data-modal.d.ts +26 -0
  37. package/dist/internal/app/p/editor/data-modal.d.ts.map +1 -0
  38. package/dist/internal/app/p/editor/data-modal.js +94 -0
  39. package/dist/internal/app/p/editor/data-modal.js.map +1 -0
  40. package/dist/internal/app/p/editor/data-panel.d.ts +18 -0
  41. package/dist/internal/app/p/editor/data-panel.d.ts.map +1 -0
  42. package/dist/internal/app/p/editor/data-panel.js +45 -0
  43. package/dist/internal/app/p/editor/data-panel.js.map +1 -0
  44. package/dist/internal/app/p/editor/editor.d.ts +51 -0
  45. package/dist/internal/app/p/editor/editor.d.ts.map +1 -0
  46. package/dist/internal/app/p/editor/editor.js +1551 -0
  47. package/dist/internal/app/p/editor/editor.js.map +1 -0
  48. package/dist/internal/app/p/editor/fields.d.ts +111 -0
  49. package/dist/internal/app/p/editor/fields.d.ts.map +1 -0
  50. package/dist/internal/app/p/editor/fields.js +141 -0
  51. package/dist/internal/app/p/editor/fields.js.map +1 -0
  52. package/dist/internal/app/p/editor/inspector.d.ts +38 -0
  53. package/dist/internal/app/p/editor/inspector.d.ts.map +1 -0
  54. package/dist/internal/app/p/editor/inspector.js +336 -0
  55. package/dist/internal/app/p/editor/inspector.js.map +1 -0
  56. package/dist/internal/app/p/editor/library.d.ts +18 -0
  57. package/dist/internal/app/p/editor/library.d.ts.map +1 -0
  58. package/dist/internal/app/p/editor/library.js +61 -0
  59. package/dist/internal/app/p/editor/library.js.map +1 -0
  60. package/dist/internal/app/p/editor/parts.d.ts +75 -0
  61. package/dist/internal/app/p/editor/parts.d.ts.map +1 -0
  62. package/dist/internal/app/p/editor/parts.js +261 -0
  63. package/dist/internal/app/p/editor/parts.js.map +1 -0
  64. package/dist/internal/app/p/editor/templates-panel.d.ts +6 -0
  65. package/dist/internal/app/p/editor/templates-panel.d.ts.map +1 -0
  66. package/dist/internal/app/p/editor/templates-panel.js +12 -0
  67. package/dist/internal/app/p/editor/templates-panel.js.map +1 -0
  68. package/dist/internal/app/p/editor/use-canvas-view.d.ts +24 -0
  69. package/dist/internal/app/p/editor/use-canvas-view.d.ts.map +1 -0
  70. package/dist/internal/app/p/editor/use-canvas-view.js +242 -0
  71. package/dist/internal/app/p/editor/use-canvas-view.js.map +1 -0
  72. package/dist/internal/app/p/editor/use-editor.d.ts +48 -0
  73. package/dist/internal/app/p/editor/use-editor.d.ts.map +1 -0
  74. package/dist/internal/app/p/editor/use-editor.js +224 -0
  75. package/dist/internal/app/p/editor/use-editor.js.map +1 -0
  76. package/dist/internal/app/p/editor/variables-panel.d.ts +8 -0
  77. package/dist/internal/app/p/editor/variables-panel.d.ts.map +1 -0
  78. package/dist/internal/app/p/editor/variables-panel.js +52 -0
  79. package/dist/internal/app/p/editor/variables-panel.js.map +1 -0
  80. package/dist/internal/components/ui/select.d.ts +12 -0
  81. package/dist/internal/components/ui/select.d.ts.map +1 -0
  82. package/dist/internal/components/ui/select.js +32 -0
  83. package/dist/internal/components/ui/select.js.map +1 -0
  84. package/dist/internal/drizzle/index.d.ts +6 -0
  85. package/dist/internal/drizzle/index.d.ts.map +1 -0
  86. package/dist/internal/drizzle/index.js +20 -0
  87. package/dist/internal/drizzle/index.js.map +1 -0
  88. package/dist/internal/drizzle/schema.d.ts +405 -0
  89. package/dist/internal/drizzle/schema.d.ts.map +1 -0
  90. package/dist/internal/drizzle/schema.js +70 -0
  91. package/dist/internal/drizzle/schema.js.map +1 -0
  92. package/dist/internal/lib/data/context.d.ts +8 -0
  93. package/dist/internal/lib/data/context.d.ts.map +1 -0
  94. package/dist/internal/lib/data/context.js +17 -0
  95. package/dist/internal/lib/data/context.js.map +1 -0
  96. package/dist/internal/lib/data/source.d.ts +54 -0
  97. package/dist/internal/lib/data/source.d.ts.map +1 -0
  98. package/dist/internal/lib/data/source.js +229 -0
  99. package/dist/internal/lib/data/source.js.map +1 -0
  100. package/dist/internal/lib/editor/ai-types.d.ts +44 -0
  101. package/dist/internal/lib/editor/ai-types.d.ts.map +1 -0
  102. package/dist/internal/lib/editor/ai-types.js +2 -0
  103. package/dist/internal/lib/editor/ai-types.js.map +1 -0
  104. package/dist/internal/lib/editor/arrange.d.ts +12 -0
  105. package/dist/internal/lib/editor/arrange.d.ts.map +1 -0
  106. package/dist/internal/lib/editor/arrange.js +72 -0
  107. package/dist/internal/lib/editor/arrange.js.map +1 -0
  108. package/dist/internal/lib/editor/cascade.d.ts +39 -0
  109. package/dist/internal/lib/editor/cascade.d.ts.map +1 -0
  110. package/dist/internal/lib/editor/cascade.js +86 -0
  111. package/dist/internal/lib/editor/cascade.js.map +1 -0
  112. package/dist/internal/lib/editor/icon.d.ts +6 -0
  113. package/dist/internal/lib/editor/icon.d.ts.map +1 -0
  114. package/dist/internal/lib/editor/icon.js +13 -0
  115. package/dist/internal/lib/editor/icon.js.map +1 -0
  116. package/dist/internal/lib/editor/presets.d.ts +10 -0
  117. package/dist/internal/lib/editor/presets.d.ts.map +1 -0
  118. package/dist/internal/lib/editor/presets.js +83 -0
  119. package/dist/internal/lib/editor/presets.js.map +1 -0
  120. package/dist/internal/lib/editor/showcase.d.ts +14 -0
  121. package/dist/internal/lib/editor/showcase.d.ts.map +1 -0
  122. package/dist/internal/lib/editor/showcase.js +219 -0
  123. package/dist/internal/lib/editor/showcase.js.map +1 -0
  124. package/dist/internal/lib/editor/site-templates.d.ts +4 -0
  125. package/dist/internal/lib/editor/site-templates.d.ts.map +1 -0
  126. package/dist/internal/lib/editor/site-templates.js +156 -0
  127. package/dist/internal/lib/editor/site-templates.js.map +1 -0
  128. package/dist/internal/lib/editor/snap.d.ts +34 -0
  129. package/dist/internal/lib/editor/snap.d.ts.map +1 -0
  130. package/dist/internal/lib/editor/snap.js +70 -0
  131. package/dist/internal/lib/editor/snap.js.map +1 -0
  132. package/dist/internal/lib/editor/style.d.ts +53 -0
  133. package/dist/internal/lib/editor/style.d.ts.map +1 -0
  134. package/dist/internal/lib/editor/style.js +313 -0
  135. package/dist/internal/lib/editor/style.js.map +1 -0
  136. package/dist/internal/lib/editor/tree.d.ts +72 -0
  137. package/dist/internal/lib/editor/tree.d.ts.map +1 -0
  138. package/dist/internal/lib/editor/tree.js +301 -0
  139. package/dist/internal/lib/editor/tree.js.map +1 -0
  140. package/dist/internal/lib/editor/types.d.ts +273 -0
  141. package/dist/internal/lib/editor/types.d.ts.map +1 -0
  142. package/dist/internal/lib/editor/types.js +411 -0
  143. package/dist/internal/lib/editor/types.js.map +1 -0
  144. package/dist/internal/lib/editor/validate.d.ts +20 -0
  145. package/dist/internal/lib/editor/validate.d.ts.map +1 -0
  146. package/dist/internal/lib/editor/validate.js +467 -0
  147. package/dist/internal/lib/editor/validate.js.map +1 -0
  148. package/dist/internal/lib/pages.d.ts +83 -0
  149. package/dist/internal/lib/pages.d.ts.map +1 -0
  150. package/dist/internal/lib/pages.js +294 -0
  151. package/dist/internal/lib/pages.js.map +1 -0
  152. package/dist/internal/lib/render/bind.d.ts +18 -0
  153. package/dist/internal/lib/render/bind.d.ts.map +1 -0
  154. package/dist/internal/lib/render/bind.js +28 -0
  155. package/dist/internal/lib/render/bind.js.map +1 -0
  156. package/dist/internal/lib/render/css.d.ts +31 -0
  157. package/dist/internal/lib/render/css.d.ts.map +1 -0
  158. package/dist/internal/lib/render/css.js +239 -0
  159. package/dist/internal/lib/render/css.js.map +1 -0
  160. package/dist/internal/lib/render/load-data.d.ts +15 -0
  161. package/dist/internal/lib/render/load-data.d.ts.map +1 -0
  162. package/dist/internal/lib/render/load-data.js +39 -0
  163. package/dist/internal/lib/render/load-data.js.map +1 -0
  164. package/dist/internal/lib/render/page-render.d.ts +17 -0
  165. package/dist/internal/lib/render/page-render.d.ts.map +1 -0
  166. package/dist/internal/lib/render/page-render.js +117 -0
  167. package/dist/internal/lib/render/page-render.js.map +1 -0
  168. package/dist/internal/lib/utils.d.ts +3 -0
  169. package/dist/internal/lib/utils.d.ts.map +1 -0
  170. package/dist/internal/lib/utils.js +6 -0
  171. package/dist/internal/lib/utils.js.map +1 -0
  172. package/dist/manrope-data.d.ts +3 -0
  173. package/dist/manrope-data.d.ts.map +1 -0
  174. package/dist/manrope-data.js +3 -0
  175. package/dist/manrope-data.js.map +1 -0
  176. package/dist/page.d.ts +9 -0
  177. package/dist/page.d.ts.map +1 -0
  178. package/dist/page.js +148 -0
  179. package/dist/page.js.map +1 -0
  180. package/dist/provider.d.ts +14 -0
  181. package/dist/provider.d.ts.map +1 -0
  182. package/dist/provider.js +45 -0
  183. package/dist/provider.js.map +1 -0
  184. package/dist/runtime.d.ts +8 -0
  185. package/dist/runtime.js +717 -0
  186. package/dist/runtime.js.map +7 -0
  187. package/dist/server.d.ts +31 -0
  188. package/dist/server.js +2267 -0
  189. package/dist/server.js.map +7 -0
  190. package/dist/styles.css +300 -0
  191. package/package.json +94 -0
  192. package/thumbnail.png +0 -0
package/README.md ADDED
@@ -0,0 +1,528 @@
1
+ # Pagiera
2
+
3
+ ![Pagiera visual website builder](./thumbnail.png)
4
+
5
+ Pagiera is a full-stack visual website builder for React and Next.js. It ships the editor, responsive canvas, page management, reusable components, templates, AI generation, server-side data fetching, publishing runtime, PostgreSQL persistence, and Redis caching as one installable package.
6
+
7
+ Design in the editor and render the same document on the server. Published pages use semantic HTML, support dynamic routes and query parameters, and can load external API data before HTML is sent to the browser.
8
+
9
+ ## Highlights
10
+
11
+ - Framer-style visual editor with an infinite canvas
12
+ - Responsive breakpoints with isolated overrides
13
+ - Free and flow-based layouts
14
+ - Reusable components and variants
15
+ - Layers, assets, templates, icons, and component library
16
+ - Hover, press, entrance, loop, and scroll effects
17
+ - Custom easing curves and spring controls
18
+ - Site-wide fonts provided through `next/font`
19
+ - AI-assisted site generation through OpenRouter and the AI SDK
20
+ - GET, POST, PUT, PATCH, and DELETE data sources
21
+ - Path parameters, query parameters, headers, and request bodies
22
+ - Server-side Request and Repeat blocks
23
+ - Dynamic routes such as `/blog/:slug`
24
+ - Draft preview and published page rendering
25
+ - PostgreSQL persistence and optimistic revisions
26
+ - Redis-backed publishing cache and AI rate limiting
27
+ - Semantic output including `main`, `section`, `nav`, `header`, `footer`, headings, links, paragraphs, and buttons
28
+
29
+ ## Requirements
30
+
31
+ - Node.js 20+
32
+ - React 18.3+
33
+ - Next.js App Router for the full-stack integration
34
+ - PostgreSQL
35
+ - Redis
36
+ - OpenRouter API key for AI generation
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ npm install pagiera
42
+ ```
43
+
44
+ ```bash
45
+ bun add pagiera
46
+ ```
47
+
48
+ ## Environment variables
49
+
50
+ Create `.env.local`:
51
+
52
+ ```env
53
+ PAGIERA_POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/pagiera
54
+ PAGIERA_REDIS_URL=redis://localhost:6379
55
+ OPENROUTER_API_KEY=sk-or-v1-your-key
56
+ OPENROUTER_MODEL=anthropic/claude-sonnet-4.5
57
+ ```
58
+
59
+ Pagiera creates its required PostgreSQL tables when the server initializes. Redis is used for published-page caching and AI rate limiting.
60
+
61
+ ## Next.js setup
62
+
63
+ ### 1. Import the editor stylesheet
64
+
65
+ ```css
66
+ /* src/app/globals.css */
67
+ @import "tailwindcss";
68
+ @import "pagiera/full.css";
69
+ ```
70
+
71
+ `full.css` contains the complete studio UI. Use `pagiera/styles.css` only with the smaller `PagieraEditor` API.
72
+
73
+ ### 2. Add the font provider
74
+
75
+ The provider makes `next/font` fonts available in **Typography → Site font**. A selection applies to the canvas, preview, and published site.
76
+
77
+ ```tsx
78
+ // src/app/layout.tsx
79
+ import { Geist, Geist_Mono } from "next/font/google";
80
+ import { PagieraProvider } from "pagiera/provider";
81
+ import "./globals.css";
82
+
83
+ const geistSans = Geist({
84
+ variable: "--font-geist-sans",
85
+ subsets: ["latin"],
86
+ });
87
+
88
+ const geistMono = Geist_Mono({
89
+ variable: "--font-geist-mono",
90
+ subsets: ["latin"],
91
+ });
92
+
93
+ export default function RootLayout({ children }: LayoutProps<"/">) {
94
+ return (
95
+ <html lang="en">
96
+ <body>
97
+ <PagieraProvider
98
+ fonts={[
99
+ { variable: geistSans.variable, title: "Geist Sans" },
100
+ { variable: geistMono.variable, title: "Geist Mono" },
101
+ ]}
102
+ >
103
+ {children}
104
+ </PagieraProvider>
105
+ </body>
106
+ </html>
107
+ );
108
+ }
109
+ ```
110
+
111
+ ```ts
112
+ type PagieraFont = {
113
+ variable: string;
114
+ title: string;
115
+ };
116
+ ```
117
+
118
+ ### 3. Mount the backend
119
+
120
+ ```ts
121
+ // src/app/api/pagiera/[...path]/route.ts
122
+ import {
123
+ createPagieraRouteHandlers,
124
+ pagieraConfigFromEnv,
125
+ } from "pagiera/server";
126
+
127
+ export const maxDuration = 120;
128
+ export const dynamic = "force-dynamic";
129
+
130
+ const handlers = createPagieraRouteHandlers(pagieraConfigFromEnv());
131
+ export const { GET, POST, PUT, PATCH, DELETE } = handlers;
132
+ ```
133
+
134
+ Open `/api/pagiera/health` after starting the application to verify PostgreSQL, Redis, and the configured OpenRouter model.
135
+
136
+ ### 4. Load editor data on the server
137
+
138
+ ```ts
139
+ // src/lib/editor-bootstrap.ts
140
+ import {
141
+ getPagieraServer,
142
+ pagieraConfigFromEnv,
143
+ } from "pagiera/server";
144
+
145
+ export async function editorBootstrap(pageId?: string) {
146
+ const server = await getPagieraServer(pagieraConfigFromEnv());
147
+ const bootstrap = await server.getEditorBootstrap(pageId);
148
+
149
+ if (!bootstrap) throw new Error("Editor page not found");
150
+ return bootstrap;
151
+ }
152
+ ```
153
+
154
+ ### 5. Mount the studio
155
+
156
+ The initial document is server-rendered. A client wrapper handles editing and in-editor navigation.
157
+
158
+ ```tsx
159
+ // src/app/editor/pagiera-editor.tsx
160
+ "use client";
161
+
162
+ import { createPagieraClient } from "pagiera";
163
+ import PagieraStudio from "pagiera/full";
164
+ import type { PagieraStudioProps } from "pagiera/full";
165
+ import { useRouter } from "next/navigation";
166
+ import { useMemo, useState } from "react";
167
+
168
+ type Bootstrap = {
169
+ page: PagieraStudioProps["page"];
170
+ pages: PagieraStudioProps["pages"];
171
+ library: PagieraStudioProps["library"];
172
+ };
173
+
174
+ export function PagieraEditorClient({ initial }: { initial: Bootstrap }) {
175
+ const router = useRouter();
176
+ const client = useMemo(() => createPagieraClient(), []);
177
+ const [bootstrap, setBootstrap] = useState(initial);
178
+
179
+ return (
180
+ <PagieraStudio
181
+ page={bootstrap.page}
182
+ pages={bootstrap.pages}
183
+ library={bootstrap.library}
184
+ adapters={{
185
+ ...client.adapters,
186
+ navigate: async (pageId, options) => {
187
+ if (pageId === bootstrap.page.id) return;
188
+ const next = await client.bootstrap(pageId) as Bootstrap;
189
+ setBootstrap(next);
190
+ const href = `/editor/${encodeURIComponent(pageId)}`;
191
+ options?.replace ? router.replace(href) : router.push(href);
192
+ },
193
+ refresh: () => {
194
+ void client.bootstrap(bootstrap.page.id).then((next) => {
195
+ setBootstrap(next as Bootstrap);
196
+ });
197
+ },
198
+ previewHref: (pageId) => `/preview/${encodeURIComponent(pageId)}`,
199
+ publishedHref: (slug) => slug === "home" ? "/" : `/${slug}`,
200
+ }}
201
+ />
202
+ );
203
+ }
204
+ ```
205
+
206
+ ```tsx
207
+ // src/app/editor/page.tsx
208
+ import { editorBootstrap } from "@/lib/editor-bootstrap";
209
+ import { PagieraEditorClient } from "./pagiera-editor";
210
+
211
+ export const dynamic = "force-dynamic";
212
+
213
+ export default async function EditorPage() {
214
+ return <PagieraEditorClient initial={await editorBootstrap()} />;
215
+ }
216
+ ```
217
+
218
+ ```tsx
219
+ // src/app/editor/[pageId]/page.tsx
220
+ import { editorBootstrap } from "@/lib/editor-bootstrap";
221
+ import { PagieraEditorClient } from "../pagiera-editor";
222
+
223
+ export const dynamic = "force-dynamic";
224
+
225
+ export default async function EditorDocumentPage({ params }: {
226
+ params: Promise<{ pageId: string }>;
227
+ }) {
228
+ return (
229
+ <PagieraEditorClient
230
+ initial={await editorBootstrap((await params).pageId)}
231
+ />
232
+ );
233
+ }
234
+ ```
235
+
236
+ ## Publishing pages
237
+
238
+ Load published documents on the server. Request blocks then finish before HTML is returned, making API-backed content available to search engines.
239
+
240
+ ```tsx
241
+ // src/lib/published-page.tsx
242
+ import { notFound } from "next/navigation";
243
+ import { RenderedPage } from "pagiera/runtime";
244
+ import {
245
+ getPagieraServer,
246
+ pagieraConfigFromEnv,
247
+ } from "pagiera/server";
248
+
249
+ type SearchParams = Promise<Record<string, string | string[] | undefined>>;
250
+
251
+ export async function renderPublishedPage(
252
+ slug: string,
253
+ searchParams: SearchParams,
254
+ params: Record<string, string> = {},
255
+ ) {
256
+ const rawQuery = await searchParams;
257
+ const query = Object.fromEntries(
258
+ Object.entries(rawQuery).map(([key, value]) => [
259
+ key,
260
+ Array.isArray(value) ? value[0] ?? "" : value ?? "",
261
+ ]),
262
+ );
263
+
264
+ const server = await getPagieraServer(pagieraConfigFromEnv());
265
+ const page = await server.getPublishedPage(slug, {
266
+ query,
267
+ params,
268
+ page: { slug },
269
+ });
270
+
271
+ if (!page) notFound();
272
+
273
+ return (
274
+ <RenderedPage
275
+ elements={page.elements}
276
+ rootStyle={page.rootStyle}
277
+ data={page.data}
278
+ />
279
+ );
280
+ }
281
+ ```
282
+
283
+ The `home` page is permanent and maps to `/`:
284
+
285
+ ```tsx
286
+ // src/app/page.tsx
287
+ import { renderPublishedPage } from "@/lib/published-page";
288
+
289
+ export const dynamic = "force-dynamic";
290
+
291
+ export default function HomePage({ searchParams }: {
292
+ searchParams: Promise<Record<string, string | string[] | undefined>>;
293
+ }) {
294
+ return renderPublishedPage("home", searchParams);
295
+ }
296
+ ```
297
+
298
+ Other pages can use a catch-all route:
299
+
300
+ ```tsx
301
+ // src/app/[...path]/page.tsx
302
+ import { renderPublishedPage } from "@/lib/published-page";
303
+
304
+ export const dynamic = "force-dynamic";
305
+
306
+ export default async function PublishedPage({ params, searchParams }: {
307
+ params: Promise<{ path: string[] }>;
308
+ searchParams: Promise<Record<string, string | string[] | undefined>>;
309
+ }) {
310
+ return renderPublishedPage((await params).path.join("/"), searchParams);
311
+ }
312
+ ```
313
+
314
+ ## Dynamic routes and request data
315
+
316
+ Page slugs may contain named parameters:
317
+
318
+ ```text
319
+ blog/:slug
320
+ ```
321
+
322
+ For `/blog/1`, pass the matched values in the server context:
323
+
324
+ ```ts
325
+ {
326
+ params: { slug: "1" },
327
+ query: { preview: "true" }
328
+ }
329
+ ```
330
+
331
+ Request URLs, headers, query fields, and bodies may reference context values:
332
+
333
+ ```text
334
+ https://dummyjson.com/posts/{{params.slug}}
335
+ ```
336
+
337
+ ```text
338
+ https://api.example.com/search?q={{query.q}}
339
+ ```
340
+
341
+ Request blocks expose one returned object directly to descendants. Repeat blocks iterate array results. Both are resolved on the server for published pages.
342
+
343
+ An upstream `404` can turn the complete route into a 404 page when the data source uses the `page-404` behavior.
344
+
345
+ ## Preview routes
346
+
347
+ ```tsx
348
+ // src/app/preview/[pageId]/page.tsx
349
+ import { notFound } from "next/navigation";
350
+ import { RenderedPage } from "pagiera/runtime";
351
+ import {
352
+ getPagieraServer,
353
+ pagieraConfigFromEnv,
354
+ } from "pagiera/server";
355
+
356
+ export const dynamic = "force-dynamic";
357
+
358
+ export default async function PreviewPage({ params }: {
359
+ params: Promise<{ pageId: string }>;
360
+ }) {
361
+ const server = await getPagieraServer(pagieraConfigFromEnv());
362
+ const page = await server.getPreviewPage((await params).pageId);
363
+ if (!page) notFound();
364
+
365
+ return (
366
+ <RenderedPage
367
+ elements={page.elements}
368
+ rootStyle={page.rootStyle}
369
+ data={page.data}
370
+ />
371
+ );
372
+ }
373
+ ```
374
+
375
+ ## Server API
376
+
377
+ ```ts
378
+ import {
379
+ createPagieraRouteHandlers,
380
+ createPagieraServer,
381
+ getPagieraServer,
382
+ pagieraConfigFromEnv,
383
+ } from "pagiera/server";
384
+ ```
385
+
386
+ `getPagieraServer(config)` returns a shared server with:
387
+
388
+ - `handle(request)` — process a Pagiera API request
389
+ - `getEditorBootstrap(pageId?)` — load editor document, pages, and library
390
+ - `getPreviewPage(pageId, context?)` — load a draft and resolve data
391
+ - `getPublishedDocument(slug)` — load published document metadata
392
+ - `getPublishedPage(slug, context?)` — load published document and SSR data
393
+ - `close()` — close PostgreSQL and Redis connections
394
+ - `pool` — PostgreSQL pool
395
+ - `redis` — Redis client
396
+
397
+ ```ts
398
+ type PagieraServerConfig = {
399
+ postgresUrl: string;
400
+ redisUrl: string;
401
+ openRouterApiKey: string;
402
+ openRouterModel: string;
403
+ basePath?: string;
404
+ aiRateLimitPerMinute?: number;
405
+ };
406
+ ```
407
+
408
+ ## Client API
409
+
410
+ ```ts
411
+ import { createPagieraClient } from "pagiera";
412
+
413
+ const client = createPagieraClient({
414
+ baseUrl: "/api/pagiera",
415
+ });
416
+ ```
417
+
418
+ The client includes:
419
+
420
+ - `bootstrap(pageId?)`
421
+ - `loadPage(pageId)`
422
+ - `adapters.save(...)`
423
+ - `adapters.createPage(...)`
424
+ - `adapters.renamePage(...)`
425
+ - `adapters.duplicatePage(...)`
426
+ - `adapters.deletePage(...)`
427
+ - `adapters.installTemplate(...)`
428
+ - `adapters.publishPage(...)`
429
+ - `adapters.unpublishPage(...)`
430
+ - `adapters.previewSource(...)`
431
+ - `adapters.generate(...)`
432
+
433
+ ## Package exports
434
+
435
+ | Import | Purpose |
436
+ | --- | --- |
437
+ | `pagiera` | Document utilities, lightweight editor, renderer, client adapters |
438
+ | `pagiera/provider` | Provider, `next/font` integration, font types |
439
+ | `pagiera/full` | Complete visual studio component |
440
+ | `pagiera/full.css` | Complete studio stylesheet |
441
+ | `pagiera/runtime` | Published and preview renderer |
442
+ | `pagiera/data` | Server-side page data loader |
443
+ | `pagiera/server` | PostgreSQL, Redis, OpenRouter, API, publishing server |
444
+ | `pagiera/styles.css` | Lightweight editor stylesheet |
445
+
446
+ ## Lightweight editor
447
+
448
+ ```tsx
449
+ "use client";
450
+
451
+ import { useState } from "react";
452
+ import {
453
+ createDocument,
454
+ PagieraEditor,
455
+ type PagieraDocument,
456
+ } from "pagiera";
457
+ import "pagiera/styles.css";
458
+
459
+ export function SmallEditor() {
460
+ const [document, setDocument] = useState<PagieraDocument>(() => (
461
+ createDocument()
462
+ ));
463
+
464
+ return (
465
+ <PagieraEditor
466
+ value={document}
467
+ onChange={setDocument}
468
+ adapters={{
469
+ save: async (nextDocument) => saveDocument(nextDocument),
470
+ }}
471
+ />
472
+ );
473
+ }
474
+ ```
475
+
476
+ ## Security
477
+
478
+ The Pagiera API can create, modify, publish, and delete content. Protect `/editor`, `/preview`, and write operations under `/api/pagiera` with your application's authentication and authorization layer before deploying publicly.
479
+
480
+ Never expose `PAGIERA_POSTGRES_URL`, `PAGIERA_REDIS_URL`, or `OPENROUTER_API_KEY` to client components. These are server-only values.
481
+
482
+ ## Troubleshooting
483
+
484
+ ### `server.getEditorBootstrap is not a function`
485
+
486
+ Make sure all imports resolve to one installed Pagiera version. Remove stale local tarballs or lockfile entries, reinstall, and verify:
487
+
488
+ ```bash
489
+ node -p "require('pagiera/package.json').version"
490
+ ```
491
+
492
+ ### CSS says `@import` must precede other rules
493
+
494
+ Upgrade Pagiera. Current builds use `@font-face` for the editor font and do not distribute a Google Fonts `@import`.
495
+
496
+ ### PostgreSQL or Redis fails
497
+
498
+ Open `/api/pagiera/health`, then verify both connection URLs are reachable from the Next.js server process.
499
+
500
+ ### AI generation fails
501
+
502
+ Verify the OpenRouter key, model identifier, model availability, and account credits.
503
+
504
+ ### Published API data is missing from HTML
505
+
506
+ Use `server.getPublishedPage(...)` or `loadPageData(...)` in a Server Component before rendering `RenderedPage`. Client-only fetching does not provide the same SEO behavior.
507
+
508
+ ## Local package example
509
+
510
+ This repository includes `package-example`, a standalone consumer that installs the generated `.tgz` instead of importing package source files.
511
+
512
+ ```bash
513
+ cd package-example
514
+ cp .env.example .env.local
515
+ bun install
516
+ bun run dev
517
+ ```
518
+
519
+ Open:
520
+
521
+ - `/editor` — visual editor
522
+ - `/preview/:pageId` — draft renderer
523
+ - `/` — published `home` page
524
+ - `/api/pagiera/health` — backend diagnostics
525
+
526
+ ## License
527
+
528
+ MIT
@@ -0,0 +1,89 @@
1
+ import type { PagieraDocument } from "./document.js";
2
+ export type PagieraPageSummary = {
3
+ id: string;
4
+ name: string;
5
+ slug: string;
6
+ published?: boolean;
7
+ };
8
+ export type PagieraSaveResult = {
9
+ status: "saved";
10
+ version?: number;
11
+ } | {
12
+ status: "conflict";
13
+ document: PagieraDocument;
14
+ version?: number;
15
+ } | {
16
+ status: "error";
17
+ message: string;
18
+ };
19
+ export type PagieraDataPreview = {
20
+ rows: Array<Record<string, unknown>>;
21
+ keys: string[];
22
+ };
23
+ export type PagieraAdapters = {
24
+ persistence?: {
25
+ save(document: PagieraDocument, context: {
26
+ pageId?: string;
27
+ version?: number;
28
+ }): Promise<PagieraSaveResult>;
29
+ };
30
+ pages?: {
31
+ list(): Promise<PagieraPageSummary[]>;
32
+ load(pageId: string): Promise<PagieraDocument>;
33
+ create(input: {
34
+ name: string;
35
+ slug: string;
36
+ }): Promise<PagieraPageSummary>;
37
+ rename(pageId: string, input: {
38
+ name: string;
39
+ slug: string;
40
+ }): Promise<void>;
41
+ duplicate(pageId: string, input: {
42
+ name: string;
43
+ slug: string;
44
+ }): Promise<PagieraPageSummary>;
45
+ delete(pageId: string): Promise<void>;
46
+ publish(pageId: string, document: PagieraDocument): Promise<{
47
+ url?: string;
48
+ }>;
49
+ unpublish(pageId: string): Promise<void>;
50
+ };
51
+ ai?: {
52
+ generate(input: {
53
+ prompt: string;
54
+ document: PagieraDocument;
55
+ breakpoint: string;
56
+ history?: Array<{
57
+ role: "user" | "assistant";
58
+ text: string;
59
+ }>;
60
+ }): Promise<PagieraDocument>;
61
+ };
62
+ data?: {
63
+ preview(source: unknown, context?: Record<string, unknown>): Promise<PagieraDataPreview>;
64
+ };
65
+ assets?: {
66
+ upload(file: File): Promise<{
67
+ url: string;
68
+ name?: string;
69
+ }>;
70
+ list?(): Promise<Array<{
71
+ id: string;
72
+ name: string;
73
+ url: string;
74
+ type?: string;
75
+ }>>;
76
+ };
77
+ templates?: {
78
+ install(templateId: string): Promise<{
79
+ pages: PagieraPageSummary[];
80
+ activePageId?: string;
81
+ }>;
82
+ };
83
+ navigation?: {
84
+ openPage(pageId: string): void;
85
+ openPreview?(pageId?: string): void;
86
+ openPublished?(url: string): void;
87
+ };
88
+ };
89
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ export type PagieraClientOptions = {
2
+ baseUrl?: string;
3
+ fetch?: typeof globalThis.fetch;
4
+ };
5
+ /** Ready-to-pass adapters for `<PagieraStudio />`. */
6
+ export declare function createPagieraClient(options?: PagieraClientOptions): {
7
+ bootstrap: (pageId?: string) => Promise<any>;
8
+ loadPage: (pageId: string) => Promise<any>;
9
+ adapters: {
10
+ save: (pageId: string, document: unknown, expectedVersion: number) => Promise<any>;
11
+ createPage: (name: string, slug: string) => Promise<any>;
12
+ renamePage: (id: string, name: string, slug: string) => Promise<any>;
13
+ duplicatePage: (id: string, name: string, slug: string) => Promise<any>;
14
+ deletePage: (id: string) => Promise<any>;
15
+ installTemplate: (id: string) => Promise<any>;
16
+ publishPage: (id: string) => Promise<any>;
17
+ unpublishPage: (id: string) => Promise<any>;
18
+ previewSource: (source: unknown, sampleQuery: string) => Promise<any>;
19
+ generate: (request: unknown) => Promise<any>;
20
+ };
21
+ };
22
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACnC,CAAC;AAYF,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB;yBAOzC,MAAM;uBACR,MAAM;;uBAEN,MAAM,YAAY,OAAO,mBAAmB,MAAM;2BAC9C,MAAM,QAAQ,MAAM;yBACtB,MAAM,QAAQ,MAAM,QAAQ,MAAM;4BAC/B,MAAM,QAAQ,MAAM,QAAQ,MAAM;yBACrC,MAAM;8BACD,MAAM;0BACV,MAAM;4BACJ,MAAM;gCACF,OAAO,eAAe,MAAM;4BAChC,OAAO;;EAGtC"}
package/dist/client.js ADDED
@@ -0,0 +1,33 @@
1
+ async function jsonRequest(fetcher, url, init) {
2
+ const response = await fetcher(url, {
3
+ ...init,
4
+ headers: { "Content-Type": "application/json", ...init?.headers },
5
+ });
6
+ const body = await response.json().catch(() => null);
7
+ if (!response.ok)
8
+ throw new Error(body?.error ?? `Pagiera API request failed (${response.status})`);
9
+ return body;
10
+ }
11
+ /** Ready-to-pass adapters for `<PagieraStudio />`. */
12
+ export function createPagieraClient(options = {}) {
13
+ const base = (options.baseUrl ?? "/api/pagiera").replace(/\/$/, "");
14
+ const fetcher = options.fetch ?? globalThis.fetch;
15
+ const call = (path, method, body) => jsonRequest(fetcher, `${base}${path}`, { method, body: body === undefined ? undefined : JSON.stringify(body) });
16
+ return {
17
+ bootstrap: (pageId) => jsonRequest(fetcher, `${base}/bootstrap${pageId ? `?pageId=${encodeURIComponent(pageId)}` : ""}`),
18
+ loadPage: (pageId) => jsonRequest(fetcher, `${base}/pages/${pageId}`),
19
+ adapters: {
20
+ save: (pageId, document, expectedVersion) => call(`/pages/${pageId}/save`, "POST", { document, expectedVersion }),
21
+ createPage: (name, slug) => call("/pages", "POST", { name, slug }),
22
+ renamePage: (id, name, slug) => call(`/pages/${id}`, "PATCH", { name, slug }),
23
+ duplicatePage: (id, name, slug) => call(`/pages/${id}/duplicate`, "POST", { name, slug }),
24
+ deletePage: (id) => call(`/pages/${id}`, "DELETE"),
25
+ installTemplate: (id) => call(`/templates/${id}`, "POST"),
26
+ publishPage: (id) => call(`/pages/${id}/publish`, "POST"),
27
+ unpublishPage: (id) => call(`/pages/${id}/unpublish`, "POST"),
28
+ previewSource: (source, sampleQuery) => call("/data/preview", "POST", { source, sampleQuery }),
29
+ generate: (request) => call("/ai", "POST", request),
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}