UNPKG

create-w3-app

Version:
530 lines (405 loc) 20.9 kB
# UPDATES.SPEC.md ## `create-w3-app` - Full Dependency Update Specification --- ## Table of Contents 1. [Current State](#current-state) 2. [Phase 1: CLI Self-Dependencies (Low Risk)](#phase-1-cli-self-dependencies-low-risk) 3. [Phase 2: Template Version Map (Mixed Risk)](#phase-2-template-version-map-mixed-risk) 4. [Phase 3: Base Template (Medium Risk)](#phase-3-base-template-medium-risk) 5. [Phase 4: Template File Changes (High Risk)](#phase-4-template-file-changes-high-risk) 6. [Phase 5: CI/CD Workflow](#phase-5-cicd-workflow) 7. [How to Run Locally](#how-to-run-locally) 8. [How to Test](#how-to-test) 9. [How to Release](#how-to-release) 10. [Release Channels](#release-channels) --- ## Current State The project manages dependencies in **three separate places**: | Location | Purpose | |----------|---------| | `package.json` (root) | Dependencies for the CLI tool itself | | `src/installers/dependencyVersionMap.ts` | Versions injected into users' scaffolded projects | | `template/base/package.json` | Base Next.js app starting point for scaffolded projects | **Current versions (as of v0.7.0):** | Package | CLI (package.json) | Version Map | Base Template | |---------|-------------------|-------------|---------------| | next | `^15.5.4` (devDep) | — | `^15.5.2` | | react | `^19.2.0` (devDep) | — | `^19.2.0` | | react-dom | `^19.2.0` (devDep) | — | `^19.0.0` | | typescript | `^5.9.3` (devDep) | — | `^5.9.3` | | tailwindcss | `^4.1.14` (devDep) | `^4.0.15` | — | | @tailwindcss/postcss | `^4.1.14` (devDep) | `^4.0.15` | — | | postcss | — | `^8.5.3` | — | | @privy-io/react-auth | `^3.3.0` (devDep) | `^2.4.14` | — | | @privy-io/wagmi | — | `^1.0.5` | — | | @rainbow-me/rainbowkit | `^2.2.8` (devDep) | `^2.2.6` | — | | wagmi | `^2.18.0` (devDep) | `^2.15.6` | — | | viem | `^2.38.0` (devDep) | `^2.31.0` | — | | @tanstack/react-query | `^5.90.2` (devDep) | `^5.69.0` | — | | lucide-react | `^0.545.0` (devDep) | `^0.515.0` | — | | class-variance-authority | `^0.7.1` (devDep) | `^0.7.1` | — | | clsx | `^2.1.1` (devDep) | `^2.1.1` | — | | tailwind-merge | `^3.3.1` (devDep) | `^3.3.1` | — | | tw-animate-css | `^1.4.0` (devDep) | `^1.3.4` | — | | prettier | `^3.6.2` (devDep) | `^3.5.3` | — | | prettier-plugin-tailwindcss | `^0.6.14` (devDep) | `^0.6.11` | — | | eslint | — | `^9.23.0` | — | | eslint-config-next | — | `^15.2.3` | — | | typescript-eslint | `^8.46.0` | `^8.27.0` | — | | @biomejs/biome | — | `^1.9.4` | — | | @eslint/eslintrc | — | `^3.3.1` | — | | eslint-plugin-drizzle | — | `^0.2.3` | — | | @clack/prompts | `^0.11.0` | — | — | | @clack/core | `^0.5.0` | — | — | | zod | `^4.1.12` | — | — | | superjson | `^2.2.2` | — | — | | next-auth | `^4.24.11` | — | — | --- ## Phase 1: CLI Self-Dependencies (Low Risk) These dependencies only affect the CLI tool itself — they do **not** affect scaffolded user projects. ### 1.1 Production Dependencies (`package.json` dependencies) | Package | Current | Latest | Action | Breaking? | |---------|---------|--------|--------|-----------| | `@clack/core` | `^0.5.0` | `1.4.2` | **UPDATE** | YES — v1 API differs | | `@clack/prompts` | `^0.11.0` | `1.6.0` | **UPDATE** | YES — v1 API differs | | `@ianvs/prettier-plugin-sort-imports` | `^4.7.0` | check latest | KEEP/UPDATE | Check latest | | `chalk` | `5.6.2` | latest | KEEP (pinned) | None | | `commander` | `^14.0.1` | check latest | KEEP/UPDATE | Check latest | | `eslint-plugin-import-x` | `^4.16.1` | check latest | KEEP/UPDATE | Check latest | | `execa` | `^9.6.0` | check latest | KEEP/UPDATE | Check latest | | `fs-extra` | `^11.3.2` | latest | KEEP/UPDATE | None | | `gradient-string` | `^3.0.0` | latest | KEEP/UPDATE | None | | `ora` | `9.0.0` | latest | KEEP (pinned) | None | | `sort-package-json` | `^3.4.0` | latest | KEEP/UPDATE | None | | `typescript-eslint` | `^8.46.0` | check latest | KEEP/UPDATE | Check latest | ### 1.2 Dev Dependencies (`package.json` devDependencies) | Package | Current | Latest | Action | Breaking? | |---------|---------|--------|--------|-----------| | `@changesets/cli` | `^2.29.7` | check latest | KEEP/UPDATE | Check latest | | `@types/fs-extra` | `^11.0.4` | latest | KEEP/UPDATE | None | | `@types/gradient-string` | `^1.1.6` | latest | KEEP/UPDATE | None | | `@types/node` | `^24.7.1` | check latest | UPDATE | None | | `prettier` | `^3.6.2` | check latest | KEEP/UPDATE | None | | `tsup` | `^8.5.0` | check latest | KEEP/UPDATE | None | | `type-fest` | `^5.0.1` | check latest | KEEP/UPDATE | None | | `typescript` | `^5.9.3` | `6.0.3` | **HOLD** | Next.js may not support TS 6 | | `zod` | `^4.1.12` | `4.4.3` | UPDATE | Low risk (minor) | | `superjson` | `^2.2.2` | check latest | KEEP/UPDATE | None | | `next-auth` | `^4.24.11` | check latest | KEEP/UPDATE | None | ### 1.3 @clack/prompts Migration Notes The `@clack/prompts` v0 → v1 migration is the highest-risk item in Phase 1. The CLI uses it in `src/cli/index.ts` for interactive prompts: - **Affected file:** `src/cli/index.ts` - **Key usage:** `text()`, `confirm()`, `select()`, `multiselect()`, `isCancel()`, `intro()`, `outro()`, `note()`, `spinner()` - **What to check:** - Import paths may have changed - Function signatures may differ - Return types may be different - `isCancel` behavior may have changed - `spinner` API may differ --- ## Phase 2: Template Version Map (Mixed Risk) File: `src/installers/dependencyVersionMap.ts` These are the versions that get injected into users' `package.json` when scaffolding a project. ### 2.1 Safe Updates (No Breaking Changes) | Package | Current | Target | Category | |---------|---------|--------|----------| | `tailwindcss` | `^4.0.15` | `^4.3.1` | Tailwind | | `postcss` | `^8.5.3` | `^8.5.15` | Tailwind | | `@tailwindcss/postcss` | `^4.0.15` | `^4.3.1` | Tailwind | | `class-variance-authority` | `^0.7.1` | `^0.7.1` | shadcn (no change) | | `clsx` | `^2.1.1` | `^2.1.1` | shadcn (no change) | | `tailwind-merge` | `^3.3.1` | `^3.3.1` | shadcn (no change) | | `tw-animate-css` | `^1.3.4` | `^1.4.0` | shadcn | | `prettier` | `^3.5.3` | latest | ESLint | | `@eslint/eslintrc` | `^3.3.1` | latest | ESLint | | `prettier-plugin-tailwindcss` | `^0.6.11` | `^0.6.14` | ESLint | | `eslint` | `^9.23.0` | latest | ESLint | | `eslint-plugin-drizzle` | `^0.2.3` | latest | ESLint | | `@biomejs/biome` | `^1.9.4` | latest | Biome | | `@tanstack/react-query` | `^5.69.0` | `^5.101.1` | Web3 | | `viem` | `^2.31.0` | `^2.53.1` | Web3 | | `@rainbow-me/rainbowkit` | `^2.2.6` | `^2.2.11` | Web3 | ### 2.2 Breaking Updates (Template Files Need Rewriting) | Package | Current | Target | Breaking Change | |---------|---------|--------|-----------------| | `eslint-config-next` | `^15.2.3` | `^16.x` | Must match Next.js 16. ESLint flat config changes | | `typescript-eslint` | `^8.27.0` | latest | Low risk, but types may change | | `@privy-io/react-auth` | `^2.4.14` | `^3.32.2` | Major v2→v3. `PrivyClientConfig`, `PrivyProvider` API | | `@privy-io/wagmi` | `^1.0.5` | `^4.0.13` | Major v1→v4. Requires privy v3. `createConfig`/`WagmiProvider` from `@privy-io/wagmi` | | `wagmi` | `^2.15.6` | `^3.6.18` | Major v2→v3. Hook renames, connector deps now optional | | `lucide-react` | `^0.515.0` | `^1.21.0` | Major v0→v1. Icon import API completely changed | ### 2.3 wagmi v2 → v3 Breaking Changes From wagmi migration guide: 1. **Connector dependencies now optional**`injected` no longer requires any extra package. For our templates using only `injected()`, no change needed. 2. **Hook renames:** - `useAccount``useConnection` - `useAccountEffect``useConnectionEffect` - `useSwitchAccount``useSwitchConnection` 3. **Mutate function renames:** Custom names (e.g. `connect()`) → `mutate()`/`mutateAsync()` 4. **Removed:** `useConnect().connectors` → use `useConnectors()` 5. **Removed:** `useSwitchChain().chains` → use `useChains()` 6. **Removed:** `useDisconnect().connectors` and `useSwitchConnection().connectors` → use `useConnections()` 7. **Minimum TypeScript:** Now `5.9.3` > **Note:** Our template config files (`wagmi.ts`, `wagmi-privy.ts`, `wagmi-rainbow.ts`) only use `createConfig`, `http`, `injected`, and `WagmiProvider` — these core APIs are **unchanged** in v3. The provider components in `template/extras/src/provider/` may need updates if they use any renamed hooks. ### 2.4 @privy-io/react-auth v2 → v3 Breaking Changes - `PrivyClientConfig` type may have new required fields or renamed options - `PrivyProvider` props may have changed - `embeddedWallets` configuration shape may have changed - `loginMethods` values may differ **Affected template files:** - `template/extras/config/privy.ts` - `template/extras/src/provider/privy-provider.tsx` - `template/extras/src/provider/privy-wagmi-provider.tsx` ### 2.5 @privy-io/wagmi v1 → v4 Breaking Changes Peer dependencies from npm registry for v4.0.13: - `@privy-io/react-auth: "^3"` (matches our privy v3 update) - `wagmi: ">=2"` (works with both v2 and v3) - `viem: "2.52.0"` (pin specific version) - `react: ">=18"` The `createConfig` and `WagmiProvider` API from `@privy-io/wagmi` need verification. **Affected template files:** - `template/extras/config/wagmi-privy.ts` - `template/extras/src/provider/privy-wagmi-provider.tsx` ### 2.6 lucide-react v0 → v1 Breaking Changes - Icon imports changed from named exports to default exports or different paths - v0: `import { Activity } from "lucide-react"` - v1: `import Activity from "lucide-react/dist/esm/icons/activity"` or tree-shakeable individual imports - Dynamic icon imports API changed **Affected template files:** - Any component importing lucide icons (check `template/extras/src/app/components/connect.tsx` and `template/extras/src/pages/components/connect.tsx` variants) --- ## Phase 3: Base Template (Medium Risk) File: `template/base/package.json` ### 3.1 Version Updates | Package | Current | Target | Notes | |---------|---------|--------|-------| | `next` | `^15.5.2` | `^16.2.9` | Requires Node >=20.9.0 | | `react` | `^19.2.0` | `^19.2.7` | Patch bump | | `react-dom` | `^19.0.0` | `^19.2.7` | Match react version | | `@types/react` | `^19.0.0` | `^19.2.7` | Match react version | | `@types/react-dom` | `^19.2.0` | `^19.2.7` | Match react-dom version | | `typescript` | `^5.9.3` | `^5.9.3` | Hold — TS 6.0.3 not needed yet | | `@types/node` | `^24.7.1` | latest | Check latest | ### 3.2 Script Changes (Next.js 16) Next.js 16 makes Turbopack the default. Remove `--turbopack` flags: ```diff - "dev": "next dev --turbopack", - "build": "next build --turbopack", + "dev": "next dev", + "build": "next build", ``` ### 3.3 Next.js 16 Breaking Changes Summary 1. **Turbopack is default** — No need for `--turbopack` flag. If template uses custom webpack config, add `--webpack` flag. 2. **`next lint` removed** — Must use ESLint CLI directly. The `lint` script in the template should use `eslint .` instead of `next lint`. 3. **`middleware` → `proxy`** — Rename middleware file and functions in template if any exist. 4. **Async Request APIs**`cookies()`, `headers()`, `params`, `searchParams` are now Promises. Template page/layout files need `await`. 5. **React 19.2** — Required by Next.js 16. 6. **`eslint-config-next`** — Must match Next.js 16 (`^16.x`). ESLint flat config is default. 7. **Minimum Node.js**`20.9.0` (was 18.17.0). --- ## Phase 4: Template File Changes (High Risk) ### 4.1 Files Requiring Changes | File | Change Needed | Reason | |------|--------------|--------| | `template/base/package.json` | Update versions, remove `--turbopack` | Next 16 + version bumps | | `template/base/next.config.js` | Remove deprecated options if any | Next 16 | | `template/extras/config/privy.ts` | `PrivyClientConfig` type update | Privy v3 | | `template/extras/config/wagmi-privy.ts` | `createConfig` from `@privy-io/wagmi` v4 API | @privy-io/wagmi v4 | | `template/extras/src/provider/privy-provider.tsx` | `PrivyProvider` API update | Privy v3 | | `template/extras/src/provider/privy-wagmi-provider.tsx` | `PrivyProvider`/`WagmiProvider` from new packages | Privy v3 + @privy-io/wagmi v4 | | `template/extras/src/app/layout/*.tsx` | `params``await params` | Next 16 async params | | `template/extras/src/app/page/*.tsx` | `searchParams``await searchParams` | Next 16 async params | | `template/extras/src/pages/_app/*.tsx` | No change (Pages Router not affected) | — | | `template/extras/src/app/components/connect.tsx` | lucide-react v1 imports | lucide-react v1 | | `template/extras/src/pages/components/connect.tsx` | lucide-react v1 imports | lucide-react v1 | | `template/extras/config/_eslint.base.js` | Flat config updates, remove `next lint` | Next 16 + ESLint flat config | | `template/extras/config/postcss.config.js` | Check for Tailwind v4 compatibility | Tailwind v4.3 | | `template/extras/config/components.json` | Check for shadcn compatibility | May need update | | `template/extras/src/styles/globals.css` | Check Tailwind v4.3 directives | Tailwind v4.3 | | `template/extras/src/styles/shadcn-globals.css` | Check Tailwind v4.3 + shadcn | Tailwind v4.3 | | `src/installers/eslint.ts` | `eslint-config-next` version, remove `next lint` scripts | Next 16 | | `src/installers/privy.ts` | Package dependencies list, file copy logic | Privy v3 + @privy-io/wagmi v4 | | `src/installers/wagmi.ts` | Package dependencies, config file paths | wagmi v3 | | `src/installers/rainbow.ts` | Package dependencies | RainbowKit update | | `src/installers/tailwind.ts` | Package dependencies | Tailwind v4.3 | | `src/installers/shadcn.ts` | Package dependencies | shadcn/lucide updates | ### 4.2 Template Layout/Page Files — Async Params Migration App Router layout and page files need `params` and `searchParams` to be awaited: ```tsx // Before (Next 15): export default function Layout({ children, params }: { children: React.ReactNode; params: { slug: string } }) { const { slug } = params // ... } // After (Next 16): export default async function Layout({ children, params }: { children: React.ReactNode; params: Promise<{ slug: string }> }) { const { slug } = await params // ... } ``` Multiple variants exist in: - `template/extras/src/app/layout/` — 7 layout variants - `template/extras/src/app/page/` — 7 page variants Each variant must be checked and updated as needed. ### 4.3 eslint-config-next Update Since Next.js 16 removed the `next lint` command, the template's `lint` script must change: ```diff - "lint": "next lint", - "lint:fix": "next lint --fix", + "lint": "eslint .", + "lint:fix": "eslint . --fix", ``` This is handled in `src/installers/eslint.ts`. --- ## Phase 5: CI/CD Workflow File: `.github/workflows/release.yml` ### 5.1 Changes | Setting | Current | Target | Reason | |---------|---------|--------|--------| | `node-version` | `20` | `22` | Next 16 requires Node >=20.9. LTS 22 is current | | `pnpm/action-setup` version | `v2` | `v4` | Latest version | | `actions/checkout` | `v4` | `v4` | Already latest | | `actions/setup-node` | `v4` | `v4` | Already latest | | pnpm version | `9` | `9` | Staying on pnpm 9 | ### 5.2 Required GitHub Secrets | Secret | Purpose | |--------|---------| | `NPM_TOKEN` | Publish to npm registry | | `GH_PAT` | Create GitHub Release | --- ## How to Run Locally ```bash # 1. Install dependencies pnpm install # 2. Type-check the CLI source pnpm typecheck # 3. Lint the CLI source pnpm lint # 4. Build the CLI pnpm build # 5. Run the CLI and create a test project # This will scaffold a full app in ../my-test-app pnpm start ../my-test-app # 6. Navigate to the test project cd ../my-test-app # 7. Install the generated project's dependencies pnpm install # 8. Run the generated dev server pnpm dev # Expected: Next.js dev server starts on http://localhost:3000 # 9. Type-check the generated project pnpm typecheck # Expected: No type errors # 10. Build the generated project pnpm build # Expected: Successful production build ``` **Quick dev loop (CLI changes only):** ```bash # Watch mode: rebuilds CLI on every change and auto-runs pnpm dev ``` --- ## How to Test ### Test Matrix Since the CLI supports many combinations of options, test each major path: | Test Case | Flags/Options | What to Verify | |-----------|--------------|----------------| | **Default** | `--default` | Tailwind + Privy installs, app builds | | **Tailwind only** | Select Tailwind: yes, Shadcn: no, Auth: none, Wagmi: no | Tailwind works, no web3 packages | | **Tailwind + Shadcn** | Tailwind: yes, Shadcn: yes, Auth: none | shadcn components work, lucide icons render | | **Privy + Wagmi** | Auth: Privy, Wagmi: yes | Providers wrap correctly, env vars exist | | **Rainbow Kit** | Auth: Rainbow Kit | RainbowKit+wagmi+viem installed, provider renders | | **ESLint** | ESLint: yes | Config files created, scripts added, lint runs | | **Biome** | Biome: yes | biome.jsonc created, scripts added | | **App Router** | Router: App Router | layout.tsx exists (not _app.tsx) | | **Pages Router** | Router: Pages Router | _app.tsx exists (not layout.tsx) | | **No Git** | `--noGit` | No .git directory created | | **No Install** | `--noInstall` | No node_modules, manual `pnpm install` works after | ### Automated Check After scaffolding each test case: ```bash cd <test-project> pnpm typecheck # Must pass pnpm build # Must pass ``` --- ## How to Release ### 1. Create a Changeset ```bash pnpm changeset ``` This interactively asks: - Which packages changed (select `create-w3-app`) - Type of bump: `major` | `minor` | `patch` - Summary message ### 2. Version Bump ```bash pnpm release ``` This runs `changeset version` which: - Bumps the version in `package.json` - Updates `CHANGELOG.md` - Deletes consumed changeset files ### 3. Build and Publish ```bash # Build the CLI pnpm build # Publish to npm (latest tag) pnpm pub:release # Or publish with tags: pnpm pub:beta # --tag beta pnpm pub:next # --tag next ``` ### 4. GitHub Release The GitHub release is created **automatically** on push to `main` via `.github/workflows/release.yml`: 1. Push to `main` triggers the workflow 2. Workflow checks if the version already exists on npm 3. If new: publishes to npm + creates GitHub Release from `CHANGELOG.md` **Manual trigger:** Use `workflow_dispatch` in GitHub Actions UI. ### 5. Post-Release Checklist - [ ] Verify package appears on [npmjs.com/package/create-w3-app](https://www.npmjs.com/package/create-w3-app) - [ ] Verify GitHub Release created at [github.com/gopiinho/create-w3-app/releases](https://github.com/gopiinho/create-w3-app/releases) - [ ] Test fresh install: `npx create-w3-app@latest test-project` - [ ] Verify `npx create-w3-app@latest` resolves correctly - [ ] Test scaffolded app: `cd test-project && pnpm install && pnpm build` --- ## Release Channels | Channel | Command | npm Tag | Use Case | |---------|---------|---------|----------| | `latest` | `pnpm pub:release` | `latest` | Stable releases | | `beta` | `pnpm pub:beta` | `beta` | Pre-release testing | | `next` | `pnpm pub:next` | `next` | Canary/experimental | Users install specific channels: ```bash npx create-w3-app@latest # stable npx create-w3-app@beta # beta npx create-w3-app@next # canary ``` --- ## Risk Summary | Phase | Risk Level | Breaking Changes | Rollback Safe? | |-------|-----------|-----------------|----------------| | Phase 1: CLI deps | Low | @clack/prompts v1 API | Yes — `pnpm install` revert | | Phase 2: Version map | Mixed | wagmi v3, privy v3, lucide v1 | Partially — versions can be reverted in map | | Phase 3: Base template | Medium | Next.js 16 async params | Yes — template file revert | | Phase 4: Template files | **High** | All breaking changes combined | Complex — multiple files intertwined | | Phase 5: CI/CD | Low | None | Yes — workflow file revert | ### Recommended Execution Order 1. **Phase 1 first** — Update CLI deps, rebuild, verify CLI still works 2. **Phase 2 (safe subset)** — Update non-breaking version map entries 3. **Phase 3** — Update base template versions and scripts 4. **Phase 4** — Update template files for each breaking change, one at a time: - a. Tailwind v4.3 (lowest risk) - b. Next.js 16 (async params, scripts, eslint config) - c. lucide-react v1 (icon imports in connect components) - d. wagmi v3 (config files, provider components) - e. privy v3 + @privy-io/wagmi v4 (config, provider, integration) 5. **Phase 5** — CI/CD updates ### After All Phases 1. Run `pnpm typecheck` — must pass 2. Run `pnpm lint` — must pass 3. Run `pnpm build` — must build successfully 4. Scaffold a test project with `pnpm start ../test-app` 5. In the test project: `pnpm install && pnpm typecheck && pnpm build` — all must pass 6. Create a changeset and release