create-react-starter-kit 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/cli-args.d.ts.map +1 -1
  2. package/dist/cli-args.js +2 -1
  3. package/dist/cli-args.js.map +1 -1
  4. package/dist/generator/dependencies.d.ts.map +1 -1
  5. package/dist/generator/dependencies.js +5 -0
  6. package/dist/generator/dependencies.js.map +1 -1
  7. package/dist/generator/index.d.ts.map +1 -1
  8. package/dist/generator/index.js +5 -0
  9. package/dist/generator/index.js.map +1 -1
  10. package/dist/prompts/index.d.ts.map +1 -1
  11. package/dist/prompts/index.js +8 -0
  12. package/dist/prompts/index.js.map +1 -1
  13. package/dist/templates/README.md.ejs +1 -1
  14. package/dist/templates/__when_apiLayer_axios__/src/services/api.ts.ejs +23 -0
  15. package/dist/templates/__when_apiLayer_axios__/src/services/http/client.ts.ejs +174 -0
  16. package/dist/templates/__when_apiLayer_axios__/src/services/http/errors.ts.ejs +81 -0
  17. package/dist/templates/__when_apiLayer_axios__/src/services/http/index.ts.ejs +5 -0
  18. package/dist/templates/__when_apiLayer_fetch__/src/services/api.ts.ejs +22 -0
  19. package/dist/templates/__when_apiLayer_fetch__/src/services/http/client.ts.ejs +195 -0
  20. package/dist/templates/__when_apiLayer_fetch__/src/services/http/errors.ts.ejs +81 -0
  21. package/dist/templates/__when_apiLayer_fetch__/src/services/http/index.ts.ejs +5 -0
  22. package/dist/templates/__when_buildTool_vite__/vite.config.ts.ejs +9 -1
  23. package/dist/templates/__when_buildTool_webpack__/webpack.config.js.ejs +1 -1
  24. package/dist/templates/__when_e2eTesting_cypress__/cypress.config.ts.ejs +2 -1
  25. package/dist/templates/__when_e2eTesting_playwright__/playwright.config.ts.ejs +4 -3
  26. package/dist/templates/__when_serverState_rtk-query__/src/store/postsApi.ts.ejs +28 -5
  27. package/dist/templates/__when_unitTesting_jest__/jest.config.json.ejs +8 -0
  28. package/dist/templates/__when_unitTesting_vitest__/tests/feedback.test.tsx.ejs +16 -0
  29. package/dist/templates/__when_unitTesting_vitest__/tests/posts.test.tsx.ejs +1 -3
  30. package/dist/templates/__when_unitTesting_vitest__/vitest.config.ts.ejs +31 -0
  31. package/dist/templates/docs/architecture.md.ejs +44 -25
  32. package/dist/templates/docs/best-practices.md.ejs +39 -3
  33. package/dist/templates/docs/examples/README.md.ejs +10 -10
  34. package/dist/templates/docs/examples/api.md.ejs +165 -8
  35. package/dist/templates/docs/examples/data-fetching.md.ejs +107 -6
  36. package/dist/templates/docs/examples/forms.md.ejs +66 -6
  37. package/dist/templates/docs/examples/state.md.ejs +50 -6
  38. package/dist/templates/docs/examples/styling.md.ejs +56 -8
  39. package/dist/templates/docs/examples/testing.md.ejs +63 -9
  40. package/dist/templates/docs/getting-started.md.ejs +63 -15
  41. package/dist/templates/docs/selected-stack.md.ejs +110 -8
  42. package/dist/templates/src/features/feedback/FeedbackForm.tsx.ejs +10 -0
  43. package/dist/templates/src/features/posts/PostsPanel.tsx.ejs +1 -1
  44. package/dist/templates/src/routes/PostsPage.tsx.ejs +7 -2
  45. package/dist/templates/src/types/index.ts.ejs +1 -1
  46. package/dist/templates/src/types/models.ts.ejs +18 -0
  47. package/dist/types.d.ts +1 -1
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/templates/README.md.ejs +1 -1
  51. package/templates/__when_apiLayer_axios__/src/services/api.ts.ejs +23 -0
  52. package/templates/__when_apiLayer_axios__/src/services/http/client.ts.ejs +174 -0
  53. package/templates/__when_apiLayer_axios__/src/services/http/errors.ts.ejs +81 -0
  54. package/templates/__when_apiLayer_axios__/src/services/http/index.ts.ejs +5 -0
  55. package/templates/__when_apiLayer_fetch__/src/services/api.ts.ejs +22 -0
  56. package/templates/__when_apiLayer_fetch__/src/services/http/client.ts.ejs +195 -0
  57. package/templates/__when_apiLayer_fetch__/src/services/http/errors.ts.ejs +81 -0
  58. package/templates/__when_apiLayer_fetch__/src/services/http/index.ts.ejs +5 -0
  59. package/templates/__when_buildTool_vite__/vite.config.ts.ejs +9 -1
  60. package/templates/__when_buildTool_webpack__/webpack.config.js.ejs +1 -1
  61. package/templates/__when_e2eTesting_cypress__/cypress.config.ts.ejs +2 -1
  62. package/templates/__when_e2eTesting_playwright__/playwright.config.ts.ejs +4 -3
  63. package/templates/__when_serverState_rtk-query__/src/store/postsApi.ts.ejs +28 -5
  64. package/templates/__when_unitTesting_jest__/jest.config.json.ejs +8 -0
  65. package/templates/__when_unitTesting_vitest__/tests/feedback.test.tsx.ejs +16 -0
  66. package/templates/__when_unitTesting_vitest__/tests/posts.test.tsx.ejs +1 -3
  67. package/templates/__when_unitTesting_vitest__/vitest.config.ts.ejs +31 -0
  68. package/templates/docs/architecture.md.ejs +44 -25
  69. package/templates/docs/best-practices.md.ejs +39 -3
  70. package/templates/docs/examples/README.md.ejs +10 -10
  71. package/templates/docs/examples/api.md.ejs +165 -8
  72. package/templates/docs/examples/data-fetching.md.ejs +107 -6
  73. package/templates/docs/examples/forms.md.ejs +66 -6
  74. package/templates/docs/examples/state.md.ejs +50 -6
  75. package/templates/docs/examples/styling.md.ejs +56 -8
  76. package/templates/docs/examples/testing.md.ejs +63 -9
  77. package/templates/docs/getting-started.md.ejs +63 -15
  78. package/templates/docs/selected-stack.md.ejs +110 -8
  79. package/templates/src/features/feedback/FeedbackForm.tsx.ejs +10 -0
  80. package/templates/src/features/posts/PostsPanel.tsx.ejs +1 -1
  81. package/templates/src/routes/PostsPage.tsx.ejs +7 -2
  82. package/templates/src/types/index.ts.ejs +1 -1
  83. package/templates/src/types/models.ts.ejs +18 -0
  84. package/dist/templates/src/services/api.ts.ejs +0 -84
  85. package/templates/src/services/api.ts.ejs +0 -84
