@yak-io/nextjs 0.1.1 → 0.1.3

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.
package/README.md CHANGED
@@ -164,7 +164,7 @@ Behind the scenes `@yak-io/javascript` merges every `RouteSource` into a single
164
164
  yak-nextjs generate-manifest
165
165
  ```
166
166
 
167
- Use the CLI when you prefer to pre-compute a manifest at build time. The JSON matches the runtime manifest structure exposed by the handlers.
167
+ Use the CLI to pre-compute a manifest at build time. The JSON matches the runtime manifest structure exposed by the handlers.
168
168
 
169
169
  **Options:**
170
170
  - `--app-dir <path>` – Path to Next.js app directory (default: `./src/app`)
@@ -197,19 +197,9 @@ Add a `prebuild` script to generate the manifest before Next.js builds:
197
197
  }
198
198
  ```
199
199
 
200
- This uses the defaults (`./src/app` `./public/yak-routes-manifest.json`). Customize if needed:
200
+ That's it! The manifest is generated to `./public/yak-routes-manifest.json` and the handler automatically fetches it at runtime on serverless platforms like Vercel. No code changes needed.
201
201
 
202
- ```json
203
- {
204
- "scripts": {
205
- "prebuild": "yak-nextjs generate-manifest --app-dir ./app --output ./public/routes.json"
206
- }
207
- }
208
- ```
209
-
210
- The handler checks these locations automatically:
211
- 1. `./yak-routes-manifest.json`
212
- 2. `./public/yak-routes-manifest.json`
202
+ The handler automatically detects the deployment environment (Vercel via `VERCEL_URL`, Netlify via `URL`, or custom `NEXT_PUBLIC_BASE_URL`) and fetches the manifest from the public folder.
213
203
 
214
204
  ### Alternative: explicit routes
215
205
 
@@ -224,24 +214,14 @@ export const { GET, POST } = createNextYakHandler({
224
214
  });
