Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ content/upstream/docs/
content/upstream/docs-subset/
content/upstream/sidebars.ts
content/upstream/CHANGELOG.md
content/upstream/prompts.yml
prototypes/docusaurus/docs/

.DS_Store
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
"scripts": {
"sync:docs": "node scripts/sync-docs.mjs",
"sync:docs:subset": "node scripts/sync-docs.mjs --subset",
"prepare:docs": "node scripts/prepare-docs.mjs --target docusaurus",
"prepare:docs": "node scripts/prepare-docs.mjs --target docusaurus && npm run prepare:prompts",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't overwrite generated prompts before checking drift

In the inspected CI workflow (.github/workflows/site-build-deploy.yml), the Prepare docs step runs before Build site; with this change, prepare:docs rewrites prompts.ts, prompts.json, and llms.txt before npm run build reaches prepare:prompts:check. That means a PR with hand-edited or stale generated prompt artifacts passes CI because the files are regenerated in the workspace first, leaving the committed tracked artifacts drifted after merge. If these artifacts are meant to be tracked, keep generation separate from the pre-build check or add a dirty-worktree/drift check before overwriting them.

Useful? React with 👍 / 👎.

"prepare:docs:subset": "node scripts/prepare-docs.mjs --target docusaurus --subset",
"prepare:prompts": "node scripts/prepare-prompts.mjs",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Subset workflow leaves prompt artifacts stale, breaking build

prepare:docs:subset runs prepare-docs.mjs --subset but does not chain prepare:prompts. The full build script now opens with prepare:prompts:check, so anyone who runs npm run prepare:subset && npm run build will hit a drift-guard failure because the subset prepare never (re)generates the prompt artifacts. Adding && npm run prepare:prompts to prepare:docs:subset — mirroring what was done for prepare:docs — would keep the two paths consistent.

"prepare:prompts:check": "node scripts/prepare-prompts.mjs --check",
"audit:docs": "node scripts/audit-docs.mjs",
"prepare": "npm run sync:docs && npm run prepare:docs",
"prepare:subset": "npm run sync:docs:subset && npm run prepare:docs:subset",
"test:docs-layout": "node --test scripts/docs-layout.test.mjs",
"test:prepare-prompts": "node --test scripts/prepare-prompts.test.mjs",
"install:site": "npm --prefix prototypes/docusaurus install",
"dev": "npm --prefix prototypes/docusaurus run start",
"build": "npm --prefix prototypes/docusaurus run build",
"build": "npm run prepare:prompts:check && npm --prefix prototypes/docusaurus run build",
"build:full": "npm run prepare && npm run build",
"cloudflare:deploy": "npm run build:full && npx wrangler pages deploy prototypes/docusaurus/build --project-name ${CLOUDFLARE_PAGES_PROJECT:-reactonrails-com}"
}
Expand Down
200 changes: 90 additions & 110 deletions prototypes/docusaurus/src/constants/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,139 +1,108 @@
import {docsRoutes} from './docsRoutes';
/*
* GENERATED FILE - DO NOT EDIT.
* Source: content/upstream/prompts.yml
* Regenerate with `npm run prepare:prompts`.
*/
export const SITE_URL = "https://reactonrails.com";

/** Canonical site origin; matches `url` in docusaurus.config.ts. */
export const SITE_URL = 'https://reactonrails.com';

/** Shown once per surface (home Quick Start + /prompts hero). */
export const agentNote =
"Paste into Cursor, Claude Code, Copilot, or any AI assistant. Each prompt points the agent at the official docs so it doesn't guess.";
export const agentNote = "Paste into Cursor, Claude Code, Copilot, or any AI assistant. Each prompt points the agent at the official docs so it doesn't guess.";

export type PromptCategory =
| 'get-started'
| 'server-rendering'
| 'migrate'
| 'features'
| 'production';
| "get-started"
| "server-rendering"
| "migrate"
| "features"
| "production";

export type Prompt = {
/** Stable slug; used as React key and to select the homepage subset. */
id: string;
title: string;
/** Copy-able prompt text. Embeds an absolute docs URL so the agent grounds itself. */
prompt: string;
/** Docs route the "Open guide →" link points to (relative; from docsRoutes). */
href: string;
category: PromptCategory;
};

/** Absolute docs URL embedded in prompt text so agents fetch the real guide. */
function docUrl(route: string): string {
return `${SITE_URL}${route}`;
}

