Skip to content

Commit 23b9eb8

Browse files
authored
Init script agent mode and react option (#897)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- RECURSEML_SUMMARY:START --> ## High-level PR Summary This PR adds support for non-interactive initialization in the Stack Auth initialization script. It introduces a `STACK_DISABLE_INTERACTIVE` environment variable flag and makes appropriate changes throughout the codebase to handle non-interactive flows. The changes include improving type definitions, adding automatic determination of project type (JS vs Next.js) and configuration (client vs server) when running in non-interactive mode, and better error handling for cases where required information is missing. These changes enable CI/CD scenarios and automation for Stack Auth integration. ⏱️ Estimated Review Time: 0h 20m <details> <summary>💡 Review Order Suggestion</summary> | Order | File Path | |-------|-----------| | 1 | `packages/init-stack/src/index.ts` | </details> <!-- RECURSEML_SUMMARY:END --> <!-- RECURSEML_ANALYSIS:START --> ## Review by RecurseML _🔍 Review performed on [bba4db2..974e4fd](bba4db2...974e4fda92d8b6e9bee38c9b7f2b2706a798489b)_ ✨ No bugs found, your code is sparkling clean <details> <summary>✅ Files analyzed, no issues (1)</summary> • `packages/init-stack/src/index.ts` </details> [![Need help? Join our Discord](https://img.shields.io/badge/Need%20help%3F%20Join%20our%20Discord-5865F2?style=plastic&logo=discord&logoColor=white)](https://discord.gg/n3SsVDAW6U) <!-- RECURSEML_ANALYSIS:END --> <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Adds non-interactive and React project initialization options to Stack Auth setup script, updates tests and documentation. > > - **Behavior**: > - Adds `--agent-mode` option in `index.ts` for non-interactive CLI runs. > - Adds `--react` option in `index.ts` for React project initialization. > - Updates `writeReactClientFile()` in `index.ts` to handle React-specific setup. > - **Scripts**: > - Updates `package.json` to include `test-run-react` and `test-run-react:manual` scripts. > - Modifies existing test scripts in `package.json` to use `--agent-mode`. > - **Documentation**: > - Updates `setup.mdx` to include React setup instructions and wizard/manual tabs. > - **Misc**: > - Removes `STACK_DISABLE_INTERACTIVE` checks in `index.ts`. > - Updates error handling and logging in `index.ts`. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup> for f63a2a5. You can [customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this summary. It will automatically update as commits are pushed.</sup> ---- <!-- ELLIPSIS_HIDDEN --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - First-class React project initialization (--react) with automatic React client scaffolding. - Added --agent-mode for fully non-interactive CLI runs and consistent --no-browser behavior. - Public env var for local React package override (STACK_REACT_INSTALL_PACKAGE_NAME_OVERRIDE). - Chores - Standardized non-interactive flows across scripts (removed legacy interactive gating). - Tests - Updated test scaffolding and run commands to use agent-mode and browser-free execution. - Documentation - Converted setup docs to a wizard-style experience with consolidated wizard/manual tabs. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 2d2a6d7 commit 23b9eb8

3 files changed

Lines changed: 286 additions & 150 deletions

File tree

docs/templates/getting-started/setup.mdx

Lines changed: 146 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -185,97 +185,164 @@ Next up, we will show you how to [retrieve and update user information](./users.
185185
Welcome to the React SDK setup guide! If you're looking for guides for other frameworks, check out the [Next.js SDK Setup](/docs/next/getting-started/setup), or the [JavaScript SDK Setup](/docs/js/getting-started/setup).
186186
</Info>
187187

188-
Before getting started, make sure you have a [React project](https://react.dev/learn/creating-a-react-app) setup. We show an example here of a Vite React project with React Router.
188+
Before getting started, make sure you have a [React project](https://react.dev/learn/creating-a-react-app) setup. We show an example here of a Vite React project.
189189

190-
<Steps>
191-
<Step>
192-
### Install npm package
193-
</Step>
190+
We recommend using our **setup wizard** for a seamless installation experience. The wizard automatically detects your project structure and walks you through the setup process. If you encounter any issues with the wizard, you can follow our manual installation steps instead.
194191

195-
```bash title="Terminal"
196-
npm install @stackframe/react
197-
```
192+
<Tabs defaultValue="wizard">
193+
<TabsList>
194+
<TabsTrigger value="wizard">Setup wizard (recommended)</TabsTrigger>
195+
<TabsTrigger value="manual">Manual installation</TabsTrigger>
196+
</TabsList>
198197

199-
<Step>
200-
### Create API keys
201-
</Step>
202-
203-
If you haven't already, [register a new account on Stack](https://app.stack-auth.com/projects), create a project in the dashboard, create a new API key from the left sidebar, and copy the project ID, publishable client key, and secret server key into a new file called `.env.local` in the root of your React project:
204-
205-
<Step>
206-
### Create `stack/client.ts` file
207-
</Step>
208-
Create a new file `stack/client.ts` in your root directory and fill it with the following Stack app initialization code:
209-
210-
```tsx title="stack/client.ts"
211-
import { StackClientApp } from "@stackframe/react";
212-
import { useNavigate } from "react-router-dom";
213-
214-
export const stackClientApp = new StackClientApp({
215-
// You should store these in environment variables based on your project setup
216-
projectId: "your-project-id",
217-
publishableClientKey: "your-publishable-client-key",
218-
tokenStore: "cookie",
219-
redirectMethod: {
220-
useNavigate,
221-
}
222-
});
223-
```
198+
<TabsContent value="wizard">
199+
<Steps>
200+
<Step>
201+
### Run installation wizard
202+
</Step>
203+
Run Stack's installation wizard with the following command:
224204

225-
<Step>
226-
### Update `App.tsx`
227-
</Step>
205+
```sh title="Terminal"
206+
npx @stackframe/init-stack@latest
207+
```
228208

229-
Update your `App.tsx` file to wrap the entire app with a `StackProvider` and `StackTheme` and add a `StackHandler` component to handle the authentication flow.
209+
<Step>
210+
### Update API keys
211+
</Step>
212+
Then, create an account on [the Stack Auth dashboard](https://app.stack-auth.com/projects), create a new project with an API key, and copy its values into the `stack/client.ts` file created by the wizard.
230213

231-
```tsx title="App.tsx"
232-
import { StackHandler, StackProvider, StackTheme } from "@stackframe/react";
233-
import { Suspense } from "react";
234-
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
235-
import { stackClientApp } from "./stack/client";
214+
<Step>
215+
### Wrap your app
216+
</Step>
217+
This example uses react-router, but all React apps should wrap the app with `StackProvider` and `StackTheme`.
236218

237-
function HandlerRoutes() {
238-
const location = useLocation();
239-
240-
return (
241-
<StackHandler app={stackClientApp} location={location.pathname} fullPage />
242-
);
243-
}
244-
245-
export default function App() {
246-
return (
247-
<Suspense fallback={null}>
248-
<BrowserRouter>
249-
<StackProvider app={stackClientApp}>
250-
<StackTheme>
251-
<Routes>
252-
<Route path="/handler/*" element={<HandlerRoutes />} />
253-
<Route path="/" element={<div>hello world</div>} />
254-
</Routes>
255-
</StackTheme>
256-
</StackProvider>
257-
</BrowserRouter>
258-
</Suspense>
259-
);
260-
}
261-
```
262-
263-
<Step>
264-
### Done!
265-
</Step>
219+
```tsx title="App.tsx"
220+
import { StackHandler, StackProvider, StackTheme } from "@stackframe/react";
221+
import { Suspense } from "react";
222+
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
223+
import { stackClientApp } from "./stack/client";
266224

267-
That's it! Stack is now configured in your React project. If you start your React app and navigate to [http://localhost:5173/handler/sign-up](http://localhost:5173/handler/sign-up), you will see the sign-up page.
225+
function HandlerRoutes() {
226+
const location = useLocation();
227+
return (
228+
<StackHandler app={stackClientApp} location={location.pathname} fullPage />
229+
);
230+
}
268231

232+
export default function App() {
233+
return (
234+
<Suspense fallback={null}>
235+
<BrowserRouter>
236+
<StackProvider app={stackClientApp}>
237+
<StackTheme>
238+
<Routes>
239+
<Route path="/handler/*" element={<HandlerRoutes />} />
240+
<Route path="/" element={<div>hello world</div>} />
241+
</Routes>
242+
</StackTheme>
243+
</StackProvider>
244+
</BrowserRouter>
245+
</Suspense>
246+
);
247+
}
248+
```
269249

270-
<div className="stack-white-image-showcase stack-350h">
271-
<img src="/imgs/sign-in.png" alt="SignIn" />
272-
</div>
250+
<Step>
251+
### Done!
252+
</Step>
253+
That's it! Stack is now configured in your React project. If you start your app and navigate to [http://localhost:5173/handler/sign-up](http://localhost:5173/handler/sign-up), you will see the sign-up page.
273254

274-
After signing up/in, you will be redirected back to the home page. We will show you how to add user information to it in the next section. You can also check out the [http://localhost:5173/handler/account-settings](http://localhost:5173/handler/account-settings) page which looks like this:
255+
<div className="stack-white-image-showcase stack-350h">
256+
<img src="/imgs/sign-in.png" alt="SignIn" />
257+
</div>
275258

276-
![Stack account settings page](/imgs/account-settings.png)
277-
278-
</Steps>
259+
After signing up/in, you will be redirected back to the home page. You can also check out the [http://localhost:5173/handler/account-settings](http://localhost:5173/handler/account-settings) page.
260+
</Steps>
261+
</TabsContent>
262+
263+
<TabsContent value="manual">
264+
<Steps>
265+
<Step>
266+
### Install npm package
267+
</Step>
268+
269+
```bash title="Terminal"
270+
npm install @stackframe/react
271+
```
272+
273+
<Step>
274+
### Create API keys
275+
</Step>
276+
If you haven't already, [register a new account on Stack](https://app.stack-auth.com/projects), create a project in the dashboard, create a new API key from the left sidebar, and copy the project ID and publishable client key. Store them based on your project setup (environment variables or directly in the client file during development).
277+
278+
<Step>
279+
### Create `stack/client.ts` file
280+
</Step>
281+
Create a new file `stack/client.ts` in your root directory and fill it with the following Stack app initialization code:
282+
283+
```tsx title="stack/client.ts"
284+
import { StackClientApp } from "@stackframe/react";
285+
// If you use React Router, uncomment the next line and the redirectMethod below
286+
// import { useNavigate } from "react-router-dom";
287+
288+
export const stackClientApp = new StackClientApp({
289+
// You should store these in environment variables based on your project setup
290+
projectId: "your-project-id",
291+
publishableClientKey: "your-publishable-client-key",
292+
tokenStore: "cookie",
293+
// redirectMethod: { useNavigate }, // Optional: only if using react-router-dom
294+
});
295+
```
296+
297+
<Step>
298+
### Update `App.tsx`
299+
</Step>
300+
If you're using React Router, update your `App.tsx` file to wrap the entire app with a `StackProvider` and `StackTheme` and add a `StackHandler` route to handle the authentication flow.
301+
302+
```tsx title="App.tsx"
303+
import { StackHandler, StackProvider, StackTheme } from "@stackframe/react";
304+
import { Suspense } from "react";
305+
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
306+
import { stackClientApp } from "./stack/client";
307+
308+
function HandlerRoutes() {
309+
const location = useLocation();
310+
return (
311+
<StackHandler app={stackClientApp} location={location.pathname} fullPage />
312+
);
313+
}
314+
315+
export default function App() {
316+
return (
317+
<Suspense fallback={null}>
318+
<BrowserRouter>
319+
<StackProvider app={stackClientApp}>
320+
<StackTheme>
321+
<Routes>
322+
<Route path="/handler/*" element={<HandlerRoutes />} />
323+
<Route path="/" element={<div>hello world</div>} />
324+
</Routes>
325+
</StackTheme>
326+
</StackProvider>
327+
</BrowserRouter>
328+
</Suspense>
329+
);
330+
}
331+
```
332+
333+
<Step>
334+
### Done!
335+
</Step>
336+
That's it! Stack is now configured in your React project. If you start your app and navigate to [http://localhost:5173/handler/sign-up](http://localhost:5173/handler/sign-up), you will see the sign-up page.
337+
338+
<div className="stack-white-image-showcase stack-350h">
339+
<img src="/imgs/sign-in.png" alt="SignIn" />
340+
</div>
341+
342+
After signing up/in, you will be redirected back to the home page. You can also check out the [http://localhost:5173/handler/account-settings](http://localhost:5173/handler/account-settings) page.
343+
</Steps>
344+
</TabsContent>
345+
</Tabs>
279346

280347

281348
{/* ELSE_IF_PLATFORM js */}

packages/init-stack/package.json

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,23 @@
1212
"lint": "eslint --ext .tsx,.ts .",
1313
"typecheck": "tsc --noEmit",
1414
"init-stack": "node dist/index.js",
15-
"init-stack:local": "STACK_NEXT_INSTALL_PACKAGE_NAME_OVERRIDE=../../stack STACK_JS_INSTALL_PACKAGE_NAME_OVERRIDE=../../js node dist/index.js",
15+
"init-stack:local": "STACK_NEXT_INSTALL_PACKAGE_NAME_OVERRIDE=../../stack STACK_JS_INSTALL_PACKAGE_NAME_OVERRIDE=../../js STACK_REACT_INSTALL_PACKAGE_NAME_OVERRIDE=../../react node dist/index.js",
1616
"test-run": "pnpm run build && pnpm run test-run-js && pnpm run test-run-node && pnpm run test-run-next && pnpm run test-run-neon && pnpm run test-run-no-browser",
1717
"test-run:manual": "pnpm run build && pnpm run test-run-js:manual && pnpm run test-run-node:manual && pnpm run test-run-next:manual && pnpm run test-run-neon:manual",
1818
"ensure-neon": "grep -q '\"@neondatabase/serverless\"' ./test-run-output/package.json && echo 'Initialized Neon successfully!'",
1919
"test-run-neon": "pnpm run test-run-node --neon && pnpm run ensure-neon",
2020
"test-run-neon:manual": "pnpm run test-run-node:manual --neon && pnpm run ensure-neon",
21-
"test-run-no-browser": "rimraf test-run-output && mkdir test-run-output && cd test-run-output && npm init --init-author-name example-author --init-license UNLICENSED --init-author-url http://example.com --init-module test-run-output --init-version 1.0.0 -y && cd .. && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --server --npm --no-browser",
21+
"test-run-no-browser": "rimraf test-run-output && mkdir test-run-output && cd test-run-output && npm init --init-author-name example-author --init-license UNLICENSED --init-author-url http://example.com --init-module test-run-output --init-version 1.0.0 -y && cd .. && pnpm run init-stack:local test-run-output --agent-mode --js --server --npm --no-browser",
2222
"test-run-node:manual": "rimraf test-run-output && mkdir test-run-output && cd test-run-output && npm init && cd .. && pnpm run init-stack:local test-run-output",
23-
"test-run-node": "rimraf test-run-output && mkdir test-run-output && cd test-run-output && npm init --init-author-name example-author --init-license UNLICENSED --init-author-url http://example.com --init-module test-run-output --init-version 1.0.0 -y && cd .. && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --server --npm",
23+
"test-run-node": "rimraf test-run-output && mkdir test-run-output && cd test-run-output && npm init --init-author-name example-author --init-license UNLICENSED --init-author-url http://example.com --init-module test-run-output --init-version 1.0.0 -y && cd .. && pnpm run init-stack:local test-run-output --agent-mode --js --server --npm --no-browser",
2424
"test-run-js:manual": "rimraf test-run-output && npx -y sv create test-run-output --no-install && pnpm run init-stack:local test-run-output",
25-
"test-run-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --client --npm",
25+
"test-run-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && pnpm run init-stack:local test-run-output --agent-mode --js --client --npm --no-browser",
2626
"test-run-next:manual": "rimraf test-run-output && npx -y create-next-app@latest test-run-output && pnpm run init-stack:local test-run-output",
27-
"test-run-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output",
28-
"test-run-keys-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --project-id my-project-id --publishable-client-key my-publishable-client-key",
29-
"test-run-keys-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --client --npm --project-id my-project-id --publishable-client-key my-publishable-client-key"
27+
"test-run-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && pnpm run init-stack:local test-run-output --agent-mode --no-browser",
28+
"test-run-keys-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && pnpm run init-stack:local test-run-output --agent-mode --project-id my-project-id --publishable-client-key my-publishable-client-key",
29+
"test-run-keys-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && pnpm run init-stack:local test-run-output --agent-mode --js --client --npm --project-id my-project-id --publishable-client-key my-publishable-client-key",
30+
"test-run-react": "rimraf test-run-output && npx -y create-vite@latest test-run-output --template react-ts && pnpm run init-stack:local test-run-output --agent-mode --no-browser --npm",
31+
"test-run-react:manual": "rimraf test-run-output && npx -y create-vite@latest test-run-output --template react-ts && pnpm run init-stack:local test-run-output --react"
3032
},
3133
"files": [
3234
"README.md",

0 commit comments

Comments
 (0)