225
215
  ```
226
216
 
227
- ### Loading a custom manifest location
228
-
229
- ```ts
230
- import { createNextYakHandler, loadRoutes } from "@yak-io/nextjs/server";
231
-
232
- export const { GET, POST } = createNextYakHandler({
233
- routes: loadRoutes("./custom/manifest.json"),
234
- });
235
- ```
236
-
237
217
  ## API surface (server)
238
218
 
239
219
  `@yak-io/nextjs/server` exports:
240
220
 
241
221
  - `scanRoutes(directory: string, options?: { directoryType?: "app" | "pages" })` – low-level filesystem scanner (useful for precomputing manifests or composing custom sources). Only captures page routes, extracting `title` and `description` from static metadata exports.
242
- - `loadRouteManifest(path?: string)` – load a pre-built JSON manifest, returns `null` if not found. Checks `./yak-routes-manifest.json` and `./public/yak-routes-manifest.json` by default.
222
+ - `loadRouteManifest(path?: string)` – load a pre-built JSON manifest via filesystem read, returns `null` if not found.
243
223
  - `loadRoutes(path?: string)` – load routes from a manifest, throws with helpful error if not found.
244
- - `createNextYakHandler(config)` – unified GET + POST handler (wrapping `createYakHandler`). When `routes`/`getRoutes` are omitted it auto-scans `./src/app` and `./src/pages` (override with `appDir`/`pagesDir`, and narrow results via `routeFilter?: { include?: RegExp[]; exclude?: RegExp[] }`). In production, automatically falls back to pre-built manifests.
224
+ - `createNextYakHandler(config)` – unified GET + POST handler. When `routes`/`getRoutes` are omitted it auto-scans `./src/app` (override with `appDir`). In production, automatically fetches manifest from public folder.
245
225
  - `createNextYakConfigHandler(config)` – GET-only convenience wrapper.
246
226
  - `createNextYakToolsHandler(config)` – POST-only wrapper.
247
227
  - Re-exported types from `@yak-io/javascript/server` (RouteInfo, RouteManifest, ToolDefinition, ToolManifest, ToolExecutor, ChatConfig, RouteSourceInput, ToolSourceInput, etc.).
@@ -290,6 +290,7 @@ function main() {
290
290
  generated_at: new Date().toISOString(),
291
291
  };
292
292
  const outputPath = path.resolve(process.cwd(), output);
293
+ // Write JSON manifest
293
294
  fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
294
295
  console.log(`✅ Generated manifest with ${uniqueRoutes.length} page routes`);
295
296
  console.log(` Output: ${outputPath}`);
@@ -1,12 +1,11 @@
1
1
  import type { RouteSourceInput, ToolSourceInput, RouteInfo, RouteManifest, ToolManifest, ToolExecutor } from "@yak-io/javascript/server";
2
2
  /**
3
- * Load a pre-built route manifest from disk.
3
+ * Load a pre-built route manifest from disk (JSON file).
4
4
  *
5
- * This should be used in production environments where filesystem scanning
6
- * is not available (e.g., Vercel serverless functions).
5
+ * This works in traditional Node.js deployments where the filesystem is available.
7
6
  *
8
7
  * Generate the manifest at build time using:
9
- * yak-nextjs generate-manifest --app-dir ./src/app --output ./public/yak-routes-manifest.json
8
+ * yak-nextjs generate-manifest
10
9
  *
11
10
  * @param manifestPath - Path to the manifest JSON file (default: tries common locations)
12
11
  * @returns Route manifest or null if not found
@@ -1 +1 @@
1
- {"version":3,"file":"createNextYakHandler.d.ts","sourceRoot":"","sources":["../../src/server/createNextYakHandler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AAWnC;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgB7E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAa7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB;;;EAKhE;AA6FD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,wCAK5E;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,uCAW1E"}
1
+ {"version":3,"file":"createNextYakHandler.d.ts","sourceRoot":"","sources":["../../src/server/createNextYakHandler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AAiBnC;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgB7E;AAgED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAe7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB;;;EAKhE;AAmGD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,wCAK5E;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,uCAW1E"}
@@ -3,20 +3,24 @@ import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { scanRoutes } from "./scan-routes.js";
5
5
  /**
6
- * Default paths to check for pre-built route manifests
6
+ * Default paths to check for pre-built route manifests (JSON files).
7
+ * These are read via fs.readFileSync at runtime.
7
8
  */
8
9
  const DEFAULT_MANIFEST_PATHS = [
9
- "./yak-routes-manifest.json",
10
10
  "./public/yak-routes-manifest.json",
11
+ "./yak-routes-manifest.json",
11
12
  ];
12
13
  /**
13
- * Load a pre-built route manifest from disk.
14
+ * Public URL path where the manifest is served from (when in public/).
15
+ */
16
+ const PUBLIC_MANIFEST_URL = "/yak-routes-manifest.json";
17
+ /**
18
+ * Load a pre-built route manifest from disk (JSON file).
14
19
  *
15
- * This should be used in production environments where filesystem scanning
16
- * is not available (e.g., Vercel serverless functions).
20
+ * This works in traditional Node.js deployments where the filesystem is available.
17
21
  *
18
22
  * Generate the manifest at build time using:
19
- * yak-nextjs generate-manifest --app-dir ./src/app --output ./public/yak-routes-manifest.json
23
+ * yak-nextjs generate-manifest
20
24
  *
21
25
  * @param manifestPath - Path to the manifest JSON file (default: tries common locations)
22
26
  * @returns Route manifest or null if not found
@@ -37,6 +41,59 @@ export function loadRouteManifest(manifestPath) {
37
41
  }
38
42
  return null;
39
43
  }
44
+ /**
45
+ * Fetch the route manifest from the public URL.
46
+ * Used in serverless environments where filesystem access is not available.
47
+ */
48
+ async function fetchRouteManifest() {
49
+ // Try to determine the base URL for fetching
50
+ const baseUrl = getBaseUrl();
51
+ if (!baseUrl) {
52
+ return null;
53
+ }
54
+ try {
55
+ const url = new URL(PUBLIC_MANIFEST_URL, baseUrl);
56
+ const response = await fetch(url.toString(), {
57
+ headers: { "Accept": "application/json" },
58
+ cache: "no-store",
59
+ });
60
+ if (!response.ok) {
61
+ return null;
62
+ }
63
+ const manifest = await response.json();
64
+ if (manifest?.routes) {
65
+ return manifest;
66
+ }
67
+ }
68
+ catch {
69
+ // Fetch failed
70
+ }
71
+ return null;
72
+ }
73
+ /**
74
+ * Get the base URL for the current deployment.
75
+ * Supports Vercel, Netlify, and custom configurations.
76
+ */
77
+ function getBaseUrl() {
78
+ // Vercel provides VERCEL_URL (without protocol)
79
+ if (process.env.VERCEL_URL) {
80
+ const protocol = process.env.VERCEL_ENV === "development" ? "http" : "https";
81
+ return `${protocol}://${process.env.VERCEL_URL}`;
82
+ }
83
+ // Netlify provides URL
84
+ if (process.env.URL) {
85
+ return process.env.URL;
86
+ }
87
+ // Custom base URL
88
+ if (process.env.NEXT_PUBLIC_BASE_URL) {
89
+ return process.env.NEXT_PUBLIC_BASE_URL;
90
+ }
91
+ // For local development
92
+ if (process.env.NODE_ENV === "development") {
93
+ return "http://localhost:3000";
94
+ }
95
+ return null;
96
+ }
40
97
  /**
41
98
  * Load routes from a pre-built manifest.
42
99
  * Throws if manifest is not found.
@@ -44,11 +101,13 @@ export function loadRouteManifest(manifestPath) {
44
101
  export function loadRoutes(manifestPath) {
45
102
  const manifest = loadRouteManifest(manifestPath);
46
103
  if (!manifest) {
47
- const pathsChecked = manifestPath ? manifestPath : DEFAULT_MANIFEST_PATHS.join(", ");
104
+ const pathsChecked = manifestPath
105
+ ? manifestPath
106
+ : [...DEFAULT_MANIFEST_PATHS].join(", ");
48
107
  throw new Error(`Route manifest not found. Checked: ${pathsChecked}\n\n` +
49
108
  `In production environments (like Vercel), route scanning requires a pre-built manifest.\n` +
50
109
  `Generate it at build time by adding to your build script:\n\n` +
51
- ` yak-nextjs generate-manifest --app-dir ./src/app --output ./public/yak-routes-manifest.json\n\n` +
110
+ ` yak-nextjs generate-manifest\n\n` +
52
111
  `Or provide routes explicitly in your handler configuration.`);
53
112
  }
54
113
  return manifest.routes;
@@ -63,30 +122,36 @@ export function createNextYakHandler(config) {
63
122
  });
64
123
  }
65
124
  /**
66
- * Attempt to scan routes from filesystem, with production-safe fallback.
125
+ * Attempt to load routes from filesystem or fetch from public URL.
67
126
  *
68
127
  * In development: scans the app directory directly
69
- * In production (Vercel, etc.): falls back to pre-built manifest if directory doesn't exist
128
+ * In production (Vercel, etc.): falls back to pre-built manifest via filesystem or HTTP fetch
70
129
  */
