create-react-starter-kit 1.0.0

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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/bin/create-react-starter-kit.js +7 -0
  4. package/dist/cli-args.d.ts +15 -0
  5. package/dist/cli-args.d.ts.map +1 -0
  6. package/dist/cli-args.js +78 -0
  7. package/dist/cli-args.js.map +1 -0
  8. package/dist/generator/dependencies.d.ts +8 -0
  9. package/dist/generator/dependencies.d.ts.map +1 -0
  10. package/dist/generator/dependencies.js +356 -0
  11. package/dist/generator/dependencies.js.map +1 -0
  12. package/dist/generator/index.d.ts +5 -0
  13. package/dist/generator/index.d.ts.map +1 -0
  14. package/dist/generator/index.js +358 -0
  15. package/dist/generator/index.js.map +1 -0
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +38 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/prompts/index.d.ts +3 -0
  21. package/dist/prompts/index.d.ts.map +1 -0
  22. package/dist/prompts/index.js +267 -0
  23. package/dist/prompts/index.js.map +1 -0
  24. package/dist/templates/.env.example.ejs +21 -0
  25. package/dist/templates/.husky/commit-msg +2 -0
  26. package/dist/templates/.husky/pre-commit +2 -0
  27. package/dist/templates/README.md.ejs +169 -0
  28. package/dist/templates/__js__/jsconfig.json +9 -0
  29. package/dist/templates/__ts__/src/vite-env.d.ts +16 -0
  30. package/dist/templates/__ts__/tsconfig.json +24 -0
  31. package/dist/templates/__when_buildTool_esbuild__/scripts/esbuild.build.mjs.ejs +23 -0
  32. package/dist/templates/__when_buildTool_esbuild__/scripts/esbuild.dev.mjs.ejs +48 -0
  33. package/dist/templates/__when_buildTool_parcel__/.parcelrc +9 -0
  34. package/dist/templates/__when_buildTool_rollup__/rollup.config.js.ejs +33 -0
  35. package/dist/templates/__when_buildTool_rspack__/rspack.config.js.ejs +36 -0
  36. package/dist/templates/__when_buildTool_vite__/vite.config.ts.ejs +37 -0
  37. package/dist/templates/__when_buildTool_webpack__/webpack.config.js.ejs +68 -0
  38. package/dist/templates/__when_e2eTesting_cypress__/cypress/e2e/home.cy.ts.ejs +6 -0
  39. package/dist/templates/__when_e2eTesting_cypress__/cypress.config.ts.ejs +8 -0
  40. package/dist/templates/__when_e2eTesting_playwright__/playwright.config.ts.ejs +16 -0
  41. package/dist/templates/__when_e2eTesting_playwright__/tests/e2e/home.spec.ts.ejs +6 -0
  42. package/dist/templates/__when_formatting_prettier__/.prettierrc +7 -0
  43. package/dist/templates/__when_formatting_stylelint__/.stylelintrc.json +3 -0
  44. package/dist/templates/__when_linting_biome__/biome.json +19 -0
  45. package/dist/templates/__when_linting_eslint__/eslint.config.js.ejs +42 -0
  46. package/dist/templates/__when_serverState_rtk-query__/src/store/postsApi.ts.ejs +19 -0
  47. package/dist/templates/__when_stateManagement_context__/src/store/context.tsx.ejs +57 -0
  48. package/dist/templates/__when_styling_tailwind__/postcss.config.js +6 -0
  49. package/dist/templates/__when_styling_tailwind__/tailwind.config.js.ejs +23 -0
  50. package/dist/templates/__when_unitTesting_jest__/jest.config.json.ejs +11 -0
  51. package/dist/templates/__when_unitTesting_jest__/tests/App.test.tsx.ejs +13 -0
  52. package/dist/templates/__when_unitTesting_jest__/tests/setup.ts.ejs +1 -0
  53. package/dist/templates/__when_unitTesting_jest__/tests/styleMock.ts.ejs +1 -0
  54. package/dist/templates/__when_unitTesting_rtl__/tests/App.test.tsx.ejs +13 -0
  55. package/dist/templates/__when_unitTesting_vitest__/tests/App.test.tsx.ejs +16 -0
  56. package/dist/templates/__when_unitTesting_vitest__/tests/setup.ts.ejs +1 -0
  57. package/dist/templates/__when_visualTesting_storybook__/.storybook/main.js.ejs +11 -0
  58. package/dist/templates/__when_visualTesting_storybook__/.storybook/preview.js +8 -0
  59. package/dist/templates/__when_visualTesting_storybook__/src/components/ui/UiButton.stories.tsx.ejs +15 -0
  60. package/dist/templates/commitlint.config.js +3 -0
  61. package/dist/templates/docs/architecture.md.ejs +74 -0
  62. package/dist/templates/docs/best-practices.md.ejs +56 -0
  63. package/dist/templates/docs/examples/README.md.ejs +14 -0
  64. package/dist/templates/docs/examples/api.md.ejs +17 -0
  65. package/dist/templates/docs/examples/data-fetching.md.ejs +18 -0
  66. package/dist/templates/docs/examples/forms.md.ejs +18 -0
  67. package/dist/templates/docs/examples/state.md.ejs +17 -0
  68. package/dist/templates/docs/examples/styling.md.ejs +23 -0
  69. package/dist/templates/docs/examples/testing.md.ejs +27 -0
  70. package/dist/templates/docs/getting-started.md.ejs +55 -0
  71. package/dist/templates/docs/selected-stack.md.ejs +55 -0
  72. package/dist/templates/index.html.ejs +19 -0
  73. package/dist/templates/public/vite.svg +4 -0
  74. package/dist/templates/src/app/App.tsx.ejs +71 -0
  75. package/dist/templates/src/app/providers.tsx.ejs +93 -0
  76. package/dist/templates/src/assets/.gitkeep +0 -0
  77. package/dist/templates/src/components/StackBadge.tsx.ejs +15 -0
  78. package/dist/templates/src/components/layout/AppLayout.tsx.ejs +64 -0
  79. package/dist/templates/src/components/ui/Toast.tsx.ejs +61 -0
  80. package/dist/templates/src/components/ui/UiButton.tsx.ejs +168 -0
  81. package/dist/templates/src/config/env.ts.ejs +18 -0
  82. package/dist/templates/src/features/counter/CounterPanel.tsx.ejs +66 -0
  83. package/dist/templates/src/features/feedback/FeedbackForm.tsx.ejs +373 -0
  84. package/dist/templates/src/features/posts/PostsPanel.tsx.ejs +91 -0
  85. package/dist/templates/src/hooks/useMounted.ts.ejs +15 -0
  86. package/dist/templates/src/lib/cn.ts.ejs +12 -0
  87. package/dist/templates/src/lib/monitoring.ts.ejs +66 -0
  88. package/dist/templates/src/lib/validation.ts.ejs +81 -0
  89. package/dist/templates/src/main.tsx.ejs +22 -0
  90. package/dist/templates/src/routes/AboutPage.tsx.ejs +30 -0
  91. package/dist/templates/src/routes/HomePage.tsx.ejs +47 -0
  92. package/dist/templates/src/services/api.ts.ejs +84 -0
  93. package/dist/templates/src/store/index.ts.ejs +80 -0
  94. package/dist/templates/src/styles/global.css.ejs +457 -0
  95. package/dist/templates/src/types/index.ts.ejs +7 -0
  96. package/dist/templates/src/utils/format.ts.ejs +3 -0
  97. package/dist/types.d.ts +46 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/dist/utils/logger.d.ts +12 -0
  102. package/dist/utils/logger.d.ts.map +1 -0
  103. package/dist/utils/logger.js +31 -0
  104. package/dist/utils/logger.js.map +1 -0
  105. package/dist/utils/validate.d.ts +3 -0
  106. package/dist/utils/validate.d.ts.map +1 -0
  107. package/dist/utils/validate.js +24 -0
  108. package/dist/utils/validate.js.map +1 -0
  109. package/package.json +62 -0
  110. package/templates/.env.example.ejs +21 -0
  111. package/templates/.husky/commit-msg +2 -0
  112. package/templates/.husky/pre-commit +2 -0
  113. package/templates/README.md.ejs +169 -0
  114. package/templates/__js__/jsconfig.json +9 -0
  115. package/templates/__ts__/src/vite-env.d.ts +16 -0
  116. package/templates/__ts__/tsconfig.json +24 -0
  117. package/templates/__when_buildTool_esbuild__/scripts/esbuild.build.mjs.ejs +23 -0
  118. package/templates/__when_buildTool_esbuild__/scripts/esbuild.dev.mjs.ejs +48 -0
  119. package/templates/__when_buildTool_parcel__/.parcelrc +9 -0
  120. package/templates/__when_buildTool_rollup__/rollup.config.js.ejs +33 -0
  121. package/templates/__when_buildTool_rspack__/rspack.config.js.ejs +36 -0
  122. package/templates/__when_buildTool_vite__/vite.config.ts.ejs +37 -0
  123. package/templates/__when_buildTool_webpack__/webpack.config.js.ejs +68 -0
  124. package/templates/__when_e2eTesting_cypress__/cypress/e2e/home.cy.ts.ejs +6 -0
  125. package/templates/__when_e2eTesting_cypress__/cypress.config.ts.ejs +8 -0
  126. package/templates/__when_e2eTesting_playwright__/playwright.config.ts.ejs +16 -0
  127. package/templates/__when_e2eTesting_playwright__/tests/e2e/home.spec.ts.ejs +6 -0
  128. package/templates/__when_formatting_prettier__/.prettierrc +7 -0
  129. package/templates/__when_formatting_stylelint__/.stylelintrc.json +3 -0
  130. package/templates/__when_linting_biome__/biome.json +19 -0
  131. package/templates/__when_linting_eslint__/eslint.config.js.ejs +42 -0
  132. package/templates/__when_serverState_rtk-query__/src/store/postsApi.ts.ejs +19 -0
  133. package/templates/__when_stateManagement_context__/src/store/context.tsx.ejs +57 -0
  134. package/templates/__when_styling_tailwind__/postcss.config.js +6 -0
  135. package/templates/__when_styling_tailwind__/tailwind.config.js.ejs +23 -0
  136. package/templates/__when_unitTesting_jest__/jest.config.json.ejs +11 -0
  137. package/templates/__when_unitTesting_jest__/tests/App.test.tsx.ejs +13 -0
  138. package/templates/__when_unitTesting_jest__/tests/setup.ts.ejs +1 -0
  139. package/templates/__when_unitTesting_jest__/tests/styleMock.ts.ejs +1 -0
  140. package/templates/__when_unitTesting_rtl__/tests/App.test.tsx.ejs +13 -0
  141. package/templates/__when_unitTesting_vitest__/tests/App.test.tsx.ejs +16 -0
  142. package/templates/__when_unitTesting_vitest__/tests/setup.ts.ejs +1 -0
  143. package/templates/__when_visualTesting_storybook__/.storybook/main.js.ejs +11 -0
  144. package/templates/__when_visualTesting_storybook__/.storybook/preview.js +8 -0
  145. package/templates/__when_visualTesting_storybook__/src/components/ui/UiButton.stories.tsx.ejs +15 -0
  146. package/templates/commitlint.config.js +3 -0
  147. package/templates/docs/architecture.md.ejs +74 -0
  148. package/templates/docs/best-practices.md.ejs +56 -0
  149. package/templates/docs/examples/README.md.ejs +14 -0
  150. package/templates/docs/examples/api.md.ejs +17 -0
  151. package/templates/docs/examples/data-fetching.md.ejs +18 -0
  152. package/templates/docs/examples/forms.md.ejs +18 -0
  153. package/templates/docs/examples/state.md.ejs +17 -0
  154. package/templates/docs/examples/styling.md.ejs +23 -0
  155. package/templates/docs/examples/testing.md.ejs +27 -0
  156. package/templates/docs/getting-started.md.ejs +55 -0
  157. package/templates/docs/selected-stack.md.ejs +55 -0
  158. package/templates/index.html.ejs +19 -0
  159. package/templates/public/vite.svg +4 -0
  160. package/templates/src/app/App.tsx.ejs +71 -0
  161. package/templates/src/app/providers.tsx.ejs +93 -0
  162. package/templates/src/assets/.gitkeep +0 -0
  163. package/templates/src/components/StackBadge.tsx.ejs +15 -0
  164. package/templates/src/components/layout/AppLayout.tsx.ejs +64 -0
  165. package/templates/src/components/ui/Toast.tsx.ejs +61 -0
  166. package/templates/src/components/ui/UiButton.tsx.ejs +168 -0
  167. package/templates/src/config/env.ts.ejs +18 -0
  168. package/templates/src/features/counter/CounterPanel.tsx.ejs +66 -0
  169. package/templates/src/features/feedback/FeedbackForm.tsx.ejs +373 -0
  170. package/templates/src/features/posts/PostsPanel.tsx.ejs +91 -0
  171. package/templates/src/hooks/useMounted.ts.ejs +15 -0
  172. package/templates/src/lib/cn.ts.ejs +12 -0
  173. package/templates/src/lib/monitoring.ts.ejs +66 -0
  174. package/templates/src/lib/validation.ts.ejs +81 -0
  175. package/templates/src/main.tsx.ejs +22 -0
  176. package/templates/src/routes/AboutPage.tsx.ejs +30 -0
  177. package/templates/src/routes/HomePage.tsx.ejs +47 -0
  178. package/templates/src/services/api.ts.ejs +84 -0
  179. package/templates/src/store/index.ts.ejs +80 -0
  180. package/templates/src/styles/global.css.ejs +457 -0
  181. package/templates/src/types/index.ts.ejs +7 -0
  182. package/templates/src/utils/format.ts.ejs +3 -0