@@ -8,20 +8,74 @@
8
8
 
9
9
  ## When to use
10
10
 
11
- - Unit: pure logic + component behavior
12
- - E2E: critical journeys across routes
13
- - Visual: regressions in UI appearance
11
+ | Layer | Use for | Avoid using for |
12
+ |-------|---------|-----------------|
13
+ | Unit / RTL | logic, component behavior, form validation | full auth/payment journeys |
14
+ | E2E | critical user journeys across routes | asserting every CSS class |
15
+ | Visual | regressions in appearance / states | business-rule correctness |
14
16
 
15
- ## Best practice
17
+ ## How to run
16
18
 
17
- Keep e2e thin. Prefer Testing Library queries that reflect how users find elements (`getByRole`, labels).
19
+ <% if (unitTesting !== 'none') { -%>
20
+ ```bash
21
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test
22
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test:watch
23
+ ```
24
+ <% } -%>
25
+ <% if (e2eTesting === 'playwright') { -%>
26
+ ```bash
27
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e:install # once
28
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e
29
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e:ui
30
+ ```
18
31
 
19
- ## Locations
32
+ E2E base URL: `http://127.0.0.1:<%= buildTool === 'webpack' ? 3000 : 5173 %>`
33
+ <% } else if (e2eTesting === 'cypress') { -%>
34
+ ```bash
35
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e
36
+ ```
37
+ <% } -%>
38
+ <% if (visualTesting === 'storybook') { -%>
39
+ ```bash
40
+ <%= packageManager === 'npm' ? 'npm run' : packageManager %> storybook
41
+ ```
42
+ <% } -%>
43
+
44
+ ## Project layout
20
45
 