export const prompts: Prompt[] = [
{
id: 'turn-on-rsc',
title: 'Turn on React Server Components',
prompt: `Turn on React Server Components in my React on Rails app (no license required). Follow ${docUrl(
docsRoutes.proReactServerComponents,
)} exactly, including the renderer and packer setup it specifies.`,
href: docsRoutes.proReactServerComponents,
category: 'server-rendering',
"id": "create-app",
"title": "Start a new app",
"prompt": "Set up a new Rails app with React on Rails, using TypeScript and server-side rendering. Follow the official guide at https://reactonrails.com/docs/getting-started/create-react-on-rails-app and use the exact commands and versions it specifies — don't improvise.",
"href": "/docs/getting-started/create-react-on-rails-app",
"category": "get-started"
},
{
id: 'create-app',
title: 'Start a new app',
prompt: `Set up a new Rails app with React on Rails, using TypeScript and server-side rendering. Follow the official guide at ${docUrl(
docsRoutes.createApp,
)} and use the exact commands and versions it specifies — don't improvise.`,
href: docsRoutes.createApp,
category: 'get-started',
"id": "install-existing",
"title": "Add to an existing Rails app",
"prompt": "Add React on Rails to my existing Rails app with TypeScript, keeping my current routes and conventions. Follow https://reactonrails.com/docs/getting-started/existing-rails-app and don't change any gem or package versions it doesn't tell you to.",
"href": "/docs/getting-started/existing-rails-app",
"category": "get-started"
},
{
id: 'install-existing',
title: 'Add to an existing Rails app',
prompt: `Add React on Rails to my existing Rails app with TypeScript, keeping my current routes and conventions. Follow ${docUrl(
docsRoutes.installExistingApp,
)} and don't change any gem or package versions it doesn't tell you to.`,
href: docsRoutes.installExistingApp,
category: 'get-started',
"id": "turn-on-rsc",
"title": "Turn on React Server Components",
"prompt": "Turn on React Server Components in my React on Rails app (no license required). Follow https://reactonrails.com/docs/pro/react-server-components exactly, including the renderer and packer setup it specifies.",
"href": "/docs/pro/react-server-components",
"category": "server-rendering"
},
{
id: 'streaming-ssr',
title: 'Add streaming SSR',
prompt: `Add streaming server-side rendering to my React on Rails app. Follow ${docUrl(
docsRoutes.proStreamingSsr,
)} exactly and don't change versions it doesn't ask you to.`,
href: docsRoutes.proStreamingSsr,
category: 'server-rendering',
"id": "streaming-ssr",
"title": "Add streaming SSR",
"prompt": "Add streaming server-side rendering to my React on Rails app. Follow https://reactonrails.com/docs/pro/streaming-ssr exactly and don't change versions it doesn't ask you to.",
"href": "/docs/pro/streaming-ssr",
"category": "server-rendering"
},
{
id: 'async-rendering',
title: 'Use async/Suspense rendering',
prompt: `Set up async (Suspense) rendering for a React on Rails component. Follow ${docUrl(
docsRoutes.proAsyncRendering,
)} exactly.`,
href: docsRoutes.proAsyncRendering,
category: 'server-rendering',
"id": "async-rendering",
"title": "Use async/Suspense rendering",
"prompt": "Set up async (Suspense) rendering for a React on Rails component. Follow https://reactonrails.com/docs/api-reference/ruby-api-pro#async_react_componentcomponent_name-options-- exactly.",
"href": "/docs/api-reference/ruby-api-pro#async_react_componentcomponent_name-options--",
"category": "server-rendering"
},
{
id: 'migrate-react-rails',
title: 'Migrate from react-rails',
prompt: `Migrate my app from react-rails to React on Rails, keeping my existing components working. Follow ${docUrl(
docsRoutes.migrateFromReactRails,
)} and don't skip any step it lists.`,
href: docsRoutes.migrateFromReactRails,
category: 'migrate',
"id": "migrate-react-rails",
"title": "Migrate from react-rails",
"prompt": "Migrate my app from react-rails to React on Rails, keeping my existing components working. Follow https://reactonrails.com/docs/migrating/migrating-from-react-rails and don't skip any step it lists.",
"href": "/docs/migrating/migrating-from-react-rails",
"category": "migrate"
},
{
id: 'code-splitting',
title: 'Add code splitting',
prompt: `Add code splitting / lazy loading to my React on Rails components. Follow ${docUrl(
docsRoutes.codeSplitting,
)} exactly.`,
href: docsRoutes.codeSplitting,
category: 'features',
"id": "code-splitting",
"title": "Add code splitting",
"prompt": "Add code splitting / lazy loading to my React on Rails components. Follow https://reactonrails.com/docs/building-features/code-splitting exactly.",
"href": "/docs/building-features/code-splitting",
"category": "features"
},
{
id: 'oss-vs-pro',
title: 'Evaluate OSS vs Pro',
prompt: `Review my React on Rails setup and tell me whether OSS or Pro fits my workload, citing the tradeoffs. Base your answer on ${docUrl(
docsRoutes.ossVsPro,
)}.`,
href: docsRoutes.ossVsPro,
category: 'production',
"id": "oss-vs-pro",
"title": "Evaluate OSS vs Pro",
"prompt": "Review my React on Rails setup and tell me whether OSS or Pro fits my workload, citing the tradeoffs. Base your answer on https://reactonrails.com/docs/getting-started/oss-vs-pro.",
"href": "/docs/getting-started/oss-vs-pro",
"category": "production"
},
{
id: 'node-renderer',
title: 'Set up the Node renderer',
prompt: `Set up the React on Rails Pro Node renderer for server rendering. Follow ${docUrl(
docsRoutes.proNodeRenderer,
)} exactly, including the configuration it specifies.`,
href: docsRoutes.proNodeRenderer,
category: 'production',
"id": "node-renderer",
"title": "Set up the Node renderer",
"prompt": "Set up the React on Rails Pro Node renderer for server rendering. Follow https://reactonrails.com/docs/pro/node-renderer exactly, including the configuration it specifies.",
"href": "/docs/pro/node-renderer",
"category": "production"
},
{
id: 'fragment-caching',
title: 'Add fragment caching',
prompt: `Add fragment caching to my server-rendered React on Rails components. Follow ${docUrl(
docsRoutes.proFragmentCaching,
)} exactly.`,
href: docsRoutes.proFragmentCaching,
category: 'production',
"id": "fragment-caching",
"title": "Add fragment caching",
"prompt": "Add fragment caching to my server-rendered React on Rails components. Follow https://reactonrails.com/docs/pro/fragment-caching exactly.",
"href": "/docs/pro/fragment-caching",
"category": "production"
},
{
id: 'upgrade-to-pro',
title: 'Get a production license / upgrade to Pro',
prompt: `Walk me through upgrading my React on Rails app to Pro and getting a production license. Follow ${docUrl(
docsRoutes.proUpgrade,
)}.`,
href: docsRoutes.proUpgrade,
category: 'production',
},
"id": "upgrade-to-pro",
"title": "Get a production license / upgrade to Pro",
"prompt": "Walk me through upgrading my React on Rails app to Pro and getting a production license. Follow https://reactonrails.com/docs/pro/upgrading-to-pro.",
"href": "/docs/pro/upgrading-to-pro",
"category": "production"
}
];

