feat(init): add init command with framework scaffolding and agent prompts - #38
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR restructures Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
1baab9c to
f9bd7ed
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
1 similar comment
✅ Actions performedReview triggered.
|
32ee86a to
40b2c6a
Compare
|
Is this PR ready for review? I see ongoing changes and it is already about 5000 lines. Is some of this generated code? |
|
@jfoshee yeah, it's ready. It's already about 5,000 lines, with half of it being prompts and the rest scaffolding code |
Used by the init command's framework scaffolders to safely add imports and modify config files without breaking existing code.
- Fix @clerk/clerk-react → @clerk/react - Fix @clerk/tanstack-start → @clerk/tanstack-react-start - Remove standalone vite detection (covered by react) - Reorder priority: scaffoldable frameworks first, then expo, react, express, fastify - Export readDeps for use by init context module
Detects framework, TypeScript, src/ directory convention, package manager, Next.js router variant, middleware filename, layout path, and existing Clerk SDK installation.
Add idempotent scaffolders for Next.js (App + Pages Router), React, React Router, Nuxt, TanStack Start, Astro, and Vue. Each scaffolder generates framework-appropriate boilerplate (middleware, providers, auth pages) while preserving existing user code. Shared helpers handle AST-based import injection (magicast with string fallback), middleware composition, and auth page creation.
- scan: detect competing auth libraries pre-scaffold and scan for hardcoded keys/leftover imports post-scaffold - format: run Prettier/Biome on generated files - preview: show planned file changes and confirm before writing - prompts: framework-specific agent mode prompts with exact code snippets and file paths
Replace the minimal init (login + link + install + env pull) with a full orchestrator that also scaffolds framework boilerplate and scans for issues. Skips login/link when already authenticated and linked.
- Add Agent Mode section - Add env var column to framework detection table - Add Expo, Express, Fastify to detection table - Document scaffolding actions for all 8 supported frameworks - Note that Expo/Express/Fastify are detected but not scaffolded
Replace monolithic prompts.ts with individual .md template files per
framework, matching the clerk-docs structured format (sections, rules,
deprecated patterns, verification checklists).
- Move prompts to src/commands/init/prompts/*.md with {{PLACEHOLDER}}
interpolation
- Add prompts for expo, express, and fastify frameworks
- Merge DOCS_URLS + TEMPLATE_MAP into single FRAMEWORK_PROMPTS record
- Extract shared pmInstallCommand, remove duplicate pmAddCommand
- Fix formatter-escaped underscores (\_app, \_\_root) in template loader
- Add "After Setup" section to all prompts (matching clerk-docs)
…js-context Move parseNextMajorVersion, detectMiddlewareBasename, detectNextjsVariant, and detectLayoutPath from context.ts into a dedicated nextjs-context.ts module. This isolates framework-specific logic behind the enrichContext hook on FrameworkScaffold rather than coupling it to gatherContext. Parallelize dirExists calls with Promise.all in both files.
…version check Replace the Record<string, FrameworkScaffold> keyed map with an array using satisfies and matches()-based lookup. Add enrichProjectContext() that delegates to each scaffolder's enrichContext hook. Add minMajorVersion guard that checks the framework dep version before scaffolding.
Add parseMajorVersion, insertAfterLastImport, wrapBodyWithProvider, and resolveNextjsMiddlewareBasename to helpers. Use proper skip FileAction in scaffoldAuthPage and scaffoldNextjsMiddleware. Flatten nested ifs with early returns and store BunFile reference once. The middleware fallback now resolves from the actual Next.js version in deps.
…, and minMajorVersion Each scaffolder now exports dep, matches(), and minMajorVersion. All skip cases use the proper FileAction skip variant. Flatten nested ifs with early returns across scaffoldLayout, scaffoldApp, scaffoldMiddleware, and scaffoldConfig. Use shared wrapBodyWithProvider (nextjs-app, tanstack-start), insertAfterLastImport (react-router, vue), and extract wrapWithClerkProvider in react.ts. Store BunFile references to avoid duplicate creation.
… internal types Remove MAX_FINDINGS so no context is lost. Convert IGNORE_DIRS to a Set for O(1) lookups. Precompile CODE_SCANS regexes once at module level. Inline matchesFramework guard. Convert AuthLibraryScan and CodeScan from exported interfaces to local types since they are not imported elsewhere.
…piled binaries
Use Bun's `import ... with { type: "text" }` to embed markdown prompt
templates at build time. This replaces the runtime readFileSync +
import.meta.dir approach that would break in compiled Bun binaries.
Remove the template cache since imports are already static.
Replace inline if-checks for prettier/biome with a FormatterConfig type and a FORMATTERS array. The runFormatters loop now iterates the config, making it trivial to add new formatters.
…version check Update context tests to call enrichProjectContext separately from gatherContext and import parseMajorVersion from helpers. Add tests for scaffold version check (below minimum, meets minimum, Next.js 16 proxy). Update nextjs-app tests to assert on the skip type instead of skipReason field. Update scan test to verify all findings are returned without cap.
Add jsxAuthPageContent with type-safe JsxClerkPackage union, scaffoldConfigFile generic for the find→check→modify pattern, authComponentName, and inline capitalize. These shared helpers eliminate duplication across framework scaffolders.
Replace duplicated authRouteContent/nextjsAuthPageContent with jsxAuthPageContent, replace per-framework scaffoldConfig with scaffoldConfigFile in astro, nuxt, and react-router. Remove unused imports and add enableV8Middleware documentation.
Update preview formatting to use switch on discriminated union, restructure prompts/index.ts with typed template resolution and variable building, and minor scan.ts cleanup.
Add tests for nextjs-app (middleware composition, provider wrapping, src/ paths, proxy basename), react-router (root modification, loader merge), tanstack-start (base dir detection), and scan (no findings cap).
Export FRAMEWORK_MAP and add lookupFramework() to resolve framework names or aliases (e.g. "tanstack-start" → "@tanstack/react-start") along with FRAMEWORK_NAMES for validation and display.
Add optional i18nLocaleDir field to ProjectContext for frameworks that detect locale-based routing directories (e.g. [locale], [lang]).
Split preview logic into previewPlan() (display only) and previewAndConfirm() (display + prompt) to support --yes mode without duplicating the plan rendering code.
Add reusable helpers for all framework scaffolders: - authFileSpecs() factory for sign-in/sign-up file generation - scaffoldEnvVars() and SIGN_ROUTE_ENV_VARS for env file management - htmlAuthComponentMarkup() and jsxAuthComponentMarkup() with Tailwind/plain CSS variants - hasTailwindStyles() for style detection - i18n middleware detection, composition, and routing helpers (detectI18nMiddlewareLib, composeWithI18nMiddleware, etc.) - findFirstDirMatch() for generic directory scanning
Add detectI18nLocaleDir() to identify App Router locale directories (e.g. [locale], [lang]) by checking for layout files inside dynamic segments. Populate i18nLocaleDir in enrichNextjsContext() so scaffolders can place auth pages inside locale-prefixed paths.
Accept optional frameworkOverride parameter in gatherContext() to skip auto-detection when the user specifies --framework explicitly.
Register --framework <name>, -y/--yes, and --prompt options on the init command. Wire them through to framework override resolution, preview-only plan display, and agent prompt output respectively.
Update all six framework scaffolders (Astro, Next.js App/Pages, Nuxt, React Router, TanStack Start) to use the shared helpers: - authFileSpecs() factory for sign-in/sign-up generation - scaffoldEnvVars() for .env file management - hasTailwindStyles() for consistent style detection - i18n-aware auth page placement using locale directory detection - htmlAuthComponentMarkup()/jsxAuthComponentMarkup() for rendering
Add tests for i18n support across frameworks:
- Context: locale directory detection ([locale], [lang]) with
layout file validation and src/ convention support
- Next.js App Router: i18n auth page placement, composed Clerk +
next-intl middleware, expression export handling, env var scaffolding
- React Router: ($locale) prefix detection for auth routes
- TanStack Start: {-$locale} directory detection for auth routes
Add --framework, --yes, and --prompt options to init command README with usage examples. Update root README help output with --verbose flag documentation.
071d210 to
ceeb037
Compare
jfoshee
left a comment
There was a problem hiding this comment.
I time-boxed my review due to the size of the PR and youth of this project. I think it's more important to get this into people's hands for testing than this have perfect code design. I did not see any blockers and I do hope people start trying this soon.
The test matrix is already getting kind-of big. I know @wyattjoh was looking at E2E tests. I expect we will want to regularly ensure that the edge version of clerk init works with the edge versions of all create templates for the various frameworks. And, as you know, each framework has variants/options. So, it would be good to start to enumerate all of those cases so we can eventually cover them with automated tests.
I manually tested NextJS and Astro taking the defaults and they worked fine. I expect we will iterate on the output to include things like sign-in buttons / user button, but totally fine to save that for later.
I like the general structure here and presence of unit tests. There are some gaps in testing, so I expect those will be covered in time.
And, I expect we will continue to keep an eye on the code structure and do refactorings as we see the patterns and logical groupings of functions. I noticed we have heuristics for detecting things in the file system, heuristics for detecting things within code text, operations for transforming text, etc.
Thanks for this huge effort, Rafael.
- Extract utility helpers from index.ts into heuristics.ts (jfoshee #18) - Extract text transformations into transformations.ts (jfoshee #19) - Fix wrapBodyWithProvider whitespace/formatting bug (jfoshee #20) - Refactor tests to use semantic path lookups instead of positional array indexing (jfoshee #13/#17) - Add doc comment to helpers.ts clarifying shared usage (jfoshee #15) - Update astro.md NEVER rules to start with "Never" (jfoshee #25) - Remove section banner comments from init command files
Summary
clerk initto detect the project's framework, install the Clerk SDK, pull env vars, and scaffold framework-specific boilerplate (middleware, providers, auth pages)@clerk/clerk-react→@clerk/react,@clerk/tanstack-start→@clerk/tanstack-react-start) and remove standalone Vite detectionAgent prompts
Prompts for
clerk init --mode agentnow live as individual.mdfiles insrc/commands/init/prompts/, using{{PLACEHOLDER}}interpolation for dynamic context (package manager, file extensions, paths). Each prompt follows the clerk-docs structure:nextjs-app-router.mdnextjs-pages-router.mdreact.mdreact-router.mdnuxt.mdtanstack-start.mdastro.mdvue.mdexpo.mdexpress.mdfastify.mdgeneric.mdgeneric-fallback.mdScaffolding support
clerkMiddlewarewith route protectionClerkProviderin layoutClerkProviderin_appclerkMiddleware+rootAuthLoaderClerkProviderwithloaderDataclerkMiddlewareinrequestMiddlewareClerkProviderin rootclerkMiddlewarewithonRequestclerk()integrationClerkProviderin entryclerkPluginin entryTest plan
bun test— 415 tests pass, 0 failuresbun run lint— 0 errorsbun run format:check— all files formattedclerk initin a fresh Next.js projectclerk initin a fresh React (Vite) projectclerk init --mode agentto verify prompt outputSummary by CodeRabbit
New Features
Documentation