Conversation
📝 WalkthroughWalkthroughAdds a Next.js route handler at Changes
Sequence DiagramsequenceDiagram
participant User
participant Handler
participant FS
participant PlatformApi
User->>Handler: GET /llm-rules/create-app/AGENTS.md?title=...
Handler->>FS: readFile('lib/intern/instant-rules.md')
Handler->>Handler: read env vars and validate
Handler->>PlatformApi: createApp({ title, orgId }, auth=token)
PlatformApi-->>Handler: { id, adminToken }
Handler->>User: 200 text/markdown (credentials + base rules, no-cache, inline, noindex)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts (2)
12-47: No error handling aroundfs.readFile/createTemporaryApp.Any failure (missing rules file, API down, network error) will bubble up as an unformatted 500. Since the consumer is an agent tool fetching Markdown, returning a structured Markdown error (or at least a clean status + short message) would be more useful than a stack dump and won’t leak internals.
Sketch
export async function GET(request: Request) { - const title = - new URL(request.url).searchParams.get('title')?.trim() || - DEFAULT_APP_TITLE; - const baseRules = await fs.readFile(RULES_PATH, 'utf8'); - const { apiURI } = await getServerConfig(); - const api = new PlatformApi({ apiURI }); - const { app, expiresMs } = await api.createTemporaryApp({ title }); + try { + const title = + new URL(request.url).searchParams.get('title')?.trim() || + DEFAULT_APP_TITLE; + const baseRules = await fs.readFile(RULES_PATH, 'utf8'); + const { apiURI } = await getServerConfig(); + const api = new PlatformApi({ apiURI }); + const { app, expiresMs } = await api.createTemporaryApp({ title }); + // ...build + return response + } catch (err) { + console.error('create-app AGENTS.md failed', err); + return new Response('# Error\n\nCould not provision a temporary Instant app. Please try again.', { + status: 502, + headers: { 'Content-Type': 'text/markdown; charset=utf-8' }, + }); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` around lines 12 - 47, The GET handler should guard calls to fs.readFile(RULES_PATH) and api.createTemporaryApp by wrapping them in a try/catch (or separate try blocks) so errors don’t surface as raw 500s; catch filesystem or network errors from fs.readFile and PlatformApi.createTemporaryApp and return a well-formed Markdown response (e.g., a short error message header and brief human-safe details) with the same headers used for AGENTS.md plus an appropriate HTTP status (e.g., 500) and omit stack traces or sensitive internals; ensure you reference the GET function, RULES_PATH, fs.readFile, and PlatformApi.createTemporaryApp so the error handling is applied exactly around those calls.
9-9: Resolveprocess.cwd()coupling in path resolution.Using
process.cwd()works fromclient/www, but breaks if the process starts from a different working directory (e.g., Docker, monorepo runners). This pattern appears elsewhere in the codebase (og-preview/page.tsx,api/chat/route.ts).Prefer resolving relative to the module since route.ts uses ES modules:
import { fileURLToPath } from 'url'; const RULES_PATH = path.join( path.dirname(fileURLToPath(import.meta.url)), '../../../../lib/intern/instant-rules.md', );Alternatively, add the file to
outputFileTracingIncludesinnext.config.jsto guarantee it ships with the bundle:const nextConfig = { // ... existing config outputFileTracingIncludes: { '/app/llm-rules/create-app/AGENTS.md/route': ['./lib/intern/instant-rules.md'], }, };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` at line 9, Replace the process.cwd() based RULES_PATH resolution in route.ts with module-relative resolution: import fileURLToPath from 'url' and compute path.dirname(fileURLToPath(import.meta.url)) then join it with the relative path to '../../../../lib/intern/instant-rules.md' to form RULES_PATH; alternatively, if you intend to bundle the file, add the entry for '/app/llm-rules/create-app/AGENTS.md/route' pointing to './lib/intern/instant-rules.md' under outputFileTracingIncludes in next.config.js so the file is included in the build. Ensure you update the RULES_PATH constant (and any other occurrences like in og-preview/page.tsx or api/chat/route.ts) to use the module-relative approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Around line 12-19: The GET handler currently calls api.createTemporaryApp for
any public request; to prevent abuse, require and validate a short-lived signed
nonce/referral before creating an app: modify the exported GET function to check
for a nonce (e.g., query param "nonce" or a header), verify it against a
server-side nonce cache or signature (issued by the create-app UI) and reject
with 400/403 if invalid, only calling PlatformApi.createTemporaryApp({ title })
after successful validation; additionally, add or wire up an IP rate-limit check
(middleware or simple in-memory counter keyed by request.ip) in the same GET
path as a fallback to throttle repeated requests.
- Around line 13-19: The title query param is passed straight to
createTemporaryApp without validation; update the extraction logic around title
(the variable defined in route.ts) to trim, reject or sanitize invalid
characters, and enforce a max length (e.g., 100 chars) — if the result is empty
or invalid, set title = DEFAULT_APP_TITLE before calling new
PlatformApi(...).createTemporaryApp; keep using getServerConfig(), RULES_PATH
and PlatformApi but ensure the sanitized/length-bounded title is what gets
forwarded to createTemporaryApp.
---
Nitpick comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Around line 12-47: The GET handler should guard calls to
fs.readFile(RULES_PATH) and api.createTemporaryApp by wrapping them in a
try/catch (or separate try blocks) so errors don’t surface as raw 500s; catch
filesystem or network errors from fs.readFile and PlatformApi.createTemporaryApp
and return a well-formed Markdown response (e.g., a short error message header
and brief human-safe details) with the same headers used for AGENTS.md plus an
appropriate HTTP status (e.g., 500) and omit stack traces or sensitive
internals; ensure you reference the GET function, RULES_PATH, fs.readFile, and
PlatformApi.createTemporaryApp so the error handling is applied exactly around
those calls.
- Line 9: Replace the process.cwd() based RULES_PATH resolution in route.ts with
module-relative resolution: import fileURLToPath from 'url' and compute
path.dirname(fileURLToPath(import.meta.url)) then join it with the relative path
to '../../../../lib/intern/instant-rules.md' to form RULES_PATH; alternatively,
if you intend to bundle the file, add the entry for
'/app/llm-rules/create-app/AGENTS.md/route' pointing to
'./lib/intern/instant-rules.md' under outputFileTracingIncludes in
next.config.js so the file is included in the build. Ensure you update the
RULES_PATH constant (and any other occurrences like in og-preview/page.tsx or
api/chat/route.ts) to use the module-relative approach.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: efe9c971-c06a-4f0c-9345-9b235303c5ed
📒 Files selected for processing (1)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts
|
View Vercel preview at instant-www-js-codex-llm-rules-create-app-jsv.vercel.app. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts (2)
17-17: Unhandled rejection risk on module-levelfs.readFile.
baseRulesPromisestarts at module load with no.catch. IfRULES_PATHis missing (e.g. file renamed, deploy layout change), this produces an unhandled promise rejection at import time and every subsequent request rejects with the same error. Consider reading inside the handler (withcache: 'force-cache'-style memoization) or attaching a catch that surfaces a clean 500.♻️ Example
-const baseRulesPromise = fs.readFile(RULES_PATH, 'utf8'); +let baseRulesPromise: Promise<string> | null = null; +function loadBaseRules() { + if (!baseRulesPromise) { + baseRulesPromise = fs.readFile(RULES_PATH, 'utf8').catch((err) => { + baseRulesPromise = null; // allow retry on next request + throw err; + }); + } + return baseRulesPromise; +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` at line 17, baseRulesPromise is created at module load via fs.readFile(RULES_PATH, 'utf8') and can cause unhandled rejections if the file is missing; move the read into the request-handling path or wrap it in a memoized accessor that handles errors. Create a getBaseRules() (or similar) function used by the route handler that reads RULES_PATH on first call, stores the resolved string in a module-level cache, and on failure catches the error and throws/returns a sanitized error so the handler can respond with a 500; alternatively, keep baseRulesPromise but attach a .catch that converts the error into a controlled rejection and ensure the GET handler checks and returns a clean 500 when the read fails. Ensure you reference baseRulesPromise and RULES_PATH when making the change.
36-53: Minor: stray trailing whitespace and heading hierarchy in the template.Lines 37 and 46 end with a trailing space, and the
---on line 51 is used as a separator after a bullet-style note rather than between sections, which some Markdown renderers will interpret as turning line 50 into a setext H2. Not a functional bug, but worth tightening since the output is served astext/markdownand piped directly to agents.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` around lines 36 - 53, In the markdown template assigned to the markdown constant in route.ts, remove the stray trailing spaces at the ends of the sentences (currently after the "You've just..." line and the "Note: You don't have access to npx." line) and replace the lone '---' separator after the Note with either a blank line or an explicit section heading (e.g., "## Instructions") to avoid unintended setext H2 rendering; update the markdown template string in the markdown variable accordingly to ensure clean whitespace and correct heading hierarchy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Around line 31-34: The createApp call in route.ts currently uses a hardcoded
orgId and lacks error handling; extract orgId into configuration (e.g., use an
env/runtime config value such as process.env.DEFAULT_ORG_ID or a next/config
entry and reference that when calling createApp) so staging/prod can override
ownership, and wrap the createApp(...) invocation in a try/catch around the
block where const { app } = await api.createApp(...) to catch network/auth/quota
errors, log the error (using the existing logger) with context and return a
controlled error response to the client instead of letting Next throw a raw 500.
- Around line 24-29: The file commits a hardcoded Platform API token in the
PlatformApi instantiation; remove the literal token and instead retrieve the
secret from the server config/environment via getServerConfig() (use
process.env.INSTANT_PLATFORM_TOKEN or the already-imported getServerConfig() to
read the token) and pass that value into new PlatformApi({ auth: { token: /*
env/token from getServerConfig */ } }); also ensure you use the server-only
instantAgentOrgId when constructing or calling PlatformApi where applicable so
no long-lived secret is checked into source control.
---
Nitpick comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Line 17: baseRulesPromise is created at module load via
fs.readFile(RULES_PATH, 'utf8') and can cause unhandled rejections if the file
is missing; move the read into the request-handling path or wrap it in a
memoized accessor that handles errors. Create a getBaseRules() (or similar)
function used by the route handler that reads RULES_PATH on first call, stores
the resolved string in a module-level cache, and on failure catches the error
and throws/returns a sanitized error so the handler can respond with a 500;
alternatively, keep baseRulesPromise but attach a .catch that converts the error
into a controlled rejection and ensure the GET handler checks and returns a
clean 500 when the read fails. Ensure you reference baseRulesPromise and
RULES_PATH when making the change.
- Around line 36-53: In the markdown template assigned to the markdown constant
in route.ts, remove the stray trailing spaces at the ends of the sentences
(currently after the "You've just..." line and the "Note: You don't have access
to npx." line) and replace the lone '---' separator after the Note with either a
blank line or an explicit section heading (e.g., "## Instructions") to avoid
unintended setext H2 rendering; update the markdown template string in the
markdown variable accordingly to ensure clean whitespace and correct heading
hierarchy.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7d954993-2516-4fd9-8a63-56f6190d7ab9
📒 Files selected for processing (1)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts
|
|
||
| What follows are instructions for using Instant. Follow them, and you are golden! | ||
|
|
||
| Note: You don't have access to npx. Instead of npx instant-cli, use INSTANT_APP_ID=... INSTANT_ADMIN_TOKEN=... pnpm dlx ... |
There was a problem hiding this comment.
Note: I hardcoded this for now, as the customer we are doing this demo for does not expose npx in their app builder. However they give access to pnpm, and pnpm dlx does the trick.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts (1)
25-32: Return a structured 500 instead of throwing for missing env vars.
throw new Error(...)here bubbles up as an opaque Next.js 500 with the error message potentially exposed in dev and swallowed in prod. Returning an explicitResponsekeeps the failure mode consistent with the rest of the handler and makes the misconfiguration observable to the caller/ops.♻️ Suggested shape
- if (!token) { - throw new Error( - 'INSTANT_LLM_RULES_CREATE_APP_PERSONAL_ACCESS_TOKEN is not set', - ); - } - if (!orgId) { - throw new Error('INSTANT_LLM_RULES_CREATE_APP_ORG_ID is not set'); - } + if (!token || !orgId) { + console.error('create-app AGENTS route is missing required env vars', { + hasToken: Boolean(token), + hasOrgId: Boolean(orgId), + }); + return new Response('Server is not configured for agent app creation', { + status: 500, + }); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` around lines 25 - 32, The code currently throws new Error when required env vars (token and orgId) are missing, which results in an opaque Next.js 500; instead update the route handler to return a structured 500 Response for both missing token and missing orgId (check the token and orgId variables and if falsy return new Response with a JSON body describing the missing variable, an appropriate message and an error code, set Content-Type: application/json, and status: 500) so the failure is observable and consistent with the other handler responses.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Line 16: The module-level promise baseRulesPromise (created from
fs.readFile(RULES_PATH, 'utf8')) can produce an unhandled rejection at import
time and permanently cache failures; move the file read into the GET handler so
reads happen lazily, wrap the fs.readFile call in try/catch inside GET to handle
transient errors, and if you want memoization only cache successful content
(e.g., store a string like baseRulesContent on success) rather than caching the
rejected promise; remove or stop using the module-level baseRulesPromise so
imports no longer risk unhandled rejections and stale errors.
---
Nitpick comments:
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts`:
- Around line 25-32: The code currently throws new Error when required env vars
(token and orgId) are missing, which results in an opaque Next.js 500; instead
update the route handler to return a structured 500 Response for both missing
token and missing orgId (check the token and orgId variables and if falsy return
new Response with a JSON body describing the missing variable, an appropriate
message and an error code, set Content-Type: application/json, and status: 500)
so the failure is observable and consistent with the other handler responses.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 76185b3e-d81f-4551-b4d9-016baec0012e
📒 Files selected for processing (1)
client/www/app/llm-rules/create-app/AGENTS.md/route.ts
| ); | ||
| const DEFAULT_APP_TITLE = 'instant-agent-app'; | ||
|
|
||
| const baseRulesPromise = fs.readFile(RULES_PATH, 'utf8'); |
There was a problem hiding this comment.
Module-level fs.readFile promise caches failures permanently and can trigger an unhandled rejection at import time.
baseRulesPromise is created eagerly when the module is loaded. Two concerns:
- If the file is missing or unreadable at startup, the rejection fires before any
awaitis attached synchronously — in some Node configurations this becomes an unhandled rejection and can terminate the process. - The rejection is cached forever on the shared promise; every subsequent request will keep throwing the same stale error until the server is restarted, even if the file becomes readable later.
Prefer reading lazily inside GET (optionally memoizing only on success), so transient errors don't poison the module.
♻️ Suggested shape
-const baseRulesPromise = fs.readFile(RULES_PATH, 'utf8');
+let cachedBaseRules: string | null = null;
+async function loadBaseRules(): Promise<string> {
+ if (cachedBaseRules !== null) return cachedBaseRules;
+ const contents = await fs.readFile(RULES_PATH, 'utf8');
+ cachedBaseRules = contents;
+ return contents;
+}
@@
- const baseRules = await baseRulesPromise;
+ const baseRules = await loadBaseRules();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@client/www/app/llm-rules/create-app/AGENTS.md/route.ts` at line 16, The
module-level promise baseRulesPromise (created from fs.readFile(RULES_PATH,
'utf8')) can produce an unhandled rejection at import time and permanently cache
failures; move the file read into the GET handler so reads happen lazily, wrap
the fs.readFile call in try/catch inside GET to handle transient errors, and if
you want memoization only cache successful content (e.g., store a string like
baseRulesContent on success) rather than caching the rejected promise; remove or
stop using the module-level baseRulesPromise so imports no longer risk unhandled
rejections and stale errors.
Sometimes we want to demo how good Instant would be for app builders.
Problem
In order for app builders to try us, they have to do two things:
This can cause some UX friction (crating an app requires signing up)
Solution
I created a new route: llm-rules/create-app/AGENTS.md.
This will (a) automatically generate an app, and (b) append the instant rules.
Users can try Instant in their own app builder, just by writing this prompt:
Note: I am currently using a personal access token rather than an ephemeral app. This is because for demos with large app builders, it would suck if someone tried to use an old demo a few weeks later, and the app broke.
@dwwoelfel @nezaj @drew-harris