21
46
  - Setup: `tests/setup.<%= ext %>` (when applicable)
22
- - Component smoke: `tests/App.test.<%= jsxExt %>`
47
+ - Unit suites: `tests/*.test.<%= jsxExt %>`
23
48
  <% if (e2eTesting === 'playwright') { -%>
24
- - E2E: `tests/e2e/home.spec.<%= ext %>`
49
+ - E2E: `tests/e2e/*.spec.<%= ext %>` (excluded from unit runner)
25
50
  <% } else if (e2eTesting === 'cypress') { -%>
26
- - E2E: `cypress/e2e/home.cy.<%= ext %>`
51
+ - E2E: `cypress/e2e/*`
52
+ <% } -%>
53
+ <% if (visualTesting === 'storybook') { -%>
54
+ - Stories: `src/**/*.stories.<%= jsxExt %>`
27
55
  <% } -%>
56
+
57
+ ## Best practices
58
+
59
+ - Query the way users do: `getByRole`, label text, placeholder — not implementation details.
60
+ - Mock at the **network/domain boundary**:
61
+ <% if (serverState === 'rtk-query') { -%>
62
+ - mock RTK hooks/endpoints for unit tests when you are not integration-testing the store
63
+ <% } else { -%>
64
+ - mock `@/services/api` helpers rather than axios/fetch internals
65
+ <% } -%>
66
+ - Keep e2e **thin**: home load, posts happy path, feedback submit.
67
+ - Do not let unit tests import Playwright specs (unit config excludes `tests/e2e`).
68
+ - For async UI, prefer `findBy*` / `waitFor` over arbitrary `sleep`.
69
+
70
+ ## Example unit test shape
71
+
72
+ ```tsx
73
+ renderWithProviders(<FeedbackForm />);
74
+ await user.click(screen.getByRole('button', { name: /Send feedback/i }));
75
+ expect(screen.getAllByText(/required|valid email/i).length).toBeGreaterThan(0);
76
+ ```
77
+
78
+ ## Related
79
+
80
+ - Strategy & CI: `docs/best-practices.md`
81
+ - Forms guide: `docs/examples/forms.md`
@@ -2,10 +2,13 @@
2
2
 
3
3
  Welcome to **<%= projectName %>**, a React starter generated by `create-react-starter-kit`.
4
4
 
5
+ This guide walks you from first install to extending the app with confidence.
6
+
5
7
  ## Prerequisites
6
8
 
7
- - Node.js 18+
8
- - <%= stackLabels.packageManager %>
9
+ - **Node.js 18+** (20 LTS recommended)
10
+ - **<%= stackLabels.packageManager %>** installed globally or via Corepack
11
+ - A modern browser for the demo UI
9
12
 
10
13
  ## Install & run
11
14
 
@@ -22,26 +25,68 @@ npm run dev
22
25
  <% } -%>