/** Curated, ordered subset for the home Quick Start: RSC first (marquee). */
const homePromptIds = ['turn-on-rsc', 'create-app', 'install-existing'] as const;
const homePromptIds = ["turn-on-rsc","create-app","install-existing"] as const;

export const homePrompts: Prompt[] = homePromptIds.map((id) => {
const found = prompts.find((prompt) => prompt.id === id);
Expand All @@ -149,19 +118,30 @@ export type PromptGroup = {
heading: string;
};

/** Display order of categories on /prompts. */
export const promptGroups: PromptGroup[] = [
{category: 'get-started', eyebrow: 'Get started', heading: 'Spin up React on Rails.'},
{
category: 'server-rendering',
eyebrow: 'Server rendering',
heading: 'Render on the server: RSC, SSR, streaming.',
"category": "get-started",
"eyebrow": "Get started",
"heading": "Spin up React on Rails."
},
{
"category": "server-rendering",
"eyebrow": "Server rendering",
"heading": "Render on the server: RSC, SSR, streaming."
},
{
"category": "migrate",
"eyebrow": "Migrate",
"heading": "Move an existing setup to React on Rails."
},
{category: 'migrate', eyebrow: 'Migrate', heading: 'Move an existing setup to React on Rails.'},
{category: 'features', eyebrow: 'Build features', heading: 'Add common capabilities.'},
{
category: 'production',
eyebrow: 'Optimize & go to production',
heading: 'Tune performance and ship with Pro.',
"category": "features",
"eyebrow": "Build features",
"heading": "Add common capabilities."
},
{
"category": "production",
"eyebrow": "Optimize & go to production",
"heading": "Tune performance and ship with Pro."
}
];
104 changes: 104 additions & 0 deletions prototypes/docusaurus/static/llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# React on Rails AI Prompts

Source: https://reactonrails.com/prompts.json
Schema version: 1

Paste into Cursor, Claude Code, Copilot, or any AI assistant. Each prompt points the agent at the official docs so it doesn't guess.

## Get started

### Start a new app

ID: create-app
Category: get-started
Doc: https://reactonrails.com/docs/getting-started/create-react-on-rails-app

Set up a new Rails app with React on Rails, using TypeScript and server-side rendering. Follow the official guide at https://reactonrails.com/docs/getting-started/create-react-on-rails-app and use the exact commands and versions it specifies — don't improvise.

### Add to an existing Rails app

ID: install-existing
Category: get-started
Doc: https://reactonrails.com/docs/getting-started/existing-rails-app

Add React on Rails to my existing Rails app with TypeScript, keeping my current routes and conventions. Follow https://reactonrails.com/docs/getting-started/existing-rails-app and don't change any gem or package versions it doesn't tell you to.

## Server rendering

### Turn on React Server Components

ID: turn-on-rsc
Category: server-rendering
Doc: https://reactonrails.com/docs/pro/react-server-components

Turn on React Server Components in my React on Rails app (no license required). Follow https://reactonrails.com/docs/pro/react-server-components exactly, including the renderer and packer setup it specifies.

### Add streaming SSR

ID: streaming-ssr
Category: server-rendering
Doc: https://reactonrails.com/docs/pro/streaming-ssr

Add streaming server-side rendering to my React on Rails app. Follow https://reactonrails.com/docs/pro/streaming-ssr exactly and don't change versions it doesn't ask you to.

### Use async/Suspense rendering

ID: async-rendering
Category: server-rendering
Doc: https://reactonrails.com/docs/api-reference/ruby-api-pro#async_react_componentcomponent_name-options--

Set up async (Suspense) rendering for a React on Rails component. Follow https://reactonrails.com/docs/api-reference/ruby-api-pro#async_react_componentcomponent_name-options-- exactly.

## Migrate

### Migrate from react-rails

ID: migrate-react-rails
Category: migrate
Doc: https://reactonrails.com/docs/migrating/migrating-from-react-rails

Migrate my app from react-rails to React on Rails, keeping my existing components working. Follow https://reactonrails.com/docs/migrating/migrating-from-react-rails and don't skip any step it lists.

## Build features

### Add code splitting

ID: code-splitting
Category: features
Doc: https://reactonrails.com/docs/building-features/code-splitting

Add code splitting / lazy loading to my React on Rails components. Follow https://reactonrails.com/docs/building-features/code-splitting exactly.

## Optimize & go to production

### Evaluate OSS vs Pro

ID: oss-vs-pro
Category: production
Doc: https://reactonrails.com/docs/getting-started/oss-vs-pro

Review my React on Rails setup and tell me whether OSS or Pro fits my workload, citing the tradeoffs. Base your answer on https://reactonrails.com/docs/getting-started/oss-vs-pro.

### Set up the Node renderer

ID: node-renderer
Category: production
Doc: https://reactonrails.com/docs/pro/node-renderer

Set up the React on Rails Pro Node renderer for server rendering. Follow https://reactonrails.com/docs/pro/node-renderer exactly, including the configuration it specifies.

### Add fragment caching

ID: fragment-caching
Category: production
Doc: https://reactonrails.com/docs/pro/fragment-caching

Add fragment caching to my server-rendered React on Rails components. Follow https://reactonrails.com/docs/pro/fragment-caching exactly.

### Get a production license / upgrade to Pro

ID: upgrade-to-pro
Category: production
Doc: https://reactonrails.com/docs/pro/upgrading-to-pro

Walk me through upgrading my React on Rails app to Pro and getting a production license. Follow https://reactonrails.com/docs/pro/upgrading-to-pro.
Loading
Loading