@@ -0,0 +1,42 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import react from 'eslint-plugin-react';
4
+ import reactHooks from 'eslint-plugin-react-hooks';
5
+ <% if (isTypeScript) { -%>
6
+ import tseslint from 'typescript-eslint';
7
+ <% } -%>
8
+ <% if (formatting === 'prettier') { -%>
9
+ import prettier from 'eslint-config-prettier';
10
+ <% } -%>
11
+
12
+ export default [
13
+ { ignores: ['dist', 'coverage', 'storybook-static'] },
14
+ js.configs.recommended,
15
+ <% if (isTypeScript) { -%>
16
+ ...tseslint.configs.recommended,
17
+ <% } -%>
18
+ {
19
+ files: ['**/*.{<%= isTypeScript ? 'ts,tsx' : 'js,jsx' %>}'],
20
+ languageOptions: {
21
+ ecmaVersion: 2022,
22
+ sourceType: 'module',
23
+ globals: globals.browser,
24
+ },
25
+ plugins: {
26
+ react,
27
+ 'react-hooks': reactHooks,
28
+ },
29
+ settings: {
30
+ react: { version: 'detect' },
31
+ },
32
+ rules: {
33
+ ...react.configs.recommended.rules,
34
+ ...reactHooks.configs.recommended.rules,
35
+ 'react/react-in-jsx-scope': 'off',
36
+ 'react/prop-types': 'off',
37
+ },
38
+ },
39
+ <% if (formatting === 'prettier') { -%>
40
+ prettier,
41
+ <% } -%>
42
+ ];
@@ -0,0 +1,19 @@
1
+ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
2
+ <% if (isTypeScript) { -%>
3
+ import type { Post } from '@/services/api';
4
+ <% } -%>
5
+ import { env } from '@/config/env';
6
+
7
+ const baseUrl = env.apiBaseUrl;
8
+
9
+ export const postsApi = createApi({
10
+ reducerPath: 'postsApi',
11
+ baseQuery: fetchBaseQuery({ baseUrl }),
12
+ endpoints: (builder) => ({
13
+ getPosts: builder.query<% if (isTypeScript) { %><Post[], void><% } %>({
14
+ query: () => '/posts?_limit=5',
15
+ }),
16
+ }),
17
+ });
18
+
19
+ export const { useGetPostsQuery } = postsApi;
@@ -0,0 +1,57 @@
1
+ import {
2
+ createContext,
3
+ useContext,
4
+ useMemo,
5
+ useReducer,
6
+ <% if (isTypeScript) { -%>
7
+ type ReactNode,
8
+ type Dispatch,
9
+ <% } -%>
10
+ } from 'react';
11
+
12
+ <% if (isTypeScript) { -%>
13
+ interface State {
14
+ value: number;
15
+ }
16
+
17
+ type Action =
18
+ | { type: 'increment' }
19
+ | { type: 'decrement' }
20
+ | { type: 'set'; payload: number };
21
+
22
+ interface AppStateContextValue {
23
+ state: State;
24
+ dispatch: Dispatch<Action>;
25
+ }
26
+ <% } -%>
27
+
28
+ const initialState<% if (isTypeScript) { %>: State<% } %> = { value: 0 };
29
+
30
+ function reducer(state<% if (isTypeScript) { %>: State<% } %>, action<% if (isTypeScript) { %>: Action<% } %>)<% if (isTypeScript) { %>: State<% } %> {
31
+ switch (action.type) {
32
+ case 'increment':
33
+ return { value: state.value + 1 };
34
+ case 'decrement':
35
+ return { value: state.value - 1 };
36
+ case 'set':
37
+ return { value: action.payload };
38
+ default:
39
+ return state;
40
+ }
41
+ }
42
+
43
+ const AppStateContext = createContext<% if (isTypeScript) { %><AppStateContextValue | null><% } %>(null);
44
+
45
+ export function AppStateProvider({ children }<% if (isTypeScript) { %>: { children: ReactNode }<% } %>) {
46
+ const [state, dispatch] = useReducer(reducer, initialState);
47
+ const value = useMemo(() => ({ state, dispatch }), [state]);
48
+ return <AppStateContext.Provider value={value}>{children}</AppStateContext.Provider>;
49
+ }
50
+
51
+ export function useAppState() {
52
+ const ctx = useContext(AppStateContext);
53
+ if (!ctx) {
54
+ throw new Error('useAppState must be used within AppStateProvider');
55
+ }
56
+ return ctx;
57
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -0,0 +1,23 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: ['./index.html', './src/**/*.{<%= isTypeScript ? 'js,ts,jsx,tsx' : 'js,jsx' %>}'],
4
+ theme: {
5
+ extend: {
6
+ colors: {
7
+ brand: {
8
+ 50: '#f0f7ff',
9
+ 100: '#dceeff',
10
+ 500: '#2563eb',
11
+ 600: '#1d4ed8',
12
+ 700: '#1e40af',
13
+ 900: '#0f172a',
14
+ },
15
+ },
16
+ fontFamily: {
17
+ display: ['"DM Sans"', 'system-ui', 'sans-serif'],
18
+ body: ['"IBM Plex Sans"', 'system-ui', 'sans-serif'],
19
+ },
20
+ },
21
+ },
22
+ plugins: [],
23
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ <% if (isTypeScript) { -%>
3
+ "preset": "ts-jest",
4
+ <% } -%>
5
+ "testEnvironment": "jsdom",
6
+ "setupFilesAfterEnv": ["<rootDir>/tests/setup.<%= ext %>"],
7
+ "moduleNameMapper": {
8
+ "^@/(.*)$": "<rootDir>/src/$1",
9
+ "\\\\.(css|scss)$": "<rootDir>/tests/styleMock.<%= ext %>"
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { AppProviders } from '@/app/providers';
3
+ import { HomePage } from '@/routes/HomePage';
4
+
5
+ test('renders the project hero', () => {
6
+ render(
7
+ <AppProviders>
8
+ <HomePage />
9
+ </AppProviders>,
10
+ );
11
+
12
+ expect(screen.getByRole('heading', { name: /<%= projectName %>/i })).toBeInTheDocument();
13
+ });
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1 @@
1
+ export default {};
@@ -0,0 +1,13 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { AppProviders } from '@/app/providers';
3
+ import { HomePage } from '@/routes/HomePage';
4
+
5
+ test('renders the project hero', () => {
6
+ render(
7
+ <AppProviders>
8
+ <HomePage />
9
+ </AppProviders>,
10
+ );
11
+
12
+ expect(screen.getByRole('heading', { name: /<%= projectName %>/i })).toBeInTheDocument();
13
+ });
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { AppProviders } from '@/app/providers';
4
+ import { HomePage } from '@/routes/HomePage';
5
+
6
+ describe('HomePage', () => {
7
+ it('renders the project hero', () => {
8
+ render(
9
+ <AppProviders>
10
+ <HomePage />
11
+ </AppProviders>,
12
+ );
13
+
14
+ expect(screen.getByRole('heading', { name: /<%= projectName %>/i })).toBeInTheDocument();
15
+ });
16
+ });
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,11 @@
1
+ /** @type { import('@storybook/<%= buildTool === 'vite' || buildTool === 'esbuild' ? 'react-vite' : 'react-webpack5' %>').StorybookConfig } */
2
+ const config = {
3
+ stories: ['../src/**/*.stories.@(<%= isTypeScript ? 'ts|tsx' : 'js|jsx' %>)'],
4
+ addons: [],
5
+ framework: {
6
+ name: '@storybook/<%= buildTool === 'vite' || buildTool === 'esbuild' ? 'react-vite' : 'react-webpack5' %>',
7
+ options: {},
8
+ },
9
+ };
10
+
11
+ export default config;
@@ -0,0 +1,8 @@
1
+ /** @type { import('@storybook/react').Preview } */
2
+ const preview = {
3
+ parameters: {
4
+ controls: { matchers: { color: /(background|color)$/i, date: /Date$/i } },
5
+ },
6
+ };
7
+
8
+ export default preview;
@@ -0,0 +1,15 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { UiButton } from '@/components/ui/UiButton';
3
+
4
+ const meta = {
5
+ title: 'UI/UiButton',
6
+ component: UiButton,
7
+ args: {
8
+ children: 'Click me',
9
+ },
10
+ } satisfies Meta<typeof UiButton>;
11
+
12
+ export default meta;
13
+ type Story = StoryObj<typeof meta>;
14
+
15
+ export const Primary: Story = {};
@@ -0,0 +1,3 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ };
@@ -0,0 +1,74 @@
1
+ # Architecture
2
+
3
+ ## Why this stack
4
+
5
+ You selected a coherent default-friendly stack during scaffolding. The generator wires providers, scripts, and a demo page so packages are not orphaned in `package.json`.
6
+
7
+ | Concern | Choice | Role |
8
+ |---------|--------|------|
9
+ | Bundler | <%= stackLabels.buildTool %> | Dev server + production build |
10
+ | Language | <%= stackLabels.language %> | Source language / typing |
11
+ | Routing | <%= stackLabels.router %> | URL → UI mapping |
12
+ | Client state | <%= stackLabels.stateManagement %> | Local interactive state |
13
+ | Server state | <%= stackLabels.serverState %> | Remote data cache |
14
+ | Forms | <%= stackLabels.forms %> | Form state & submit |
15
+ | Validation | <%= stackLabels.validation %> | Schema rules |
16
+ | Styling | <%= stackLabels.styling %> | Visual system |
17
+ | UI kit | <%= stackLabels.uiLibrary %> | Components / primitives |
18
+ | API | <%= stackLabels.apiLayer %> | HTTP transport |
19
+
20
+ ## Folder organization (feature-based)
21
+
22
+ This scaffold uses a **feature-based / domain-driven** layout — the pattern most large React teams settle on as apps grow (similar in spirit to how companies structure product domains: keep code that changes together close together).
23
+
24
+ ```text
25
+ src/
26
+ app/ # bootstrap, providers, root App shell
27
+ assets/ # images, fonts, static media imported from code
28
+ components/ # shared, feature-agnostic UI (layout/, ui/)
29
+ config/ # env helpers and app-level constants
30
+ features/ # domain modules (counter, posts, feedback, …)
31
+ hooks/ # shared hooks
32
+ lib/ # third-party wrappers / cross-cutting helpers
33
+ routes/ # route-level pages
34
+ services/ # API clients / transport
35
+ store/ # global client state (when selected)
36
+ styles/ # global styles / tokens
37
+ types/ # shared TypeScript types
38
+ utils/ # pure helpers
39
+ ```
40
+
41
+ **Rules of thumb**
42
+
43
+ - Put new product work in `src/features/<domain>/`.
44
+ - Keep `components/` dumb and reusable.
45
+ - Import with the `@/` alias (e.g. `import { apiGet } from '@/services/api'`).
46
+ - Prefer a feature's public surface over deep cross-feature imports.
47
+
48
+ ## Path aliases
49
+
50
+ `@/*` maps to `src/*` in TypeScript/JS config and in your bundler (`<%= stackLabels.buildTool %>`).
51
+
52
+ ```ts
53
+ import { HomePage } from '@/routes/HomePage';
54
+ import { useToast } from '@/components/ui/Toast';
55
+ ```
56
+
57
+ ## Runtime composition
58
+
59
+ `src/main.<%= jsxExt %>` → providers (`src/app/providers.<%= jsxExt %>`) → router (`src/app/App.<%= jsxExt %>`) → layouts/pages.
60
+
61
+ Providers are ordered deliberately: state → server cache → UI theme → toasts.
62
+
63
+ ## Boundaries
64
+
65
+ - **UI** must not call `fetch`/`axios` directly in deep leaves — go through `services/`.
66
+ - **Schemas** live in `lib/validation` so forms and API payloads share rules.
67
+ - **Env access** stays in `config/`, `services/`, and `lib/monitoring`.
68
+
69
+ ## Production readiness patterns
70
+
71
+ - Code-split heavy routes when the app grows.
72
+ - Fail closed on missing monitoring DSN (already gated).
73
+ - Keep lint/format/test scripts green in CI.
74
+ - Document public env vars only in `.env.example`.
@@ -0,0 +1,56 @@
1
+ # Best practices
2
+
3
+ ## Code organization
4
+
5
+ - Colocate tests next to units or under `tests/` for cross-cutting suites.
6
+ - Prefer small modules with clear exports over “utils dump” files.
7
+ - Name features after domains (`billing`, `auth`), not technical junk drawers.
8
+
9
+ ## Linting & formatting
10
+
11
+ - Tooling: **<%= stackLabels.linting %>** + **<%= stackLabels.formatting %>**
12
+ - Run lint before push; treat warnings as debt with a burn-down plan.
13
+ - Husky + lint-staged formats staged files so diffs stay clean.
14
+ - commitlint enforces Conventional Commits on `git commit`.
15
+
16
+ ## Environment variables
17
+
18
+ - Never commit `.env`.
19
+ - Prefix client-visible vars for your bundler.
20
+ - Validate required env at boot for production deploys.
21
+
22
+ ## Testing strategy
23
+
24
+ <% if (unitTesting === 'vitest' || unitTesting === 'jest') { -%>
25
+ - Unit/integration with **<%= stackLabels.unitTesting %>** + Testing Library for components.
26
+ <% } else if (unitTesting === 'rtl') { -%>
27
+ - React Testing Library is installed — pair it with a runner of your choice.
28
+ <% } else { -%>
29
+ - Unit testing was skipped; add a runner before your first production release.
30
+ <% } -%>
31
+ <% if (e2eTesting !== 'none') { -%>
32
+ - E2E with **<%= stackLabels.e2eTesting %>** for critical user journeys (load home, submit form).
33
+ <% } -%>
34
+ <% if (visualTesting === 'storybook') { -%>
35
+ - Storybook for isolated UI development and visual review.
36
+ <% } else if (visualTesting === 'chromatic') { -%>
37
+ - Chromatic for visual regression against baselines.
38
+ <% } -%>
39
+
40
+ Aim for: fast unit tests on logic, fewer integration tests on features, thin e2e on happy paths.
41
+
42
+ ## Deployment notes
43
+
44
+ 1. `<%= packageManager === 'npm' ? 'npm run' : packageManager %> build`
45
+ 2. Serve `dist/` (or your bundler's output) behind HTTPS.
46
+ 3. Configure SPA fallback to `index.html` for client routes.
47
+ 4. Inject production env vars in the host (Vercel, Netlify, Cloudflare, nginx, etc.).
48
+ 5. Enable error tracking DSN in production only.
49
+
50
+ ## Production checklist
51
+
52
+ - [ ] Env vars documented and set
53
+ - [ ] Lint + tests in CI
54
+ - [ ] Bundle analyzed for accidental secrets
55
+ - [ ] Monitoring verified with a test event
56
+ - [ ] Accessibility pass on primary flows
@@ -0,0 +1,14 @@
1
+ # Examples index
2
+
3
+ Each file documents a concern wired into this scaffold:
4
+
5
+ | File | Topic |
6
+ |------|-------|
7
+ | `state.md` | Client state patterns |
8
+ | `data-fetching.md` | Server state / caching |
9
+ | `forms.md` | Forms + validation |
10
+ | `styling.md` | Visual system |
11
+ | `api.md` | HTTP layer |
12
+ | `testing.md` | Unit / E2E / visual |
13
+
14
+ Open the home page to see live counterparts of these examples.
@@ -0,0 +1,17 @@
1
+ # API layer example
2
+
3
+ **Choice:** <%= stackLabels.apiLayer %>
4
+
5
+ ## When to use
6
+
7
+ All HTTP traffic should go through a single module for base URL, headers, and error logging.
8
+
9
+ ## Best practice
10
+
11
+ - Type responses at the boundary.
12
+ - Surface user-friendly errors in UI; log technical details to monitoring.
13
+ - Do not scatter `fetch`/`axios` calls across components.
14
+
15
+ ## Snippet
16
+
17
+ `src/services/api.<%= ext %>` — `apiGet`, `apiPost`, `fetchPosts`, `createFeedback`.
@@ -0,0 +1,18 @@
1
+ # Data fetching example
2
+
3
+ **Library:** <%= stackLabels.serverState %>
4
+ **Transport:** <%= stackLabels.apiLayer %>
5
+
6
+ **Live demo:** Posts panel on `/`
7
+
8
+ ## When to use
9
+
10
+ Any remote read/write that benefits from caching, deduplication, retries, or background refresh.
11
+
12
+ ## Best practice
13
+
14
+ Separate server cache from client UI state. Key queries by resource identity, not by component instance.
15
+
16
+ ## Snippet
17
+
18
+ See `src/features/posts/PostsPanel.<%= jsxExt %>` and `src/services/api.<%= ext %>`.
@@ -0,0 +1,18 @@
1
+ # Forms & validation example
2
+
3
+ **Forms:** <%= stackLabels.forms %>
4
+ **Validation:** <%= stackLabels.validation %>
5
+
6
+ **Live demo:** Feedback form on `/`
7
+
8
+ ## When to use
9
+
10
+ Multi-field input with client-side rules and async submit.
11
+
12
+ ## Best practice
13
+
14
+ Define schemas once in `src/lib/validation.<%= ext %>` and reuse across UI and API boundaries.
15
+
16
+ ## Snippet
17
+
18
+ See `src/features/feedback/FeedbackForm.<%= jsxExt %>`.
@@ -0,0 +1,17 @@
1
+ # Client state example
2
+
3
+ **Library:** <%= stackLabels.stateManagement %>
4
+
5
+ **Live demo:** Counter panel on `/`
6
+
7
+ ## When to use
8
+
9
+ Shared interactive state that is not fetched from an API (wizard steps, UI toggles, local counters).
10
+
11
+ ## Best practice
12
+
13
+ Keep stores/slices focused. Prefer feature-local state; promote to global only when multiple distant trees need it.
14
+
15
+ ## Snippet
16
+
17
+ See `src/features/counter/CounterPanel.<%= jsxExt %>` and `src/store/`.
@@ -0,0 +1,23 @@
1
+ # Styling & UI example
2
+
3
+ **Styling:** <%= stackLabels.styling %>
4
+ **UI library:** <%= stackLabels.uiLibrary %>
5
+
6
+ ## When to use
7
+
8
+ Establish design tokens early; use a component library for complex accessible primitives.
9
+
10
+ ## Best practice
11
+
12
+ <% if (uiLibrary === 'shadcn') { -%>
13
+ Treat shadcn-style primitives as owned source — customize freely, keep `cn()` helpers consistent.
14
+ <% } else if (uiLibrary === 'none') { -%>
15
+ Invest in a small set of shared primitives (`UiButton`, layout) before adding a full kit.
16
+ <% } else { -%>
17
+ Wrap third-party components in thin adapters (`UiButton`) so swapping kits later is cheaper.
18
+ <% } -%>
19
+
20
+ ## Snippet
21
+
22
+ Global styles: `src/styles/global.<%= styling === 'sass' && uiLibrary !== 'shadcn' ? 'scss' : 'css' %>`
23
+ Button adapter: `src/components/ui/UiButton.<%= jsxExt %>`
@@ -0,0 +1,27 @@
1
+ # Testing example
2
+
3
+ | Layer | Choice |
4
+ |-------|--------|
5
+ | Unit | <%= stackLabels.unitTesting %> |
6
+ | E2E | <%= stackLabels.e2eTesting %> |
7
+ | Visual | <%= stackLabels.visualTesting %> |
8
+
9
+ ## When to use
10
+
11
+ - Unit: pure logic + component behavior
12
+ - E2E: critical journeys across routes
13
+ - Visual: regressions in UI appearance
14
+
15
+ ## Best practice
16
+
17
+ Keep e2e thin. Prefer Testing Library queries that reflect how users find elements (`getByRole`, labels).
18
+
19
+ ## Locations
20
+
21
+ - Setup: `tests/setup.<%= ext %>` (when applicable)
22
+ - Component smoke: `tests/App.test.<%= jsxExt %>`
23
+ <% if (e2eTesting === 'playwright') { -%>
24
+ - E2E: `tests/e2e/home.spec.<%= ext %>`
25
+ <% } else if (e2eTesting === 'cypress') { -%>
26
+ - E2E: `cypress/e2e/home.cy.<%= ext %>`
27
+ <% } -%>
@@ -0,0 +1,55 @@
1
+ # Getting started
2
+
3
+ Welcome to **<%= projectName %>**, a React starter generated by `create-react-starter-kit`.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 18+
8
+ - <%= stackLabels.packageManager %>
9
+
10
+ ## Install & run
11
+
12
+ ```bash
13
+ <% if (packageManager === 'pnpm') { -%>
14
+ pnpm install
15
+ pnpm dev
16
+ <% } else if (packageManager === 'yarn') { -%>
17
+ yarn
18
+ yarn dev
19
+ <% } else { -%>
20
+ npm install
21
+ npm run dev
22
+ <% } -%>
23
+ ```
24
+
25
+ ## Environment variables
26
+
27
+ Copy `.env.example` → `.env` and fill values. Restart the dev server after changes.
28
+
29
+ Only variables prefixed for your bundler (e.g. `VITE_`) are exposed to the browser. Keep secrets on the server.
30
+
31
+ ## What to explore first
32
+
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.
37
+
38
+ ## Extending the app
39
+
40
+ - Add a domain under `src/features/<name>/`.
41
+ - Register routes in `src/app/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'`.
45
+
46
+ ## Testing
47
+
48
+ <% if (unitTesting !== 'none') { -%>
49
+ - Unit: `<%= packageManager === 'npm' ? 'npm run' : packageManager %> test`
50
+ <% } -%>
51
+ <% if (e2eTesting !== 'none') { -%>
52
+ - E2E: `<%= packageManager === 'npm' ? 'npm run' : packageManager %> test:e2e`
53
+ <% } -%>
54
+
55
+ See `docs/best-practices.md` for CI and production notes.
@@ -0,0 +1,55 @@
1
+ # Selected stack
2
+
3
+ This document explains each choice made when generating **<%= projectName %>**.
4
+
5
+ ## Build — <%= stackLabels.buildTool %>
6
+
7
+ Fast local feedback and a production bundle. Prefer keeping config minimal; add plugins only when needed.
8
+
9
+ **Best practice:** lock Node and package manager versions in CI for reproducible builds.
10
+
11
+ ## Language — <%= stackLabels.language %>
12
+
13
+ <% if (isTypeScript) { -%>
14
+ TypeScript catches contract mistakes early. Keep `strict` on; avoid `any` except at true boundaries.
15
+ <% } else { -%>
16
+ JavaScript keeps the barrier low. Consider migrating hot modules to TypeScript as the app grows.
17
+ <% } -%>
18
+
19
+ ## Routing — <%= stackLabels.router %>
20
+
21
+ Client-side navigation with nested layouts. Keep route modules thin; push data loading into features.
22
+
23
+ ## Client state — <%= stackLabels.stateManagement %>
24
+
25
+ Use for UI state (modals, wizards, ephemeral counters). Do **not** mirror server entities here if you have a server-state library.
26
+
27
+ ## Server state — <%= stackLabels.serverState %>
28
+
29
+ Caches remote data, handles loading/error, and deduplicates requests. Example: posts panel on the home page.
30
+
31
+ ## Forms — <%= stackLabels.forms %> / Validation — <%= stackLabels.validation %>
32
+
33
+ Schemas define the contract; the form library binds inputs. Share schemas with API payloads when possible.
34
+
35
+ ## Styling — <%= stackLabels.styling %> / UI — <%= stackLabels.uiLibrary %>
36
+
37
+ Tokens and primitives establish visual consistency. Prefer composition over one-off CSS.
38
+
39
+ ## API — <%= stackLabels.apiLayer %>
40
+
41
+ Centralize base URL, headers, and error logging in `src/services/api.<%= ext %>`.
42
+
43
+ ## Quality gates
44
+
45
+ | Area | Choice |
46
+ |------|--------|
47
+ | Unit | <%= stackLabels.unitTesting %> |
48
+ | E2E | <%= stackLabels.e2eTesting %> |
49
+ | Visual | <%= stackLabels.visualTesting %> |
50
+ | Lint | <%= stackLabels.linting %> |
51
+ | Format | <%= stackLabels.formatting %> |
52
+ | Git hooks | Husky + lint-staged + commitlint |
53
+ | Structure | Feature-based + `@/` aliases |
54
+
55
+ See `docs/examples/` for focused usage notes.