23
26
  ```
24
27
 
28
+ Dev server URL (default): **http://localhost:<%= buildTool === 'webpack' ? 3000 : 5173 %>**
29
+
30
+ Useful scripts:
31
+
32
+ | Script | Purpose |
33
+ |--------|---------|
34
+ | `dev` | Local development server |
35
+ | `build` | Production bundle |
36
+ | `preview` | Serve the production build locally |
37
+ <% if (unitTesting !== 'none') { -%>
38
+ | `test` / `test:watch` | Unit tests |
39
+ <% } -%>
40
+ <% if (e2eTesting !== 'none') { -%>
41
+ | `test:e2e` | End-to-end tests |
42
+ <% } -%>
43
+ <% if (visualTesting === 'storybook') { -%>
44
+ | `storybook` | Component explorer |
45
+ <% } -%>
46
+ | `lint` / `format` | Code quality |
47
+
25
48
  ## Environment variables
26
49
 
27
- Copy `.env.example` → `.env` and fill values. Restart the dev server after changes.
50
+ 1. Copy `.env.example` → `.env`
51
+ 2. Fill values for your environment
52
+ 3. Restart `dev` after changes
28
53
 
29
- Only variables prefixed for your bundler (e.g. `VITE_`) are exposed to the browser. Keep secrets on the server.
54
+ Only client-safe variables (typically `VITE_*`) are exposed to the browser. Never put private API keys in front-end env vars.
55
+
56
+ | Variable | Purpose |
57
+ |----------|---------|
58
+ | `VITE_API_BASE_URL` | REST API base URL (defaults to JSONPlaceholder for demos) |
59
+ <% if (errorTracking === 'sentry') { -%>
60
+ | `VITE_SENTRY_DSN` | Sentry DSN |
61
+ <% } else if (errorTracking === 'bugsnag') { -%>
62
+ | `VITE_BUGSNAG_API_KEY` | Bugsnag API key |
63
+ <% } else if (errorTracking === 'logrocket') { -%>
64
+ | `VITE_LOGROCKET_APP_ID` | LogRocket app id |
65
+ <% } else if (errorTracking === 'datadog') { -%>
66
+ | `VITE_DATADOG_APPLICATION_ID` / `VITE_DATADOG_CLIENT_TOKEN` | Datadog RUM |
67
+ <% } -%>
30
68
 
31
69
  ## What to explore first
32
70
 
33
- 1. Open `/` demo panels for state, data fetching, and forms.
34
- 2. Open `/about` orientation for the folder layout.
35
- 3. Read `docs/selected-stack.md` why each library is present.
36
- 4. Skim `docs/examples/` focused usage notes per concern.
71
+ 1. **`/`**stack badges and orientation
72
+ 2. **`/counter`**client state (<%= stackLabels.stateManagement %>)
73
+ 3. **`/posts`**server state (<%= stackLabels.serverState %>)
74
+ 4. **`/feedback`**forms + validation (<%= stackLabels.forms %> / <%= stackLabels.validation %>)
75
+ 5. **`docs/selected-stack.md`** — why each library was chosen
76
+ 6. **`docs/examples/`** — deep usage guides with copy-paste patterns
37
77
 
38
- ## Extending the app
78
+ ## Extending the app (recommended flow)
39
79
 
40
- - Add a domain under `src/features/<name>/`.
41
- - Register routes in `src/App.<%= jsxExt %>`.
42
- - Put shared UI in `src/components/`.
43
- - Put HTTP clients in `src/services/`.
44
- - Import with `@/` (maps to `src/`), e.g. `import { env } from '@/config/env'`.
80
+ 1. Create a feature folder: `src/features/<domain>/`
81
+ 2. Add UI, hooks, and domain types next to that feature
82
+ 3. Register a route in `src/App.<%= jsxExt %>`
83
+ 4. Put shared primitives in `src/components/`
84
+ <% if (apiLayer === 'none') { -%>
85
+ 5. Add RTK Query endpoints in `src/store/` (or a feature-local `*Api` slice)
86
+ <% } else { -%>
87
+ 5. Add HTTP helpers in `src/services/api.<%= ext %>` (and keep transport details in `src/services/http/`)
88
+ <% } -%>
89
+ 6. Import with `@/` — e.g. `import { env } from '@/config/env'`
45
90
 
46
91
  ## Testing
47
92
 
@@ -51,5 +96,8 @@ Only variables prefixed for your bundler (e.g. `VITE_`) are exposed to the brows
51
96
  <% if (e2eTesting !== 'none') { -%>
52
97
  - E2E: `<%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e`
53
98
  <% } -%>
99
+ <% if (visualTesting === 'storybook') { -%>
100
+ - Storybook: `<%= packageManager === 'npm' ? 'npm run' : packageManager %> storybook`
101
+ <% } -%>
54
102
 
55
- See `docs/best-practices.md` for CI and production notes.
103
+ See `docs/best-practices.md` and `docs/examples/testing.md` for strategy and CI notes.
@@ -1,44 +1,146 @@
1
1
  # Selected stack
2
2
 
3
- This document explains each choice made when generating **<%= projectName %>**.
3
+ This document explains each choice made when generating **<%= projectName %>**, how to use it day-to-day, and the practices that keep the codebase maintainable.
4
4
 
5
5
  ## Build — <%= stackLabels.buildTool %>
6
6
 
7
- Fast local feedback and a production bundle. Prefer keeping config minimal; add plugins only when needed.
7
+ <% if (buildTool === 'vite') { -%>
8
+ Vite gives fast HMR and a Rollup-based production build. Config lives in `vite.config.<%= ext %>`.
8
9
 
9
- **Best practice:** lock Node and package manager versions in CI for reproducible builds.
10
+ **Day-to-day:** `<%= packageManager === 'npm' ? 'npm run' : packageManager %> dev` → http://localhost:5173
11
+ <% } else if (buildTool === 'webpack') { -%>
12
+ Webpack is configured in `webpack.config.js` with Babel (or TS pipeline), HtmlWebpackPlugin, and a dev server.
13
+
14
+ **Day-to-day:** `<%= packageManager === 'npm' ? 'npm run' : packageManager %> dev` → http://localhost:3000
15
+ <% } else { -%>
16
+ Your bundler is wired with scripts in `package.json`. Prefer keeping config minimal; add plugins only when needed.
17
+ <% } -%>
18
+
19
+ **Best practices**
20
+
21
+ - Lock Node and package manager versions in CI.
22
+ - Treat `build` as the source of truth for production issues (not only `dev`).
23
+ - Keep path aliases (`@/`) in sync between TS config and the bundler.
10
24
 
11
25
  ## Language — <%= stackLabels.language %>
12
26
 
13
27
  <% if (isTypeScript) { -%>
14
- TypeScript catches contract mistakes early. Keep `strict` on; avoid `any` except at true boundaries.
28
+ TypeScript catches contract mistakes early. Keep `strict` on; avoid `any` except at true boundaries (third-party quirks, gradual migrations).
29
+
30
+ **Pattern:** model API payloads in `src/types/models.<%= ext %>`, not inline in components.
15
31
  <% } else { -%>
16
- JavaScript keeps the barrier low. Consider migrating hot modules to TypeScript as the app grows.
32
+ JavaScript keeps the barrier low. Prefer JSDoc for public helpers, and consider migrating hot modules to TypeScript as the app grows.
17
33
  <% } -%>
18
34
 
19
35
  ## Routing — <%= stackLabels.router %>
20
36
 
21
37
  Client-side navigation with nested layouts. Keep route modules thin; push data loading into features.
22
38
 
39
+ **Best practices**
40
+
41
+ - Colocate route-level UI under `src/routes/`.
42
+ - Avoid fetching in layout components unless every child needs the data.
43
+ - Use loading/error UI at the feature boundary.
44
+
23
45
  ## Client state — <%= stackLabels.stateManagement %>
24
46
 
25
47
  Use for UI state (modals, wizards, ephemeral counters). Do **not** mirror server entities here if you have a server-state library.
26
48
 
49
+ **Live demo:** `/counter` → `src/features/counter/`
50
+
51
+ **Best practices**
52
+
53
+ - Feature-local state first; promote to global only when multiple distant trees need it.
54
+ - Keep stores/slices focused on one domain.
55
+ - Prefer selectors/hooks over reading the whole store in components.
56
+
27
57
  ## Server state — <%= stackLabels.serverState %>
28
58
 
29
- Caches remote data, handles loading/error, and deduplicates requests. Example: posts panel on the home page.
59
+ Caches remote data, handles loading/error, and deduplicates requests.
60
+
61
+ **Live demo:** `/posts` → `src/features/posts/PostsPanel.<%= jsxExt %>`
62
+
63
+ <% if (serverState === 'rtk-query') { -%>
64
+ **How to use**
65
+
66
+ 1. Define endpoints in `src/store/postsApi.<%= ext %>` (or a new `*Api` slice).
67
+ 2. Export hooks (`useGetPostsQuery`, `useCreateFeedbackMutation`).
68
+ 3. Call hooks from features — no manual `useEffect` fetching.
69
+
70
+ **Best practices**
71
+
72
+ - Use `tagTypes` + `providesTags` / `invalidatesTags` for cache coherence.
73
+ - Put auth headers in `prepareHeaders`, not in every endpoint.
74
+ - Prefer mutations for writes; invalidate related query tags after success.
75
+ <% } else if (serverState === 'tanstack-query') { -%>
76
+ **How to use**
77
+
78
+ ```tsx
79
+ const { data, isLoading, error, refetch } = useQuery({
80
+ queryKey: ['posts'],
81
+ queryFn: ({ signal }) => fetchPosts(signal),
82
+ });
83
+ ```
84
+
85
+ **Best practices**
86
+
87
+ - Stable, hierarchical query keys: `['posts']`, `['posts', id]`.
88
+ - Pass `signal` into your HTTP helpers so navigations cancel in-flight work.
89
+ - Keep `queryFn` thin — call domain API helpers, not raw HTTP.
90
+ <% } else if (serverState === 'swr') { -%>
91
+ **How to use**
92
+
93
+ SWR is configured in `providers.<%= jsxExt %>` with a shared `fetcher`. Components call `useSWR(key)`.
94
+
95
+ **Best practices**
96
+
97
+ - Keys should be URLs or stable resource identifiers.
98
+ - Use `mutate` for local revalidation after writes.
99
+ <% } else { -%>
100
+ No dedicated server-state library was selected. Prefer adding one before the app grows past a few screens.
101
+ <% } -%>
30
102
 
31
103
  ## Forms — <%= stackLabels.forms %> / Validation — <%= stackLabels.validation %>
32
104
 
33
105
  Schemas define the contract; the form library binds inputs. Share schemas with API payloads when possible.
34
106
 
107
+ **Live demo:** `/feedback` → `src/features/feedback/FeedbackForm.<%= jsxExt %>`
108
+ **Schemas:** `src/lib/validation.<%= ext %>`
109
+
110
+ **Best practices**
111
+
112
+ - Validate on submit (and optionally on blur) — avoid blocking every keystroke unless UX requires it.
113
+ - Keep error messages user-facing; log technical details separately.
114
+ - Reuse the same schema on the server if you own both sides.
115
+
35
116
  ## Styling — <%= stackLabels.styling %> / UI — <%= stackLabels.uiLibrary %>
36
117
 
37
118
  Tokens and primitives establish visual consistency. Prefer composition over one-off CSS.
38
119
 
120
+ **Best practices**
121
+
122
+ - Wrap third-party primitives in thin adapters (`UiButton`) so swapping kits later is cheaper.
123
+ - Keep global tokens in `src/styles/`; keep feature-specific styles close to the feature.
124
+
39
125
  ## API — <%= stackLabels.apiLayer %>
40
126
 
41
- Centralize base URL, headers, and error logging in `src/services/api.<%= ext %>`.
127
+ <% if (apiLayer === 'none') { -%>
128
+ HTTP is owned by **RTK Query** (`fetchBaseQuery`). There is intentionally **no** separate Axios/Fetch client in this project.
129
+
130
+ See `docs/examples/data-fetching.md` and `src/store/postsApi.<%= ext %>`.
131
+ <% } else if (apiLayer === 'axios') { -%>
132
+ Axios is configured under `src/services/http/` with:
133
+
134
+ - request interceptors (auth token, request IDs)
135
+ - response interceptors (normalized `ApiError`, 401 event)
136
+ - domain helpers in `src/services/api.<%= ext %>`
137
+
138
+ See `docs/examples/api.md` for patterns and examples.
139
+ <% } else { -%>
140
+ A shared Fetch wrapper lives under `src/services/http/` with timeout, auth headers, request IDs, and normalized `ApiError`s. Domain helpers sit in `src/services/api.<%= ext %>`.
141
+
142
+ See `docs/examples/api.md` for patterns and examples.
143
+ <% } -%>
42
144
 
43
145
  ## Quality gates
44
146
 
@@ -52,4 +154,4 @@ Centralize base URL, headers, and error logging in `src/services/api.<%= ext %>`
52
154
  | Git hooks | Husky + lint-staged + commitlint |
53
155
  | Structure | Feature-based + `@/` aliases |
54
156
 
55
- See `docs/examples/` for focused usage notes.
157
+ See `docs/examples/` for focused usage notes with deeper examples.
@@ -32,7 +32,11 @@ import { validateFeedback<% if (isTypeScript) { %>, type FeedbackValues<% } %> }
32
32
  import { feedbackSchema<% if (isTypeScript) { %>, type FeedbackValues<% } %> } from '@/lib/validation';
33
33
  <% } -%>
34
34
  <% } -%>
35
+ <% if (serverState === 'rtk-query') { -%>
36
+ import { useCreateFeedbackMutation } from '@/store/postsApi';
37
+ <% } else { -%>
35
38
  import { createFeedback } from '@/services/api';
39
+ <% } -%>
36
40
  import { UiButton } from '@/components/ui/UiButton';
37
41
 
38
42
  const defaults<% if (isTypeScript) { %>: FeedbackValues<% } %> = {
@@ -43,6 +47,12 @@ const defaults<% if (isTypeScript) { %>: FeedbackValues<% } %> = {
43
47
 
44
48
  export function FeedbackForm() {
45
49
  const [status, setStatus] = useState<% if (isTypeScript) { %><string | null><% } %>(null);
50
+ <% if (serverState === 'rtk-query') { -%>
51
+ const [createFeedbackMutation] = useCreateFeedbackMutation();
52
+ const createFeedback = async (values<% if (isTypeScript) { %>: FeedbackValues<% } %>) => {
53
+ await createFeedbackMutation(values).unwrap();
54
+ };
55
+ <% } -%>
46
56
 
47
57
  <% if (forms === 'react-hook-form') { -%>
48
58
  const {
@@ -14,7 +14,7 @@ export function PostsPanel() {
14
14
  <% if (serverState === 'tanstack-query') { -%>
15
15
  const { data, isLoading, error, refetch, isFetching } = useQuery({
16
16
  queryKey: ['posts'],
17
- queryFn: fetchPosts,
17
+ queryFn: ({ signal }) => fetchPosts(signal),
18
18
  });
19
19
  <% } else if (serverState === 'swr') { -%>
20
20
  const { data, error, isLoading, isValidating, mutate } = useSWR('/posts?_limit=5');
@@ -7,8 +7,13 @@ export function PostsPage() {
7
7
  <p className="eyebrow">Server state</p>
8
8
  <h1>Posts</h1>
9
9
  <p className="lede">
10
- Fetches sample posts via <strong><%= stackLabels.serverState === 'None' ? stackLabels.apiLayer : stackLabels.serverState %></strong>{' '}
11
- and <strong><%= stackLabels.apiLayer %></strong>.
10
+ Fetches sample posts via <strong><%= stackLabels.serverState === 'None' ? stackLabels.apiLayer : stackLabels.serverState %></strong>
11
+ <% if (apiLayer !== 'none' && serverState !== 'rtk-query') { -%>
12
+ {' '}and <strong><%= stackLabels.apiLayer %></strong>
13
+ <% } else if (serverState === 'rtk-query') { -%>
14
+ {' '}(HTTP via <code>fetchBaseQuery</code>)
15
+ <% } -%>
16
+ .
12
17
  </p>
13
18
  </header>
14
19
  <PostsPanel />
@@ -1,6 +1,6 @@
1
1
  <% if (isTypeScript) { -%>
2
2
  /** Shared domain types used across features. */
3
- export type { Post } from '@/services/api';
3
+ export type { Post, FeedbackPayload } from './models';
4
4
  <% } else { -%>
5
5
  // Shared types live here when you migrate hot paths to TypeScript.
6
6
  export {};
@@ -0,0 +1,18 @@
1
+ <% if (isTypeScript) { -%>
2
+ /** Shared domain models used by features and the HTTP / RTK layers. */
3
+ export interface Post {
4
+ userId: number;
5
+ id: number;
6
+ title: string;
7
+ body: string;
8
+ }
9
+
10
+ export interface FeedbackPayload {
11
+ name: string;
12
+ email: string;
13
+ message: string;
14
+ }
15
+ <% } else { -%>
16
+ // Shared domain models live here when you migrate hot paths to TypeScript.
17
+ export {};
18
+ <% } -%>
package/dist/types.d.ts CHANGED
@@ -12,7 +12,7 @@ export type E2ETesting = 'playwright' | 'cypress' | 'none';
12
12
  export type VisualTesting = 'storybook' | 'chromatic' | 'none';
13
13
  export type Linting = 'eslint' | 'biome';
14
14
  export type Formatting = 'prettier' | 'stylelint';
15
- export type ApiLayer = 'axios' | 'fetch';
15
+ export type ApiLayer = 'axios' | 'fetch' | 'none';
16
16
  export type PackageManager = 'pnpm' | 'yarn' | 'npm';
17
17
  export type ErrorTracking = 'sentry' | 'bugsnag' | 'logrocket' | 'datadog' | 'none';
18
18
  export interface ProjectAnswers {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AACxF,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC;AACxD,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACjF,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;AAC1E,MAAM,MAAM,KAAK,GAAG,iBAAiB,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,CAAC;AAC5E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAChF,MAAM,MAAM,SAAS,GACjB,KAAK,GACL,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,MAAM,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAC7D,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;AAC/D,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAClD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AACzC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AACrD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,aAAa,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;IACjB,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AACxF,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC;AACxD,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACjF,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;AAC1E,MAAM,MAAM,KAAK,GAAG,iBAAiB,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,CAAC;AAC5E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAChF,MAAM,MAAM,SAAS,GACjB,KAAK,GACL,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,MAAM,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAC7D,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;AAC/D,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAClD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAClD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AACrD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,aAAa,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;IACjB,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-react-starter-kit",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Interactive CLI to scaffold a production-ready React app with your preferred stack",
5
5
  "keywords": [
6
6
  "react",
@@ -45,7 +45,7 @@ npm run dev
45
45
  <% } -%>
46
46
  ```