71
- function tryLoadRoutes(appDir) {
130
+ async function tryLoadRoutes(appDir) {
72
131
  const targetDir = path.resolve(process.cwd(), appDir);
73
132
  // If the app directory exists, scan it directly (development mode)
74
133
  if (fs.existsSync(targetDir)) {
75
134
  return scanRoutes(appDir);
76
135
  }
77
- // In production, the source directory doesn't exist - try loading from manifest
136
+ // In production, the source directory doesn't exist - try loading from manifest file
78
137
  const manifest = loadRouteManifest();
79
138
  if (manifest) {
80
139
  return manifest.routes;
81
140
  }
141
+ // Try fetching from public URL (works on Vercel/serverless)
142
+ const fetchedManifest = await fetchRouteManifest();
143
+ if (fetchedManifest) {
144
+ return fetchedManifest.routes;
145
+ }
82
146
  // Neither source nor manifest available - provide helpful error
83
147
  throw new Error(`App directory not found: ${targetDir}\n\n` +
84
148
  `This typically happens in production (Vercel, etc.) where source files aren't deployed.\n\n` +
85
149
  `Solutions:\n` +
86
- `1. Generate a route manifest at build time:\n` +
87
- ` Add to your build script: yak-nextjs generate-manifest --app-dir ./src/app --output ./public/yak-routes-manifest.json\n\n` +
150
+ `1. Generate a route manifest at build time (recommended):\n` +
151
+ ` Add to package.json: "prebuild": "yak-nextjs generate-manifest"\n` +
152
+ ` The manifest will be placed in public/ and automatically loaded.\n\n` +
88
153
  `2. Provide routes explicitly:\n` +
89
- ` createNextYakHandler({ routes: [...] })\n\n` +
154
+ ` createNextYakHandler({ routes: [{ path: "/", title: "Home" }, ...] })\n\n` +
90
155
  `3. Use getRoutes callback:\n` +
91
156
  ` createNextYakHandler({ getRoutes: async () => [...] })`);
92
157
  }
@@ -97,7 +162,10 @@ function resolveRouteSources(config) {
97
162
  if (config.getRoutes) {
98
163
  return config.getRoutes;
99
164
  }
100
- return async () => applyRouteFilters(tryLoadRoutes(config.appDir ?? "./src/app"), config.routeFilter);
165
+ return async () => {
166
+ const routes = await tryLoadRoutes(config.appDir ?? "./src/app");
167
+ return applyRouteFilters(routes, config.routeFilter);
168
+ };
101
169
  }
102
170
  function applyRouteFilters(routes, filter) {
103
171
  if (!filter) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/nextjs",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Next.js SDK for embedding yak chatbot with route manifest generation",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",