47
47
 
48
- Open the URL printed in the terminal (typically `http://localhost:5173`).
48
+ Open the URL printed in the terminal (typically `http://localhost:<%= buildTool === 'webpack' ? 3000 : 5173 %>`).
49
49
 
50
50
  ## Environment setup
51
51
 
@@ -0,0 +1,23 @@
1
+ import { apiGet, apiPost } from '@/services/http';
2
+ <% if (isTypeScript) { -%>
3
+ import type { FeedbackPayload, Post } from '@/types/models';
4
+ <% } -%>
5
+
6
+ /**
7
+ * Domain API methods — keep React components free of raw URLs and HTTP details.
8
+ * Call these from TanStack Query / SWR queryFns, or directly for simple mutations.
9
+ */
10
+ export async function fetchPosts(signal<% if (isTypeScript) { %>?: AbortSignal<% } %>) {
11
+ return apiGet<% if (isTypeScript) { %><Post[]><% } %>('/posts?_limit=5', { signal });
12
+ }
13
+
14
+ export async function createFeedback(
15
+ payload<% if (isTypeScript) { %>: FeedbackPayload<% } %>,
16
+ signal<% if (isTypeScript) { %>?: AbortSignal<% } %>,
17
+ ) {
18
+ return apiPost('/posts', payload, { signal });
19
+ }
20
+
21
+ <% if (isTypeScript) { -%>
22
+ export type { FeedbackPayload, Post } from '@/types/models';
23
+ <% } -%>