create-template-project 0.1.0 → 0.2.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 (70) hide show
  1. package/README.md +8 -8
  2. package/dist/cli.mjs +54 -18
  3. package/dist/config/dependencies.json +59 -39
  4. package/dist/generators/info.mjs +58 -0
  5. package/dist/generators/project.mjs +60 -27
  6. package/dist/index.mjs +4 -1
  7. package/dist/templates/base/files/.github/workflows/node.js.yml +5 -3
  8. package/dist/templates/base/files/.prettierignore +50 -0
  9. package/dist/templates/base/files/.prettierrc.json +4 -2
  10. package/dist/templates/base/files/AGENTS.md +5 -2
  11. package/dist/templates/base/files/README.md +36 -13
  12. package/dist/templates/base/files/_oxlint.config.ts +17 -33
  13. package/dist/templates/base/files/tsconfig.json +32 -32
  14. package/dist/templates/base/files/vitest.config.ts +2 -2
  15. package/dist/templates/base/index.mjs +40 -1
  16. package/dist/templates/cli/index.mjs +14 -1
  17. package/dist/templates/web-app/files/index.html +11 -0
  18. package/dist/templates/web-app/files/playwright.config.ts +26 -0
  19. package/dist/templates/web-app/files/src/index.tsx +21 -0
  20. package/dist/templates/web-app/files/tests/e2e/basic.e2e-test.ts +13 -0
  21. package/dist/templates/web-app/files/vite.config.ts +30 -0
  22. package/dist/templates/web-app/index.mjs +69 -0
  23. package/dist/templates/web-fullstack/files/client/index.html +10 -0
  24. package/dist/templates/{fullstack → web-fullstack}/files/client/package.json +2 -2
  25. package/dist/templates/{fullstack → web-fullstack}/files/client/src/contexts/AuthContext.tsx +1 -5
  26. package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Login.tsx +4 -33
  27. package/dist/templates/web-fullstack/files/client/vite.config.ts +26 -0
  28. package/dist/templates/web-fullstack/files/playwright.config.ts +33 -0
  29. package/dist/templates/{fullstack → web-fullstack}/files/server/package.json +2 -2
  30. package/dist/templates/web-fullstack/files/server/vite.config.ts +21 -0
  31. package/dist/templates/web-fullstack/files/tests/e2e/basic.e2e-test.ts +14 -0
  32. package/dist/templates/web-fullstack/index.mjs +78 -0
  33. package/dist/templates/web-vanilla/files/index.html +11 -0
  34. package/dist/templates/web-vanilla/files/package.json +17 -0
  35. package/dist/templates/web-vanilla/files/playwright.config.ts +26 -0
  36. package/dist/templates/web-vanilla/files/tests/e2e/basic.e2e-test.ts +11 -0
  37. package/dist/templates/web-vanilla/files/vite.config.ts +24 -0
  38. package/dist/templates/web-vanilla/index.mjs +45 -0
  39. package/dist/types.mjs +4 -4
  40. package/dist/utils/file.mjs +31 -13
  41. package/package.json +24 -21
  42. package/dist/templates/fullstack/files/client/index.html +0 -8
  43. package/dist/templates/fullstack/files/client/tsdown.config.ts +0 -3
  44. package/dist/templates/fullstack/files/server/tsdown.config.ts +0 -3
  45. package/dist/templates/fullstack/index.mjs +0 -42
  46. package/dist/templates/webapp/files/backend/src/index.ts +0 -17
  47. package/dist/templates/webapp/files/frontend/index.html +0 -9
  48. package/dist/templates/webapp/files/frontend/src/index.ts +0 -4
  49. package/dist/templates/webapp/files/package.json +0 -13
  50. package/dist/templates/webapp/files/tsdown.config.ts +0 -10
  51. package/dist/templates/webapp/index.mjs +0 -16
  52. package/dist/templates/webpage/files/index.html +0 -8
  53. package/dist/templates/webpage/files/package.json +0 -8
  54. package/dist/templates/webpage/index.mjs +0 -16
  55. /package/dist/templates/{webapp → web-app}/files/src/index.test.ts +0 -0
  56. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/App.test.tsx +0 -0
  57. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/App.tsx +0 -0
  58. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/components/ProtectedRoute.tsx +0 -0
  59. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/main.tsx +0 -0
  60. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Dashboard.tsx +0 -0
  61. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/trpc.ts +0 -0
  62. /package/dist/templates/{fullstack → web-fullstack}/files/package.json +0 -0
  63. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/context.ts +0 -0
  64. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/index.test.ts +0 -0
  65. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/index.ts +0 -0
  66. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/_app.ts +0 -0
  67. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/auth.ts +0 -0
  68. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/trpc.ts +0 -0
  69. /package/dist/templates/{webpage → web-vanilla}/files/src/index.test.ts +0 -0
  70. /package/dist/templates/{webpage → web-vanilla}/files/src/index.ts +0 -0
package/dist/index.mjs CHANGED
@@ -4,7 +4,10 @@ import { generateProject } from "./generators/project.mjs";
4
4
  import { cancel, intro, outro } from "@clack/prompts";
5
5
  import debugLib from "debug";
6
6
  //#region src/index.ts
7
- if (process.argv.includes("--debug")) debugLib.enable("*");
7
+ if (process.argv.includes("--debug")) {
8
+ process.env["DEBUG"] = "create-template-project:*";
9
+ debugLib.enable("create-template-project:*");
10
+ }
8
11
  const debug = debugLib("create-template-project:main");
9
12
  const main = async () => {
10
13
  try {
@@ -11,10 +11,12 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - uses: actions/checkout@v4
14
+ # [PM_SETUP]
14
15
  - name: Use Node.js
15
16
  uses: actions/setup-node@v4
16
17
  with:
17
18
  node-version: '22.x'
18
- cache: 'npm'
19
- - run: npm ci
20
- - run: npm run ci
19
+ cache: '{{packageManager}}'
20
+ - run: '{{installCommand}}'
21
+ # [PLAYWRIGHT_SETUP]
22
+ - run: '{{packageManager}} run ci'
@@ -0,0 +1,50 @@
1
+ # dependencies
2
+ node_modules/
3
+
4
+ # build outputs
5
+ dist/
6
+ build/
7
+ coverage/
8
+ out/
9
+ .next/
10
+ .nuxt/
11
+ .svelte-kit/
12
+
13
+ # logs
14
+ *.log
15
+ npm-debug.log*
16
+ yarn-debug.log*
17
+ yarn-error.log*
18
+ pnpm-debug.log*
19
+
20
+ # env
21
+ .env
22
+ .env.*.local
23
+
24
+ # cache
25
+ .cache/
26
+ .parcel-cache/
27
+ .eslintcache
28
+
29
+ # lock files (optional, usually formatted fine)
30
+ package-lock.json
31
+ yarn.lock
32
+ pnpm-lock.yaml
33
+
34
+ # generated files
35
+ *.min.js
36
+ *.min.css
37
+
38
+ # static assets (optional)
39
+ public/
40
+ assets/
41
+
42
+ # IDE / OS
43
+ .vscode/
44
+ .idea/
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # misc
49
+ tmp/
50
+ temp/
@@ -1,6 +1,8 @@
1
1
  {
2
+ "printWidth": 160,
3
+ "embeddedLanguageFormatting": "off",
2
4
  "useTabs": true,
3
5
  "singleQuote": true,
4
- "trailingComma": "all",
5
- "printWidth": 100
6
+ "bracketSpacing": false,
7
+ "endOfLine": "auto"
6
8
  }
@@ -1,5 +1,8 @@
1
1
  # Agent Guidelines: {{projectName}}
2
2
 
3
3
  Build/Lint/Test:
4
- - `npm run ci`
5
- - `npx vitest <file>`
4
+ - `npm run ci`: Runs lint, build, and all tests.
5
+ - `npm run dev`: Starts the development server.
6
+ - `npm run test`: Runs unit tests (browser-based for web projects).
7
+ - `npm run test:e2e`: Runs Playwright E2E tests.
8
+ - `npx vitest <file>`: Runs a specific test file.
@@ -3,21 +3,44 @@
3
3
  {{description}}
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/{{projectName}}.svg)](https://www.npmjs.com/package/{{projectName}})
6
- [![NPM Downloads](https://img.shields.io/npm/dm/{{projectName}}.svg)](https://www.npmjs.com/package/{{projectName}})
7
6
  [![Node.js CI](https://github.com/doberkofler/{{projectName}}/actions/workflows/node.js.yml/badge.svg)](https://github.com/doberkofler/{{projectName}}/actions/workflows/node.js.yml)
8
7
 
9
- ## Generated with create-template-project.
8
+ ## Development Workflow
10
9
 
11
- ## Templates
12
- - **cli**: Node.js CLI application.
13
- - **webpage**: Standalone web page.
14
- - **webapp**: Web application with Express.
15
- - **fullstack**: Monorepo with Express and React.
10
+ This project is built using **Vite 8** for high-performance development and bundling.
11
+
12
+ ### Available Scripts
13
+
14
+ - `npm run dev`: Starts the development server.
15
+ - `npm run build`: Builds the project for production.
16
+ - `npm run preview`: Previews the production build.
17
+ - `npm run test`: Runs the unit test suite (browser-based for web targets using **Vitest** and **Playwright**).
18
+ - `npm run test:e2e`: Runs E2E tests using **Playwright**.
19
+ - `npm run lint`: Lints and formats the codebase using **oxlint** and **prettier**.
20
+ - `npm run ci`: Full CI pipeline (lint, build, test).
16
21
 
17
22
  ## Getting Started
18
- ```bash
19
- npm install
20
- npm run dev # if applicable
21
- npm run build
22
- npm run test
23
- ```
23
+
24
+ 1. **Install dependencies**:
25
+ ```bash
26
+ npm install
27
+ ```
28
+ 2. **Start development server**:
29
+ ```bash
30
+ npm run dev
31
+ ```
32
+ 3. **Run tests**:
33
+ ```bash
34
+ npm run test
35
+ npm run test:e2e
36
+ ```
37
+
38
+ ## Tooling
39
+
40
+ - **Vite 8**: Modern, ultra-fast development and build tool.
41
+ - **Vitest**: Vite-native testing framework with browser support.
42
+ - **Playwright**: Reliable E2E and browser automation.
43
+ - **oxlint**: Extremely fast JavaScript/TypeScript linter.
44
+ - **Prettier**: Opinionated code formatter.
45
+ - **Husky & Commitlint**: Ensuring high-quality commit messages.
46
+ - **Conventional Changelog**: Automated changelog generation.
@@ -1,50 +1,40 @@
1
- import { defineConfig } from 'oxlint';
1
+ import {defineConfig} from 'oxlint';
2
2
  import pluginRegexp from 'eslint-plugin-regexp';
3
3
 
4
4
  export default defineConfig({
5
5
  options: {
6
6
  typeAware: true,
7
- typeCheck: true
7
+ typeCheck: true,
8
8
  },
9
- plugins: [
10
- 'unicorn',
11
- 'typescript',
12
- 'oxc',
13
- 'import',
14
- 'react',
15
- 'jsdoc',
16
- 'promise',
17
- 'vitest'
18
- ],
19
- jsPlugins: [
20
- 'eslint-plugin-regexp'
21
- ],
9
+ plugins: ['unicorn', 'typescript', 'oxc', 'import', 'react', 'jsdoc', 'promise', 'vitest'],
10
+ jsPlugins: ['eslint-plugin-regexp'],
22
11
  categories: {
23
- correctness: 'error'
12
+ correctness: 'error',
24
13
  },
25
14
  rules: {
26
15
  ...pluginRegexp.configs.recommended.rules,
16
+ curly: ['error', 'all'],
27
17
  'typescript/no-unused-vars': [
28
18
  'error',
29
19
  {
30
20
  caughtErrors: 'none',
31
- argsIgnorePattern: '^_'
32
- }
33
- ]
21
+ argsIgnorePattern: '^_',
22
+ },
23
+ ],
34
24
  },
35
25
  settings: {
36
26
  'jsx-a11y': {
37
27
  polymorphicPropName: undefined,
38
28
  components: {},
39
- attributes: {}
29
+ attributes: {},
40
30
  },
41
31
  next: {
42
- rootDir: []
32
+ rootDir: [],
43
33
  },
44
34
  react: {
45
35
  formComponents: [],
46
36
  linkComponents: [],
47
- version: undefined
37
+ version: undefined,
48
38
  },
49
39
  jsdoc: {
50
40
  ignorePrivate: false,
@@ -54,21 +44,15 @@ export default defineConfig({
54
44
  augmentsExtendsReplacesDocs: false,
55
45
  implementsReplacesDocs: false,
56
46
  exemptDestructuredRootsFromChecks: false,
57
- tagNamePreference: {}
47
+ tagNamePreference: {},
58
48
  },
59
49
  vitest: {
60
- typecheck: false
61
- }
50
+ typecheck: false,
51
+ },
62
52
  },
63
53
  env: {
64
- builtin: true
54
+ builtin: true,
65
55
  },
66
56
  globals: {},
67
- ignorePatterns: [
68
- '**/.*',
69
- 'node_modules/**',
70
- 'dist/**',
71
- 'coverage/**',
72
- 'public/**'
73
- ]
57
+ ignorePatterns: ['**/.*', 'node_modules/**', 'dist/**', 'coverage/**', 'public/**'],
74
58
  });
@@ -1,42 +1,42 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  /* Language and Environment */
4
- "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
5
- "lib": ["ESNext"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
6
- "module": "NodeNext", /* Specify what module code is generated. */
7
- "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */
8
- "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */
9
- "resolveJsonModule": true, /* Enable importing .json files. */
4
+ "target": "ES2023" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
5
+ "lib": ["ES2023"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
6
+ "module": "ESNext" /* Specify what module code is generated. */,
7
+ "moduleResolution": "bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
8
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. */,
9
+ "resolveJsonModule": true /* Enable importing .json files. */,
10
+ "allowImportingTsExtensions": /* Allow imports to include TypeScript file extensions. */ true,
11
+ "noEmit": true /* Disable emitting files from a compilation. */,
10
12
 
11
13
  /* Strict Type-Checking Options */
12
- "strict": true, /* Enable all strict type-checking options. */
13
- "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
14
- "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
15
- "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
16
- "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
17
- "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
18
- "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
19
- "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
20
- "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
21
- "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
22
- "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
23
- "exactOptionalPropertyTypes": true, /* Interpret optional property types as strictly typed, preventing assignment of 'undefined'. */
24
- "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
25
- "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
26
- "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
27
- "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
28
- "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
29
- "allowUnusedLabels": false, /* Disable error reporting for unused labels. */
30
- "allowUnreachableCode": false, /* Disable error reporting for unreachable code. */
14
+ "strict": true /* Enable all strict type-checking options. */,
15
+ "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
16
+ "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */,
17
+ "strictFunctionTypes": true /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */,
18
+ "strictBindCallApply": true /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */,
19
+ "strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */,
20
+ "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */,
21
+ "useUnknownInCatchVariables": true /* Default catch clause variables as 'unknown' instead of 'any'. */,
22
+ "alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
23
+ "noUnusedLocals": true /* Enable error reporting when local variables aren't read. */,
24
+ "noUnusedParameters": true /* Raise an error when a function parameter isn't read. */,
25
+ "exactOptionalPropertyTypes": true /* Interpret optional property types as strictly typed, preventing assignment of 'undefined'. */,
26
+ "noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */,
27
+ "noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */,
28
+ "noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */,
29
+ "noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */,
30
+ "noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type. */,
31
+ "allowUnusedLabels": false /* Disable error reporting for unused labels. */,
32
+ "allowUnreachableCode": false /* Disable error reporting for unreachable code. */,
31
33
 
32
34
  /* Emit */
33
- "outDir": "./dist", /* Specify an output folder for all emitted files. */
34
-
35
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
36
+
35
37
  /* Completeness */
36
- "skipLibCheck": true, /* Skip type checking all .d.ts files. */
37
- "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
38
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */,
39
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
38
40
  },
39
- "include": [
40
- "src/**/*"
41
- ]
41
+ "include": ["src/**/*"]
42
42
  }
@@ -1,3 +1,3 @@
1
- import { defineConfig } from 'vitest/config';
1
+ import {defineConfig} from 'vitest/config';
2
2
 
3
- export default defineConfig({ test: { coverage: { provider: 'v8' } } });
3
+ export default defineConfig({test: {coverage: {provider: 'v8'}}});
@@ -5,7 +5,46 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
5
  const getBaseTemplate = (_opts) => {
6
6
  return {
7
7
  name: "base",
8
- dependencies: {},
8
+ description: "The foundation for all project templates, including common tooling and configuration.",
9
+ components: [
10
+ {
11
+ name: "TypeScript",
12
+ description: "Mandatory strict mode for type safety."
13
+ },
14
+ {
15
+ name: "oxlint",
16
+ description: "Ultra-fast Rust-based linter."
17
+ },
18
+ {
19
+ name: "Prettier",
20
+ description: "Consistent code formatting."
21
+ },
22
+ {
23
+ name: "Vitest",
24
+ description: "Modern, fast unit testing with coverage."
25
+ },
26
+ {
27
+ name: "Husky",
28
+ description: "Git hooks for pre-commit linting."
29
+ },
30
+ {
31
+ name: "commitlint",
32
+ description: "Standardized commit messages."
33
+ },
34
+ {
35
+ name: "conventional-changelog",
36
+ description: "Automated release notes."
37
+ },
38
+ {
39
+ name: "debug",
40
+ description: "Structured logging for debugging."
41
+ },
42
+ {
43
+ name: "Zod",
44
+ description: "TypeScript-first schema validation for runtime type safety."
45
+ }
46
+ ],
47
+ dependencies: { zod: "zod" },
9
48
  devDependencies: { "eslint-plugin-regexp": "" },
10
49
  scripts: {},
11
50
  files: [],
@@ -2,9 +2,22 @@ import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  //#region src/templates/cli/index.ts
4
4
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const getCliTemplate = (_opts) => {
5
+ const getCliTemplate = (opts) => {
6
+ const components = [{
7
+ name: "commander",
8
+ description: "The complete solution for Node.js command-line interfaces."
9
+ }, {
10
+ name: "cli-progress",
11
+ description: "Easy to use progress-bar for terminal applications."
12
+ }];
13
+ if (!opts.skipBuild) components.push({
14
+ name: "tsdown",
15
+ description: "A zero-config bundler for TypeScript."
16
+ });
6
17
  return {
7
18
  name: "cli",
19
+ description: "A robust Node.js command-line application template.",
20
+ components,
8
21
  dependencies: {},
9
22
  devDependencies: {},
10
23
  scripts: {},
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>{{projectName}}</title>
5
+ </head>
6
+ <body>
7
+ <h1>{{projectName}}</h1>
8
+ <div id="app"></div>
9
+ <script type="module" src="/src/index.tsx"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,26 @@
1
+ import {defineConfig, devices} from '@playwright/test';
2
+
3
+ export default defineConfig({
4
+ testDir: './tests/e2e',
5
+ testMatch: '**/*.e2e-test.ts',
6
+ fullyParallel: true,
7
+ forbidOnly: !!process.env.CI,
8
+ retries: process.env.CI ? 2 : 0,
9
+ workers: process.env.CI ? 1 : undefined,
10
+ reporter: 'html',
11
+ use: {
12
+ baseURL: 'http://localhost:3000',
13
+ trace: 'on-first-retry',
14
+ },
15
+ projects: [
16
+ {
17
+ name: 'chromium',
18
+ use: {...devices['Desktop Chrome']},
19
+ },
20
+ ],
21
+ webServer: {
22
+ command: 'npm run build && npm run start',
23
+ url: 'http://localhost:3000',
24
+ reuseExistingServer: !process.env.CI,
25
+ },
26
+ });
@@ -0,0 +1,21 @@
1
+ import {createRoot} from 'react-dom/client';
2
+ import {Typography, Container, Box} from '@mui/material';
3
+
4
+ const App = () => {
5
+ return (
6
+ <Container maxWidth="sm">
7
+ <Box sx={{my: 4, textAlign: 'center'}}>
8
+ <Typography variant="h4" component="h1" gutterBottom>
9
+ Hello from React!
10
+ </Typography>
11
+ <Typography variant="body1">This project was scaffolded with the web-app template.</Typography>
12
+ </Box>
13
+ </Container>
14
+ );
15
+ };
16
+
17
+ const container = document.getElementById('app');
18
+ if (container) {
19
+ const root = createRoot(container);
20
+ root.render(<App />);
21
+ }
@@ -0,0 +1,13 @@
1
+ import {test, expect} from '@playwright/test';
2
+
3
+ test('has title', async ({page}) => {
4
+ await page.goto('/');
5
+ await expect(page).toHaveTitle(/{{projectName}}/);
6
+ });
7
+
8
+ test('api is reachable', async ({page}) => {
9
+ const response = await page.request.get('/api/hello');
10
+ expect(response.ok()).toBeTruthy();
11
+ const data = await response.json();
12
+ expect(data.message).toBe('Hello from Express!');
13
+ });
@@ -0,0 +1,30 @@
1
+ import path from 'node:path';
2
+ import {defineConfig} from 'vitest/config';
3
+ import react from '@vitejs/plugin-react';
4
+ import {playwright} from '@vitest/browser-playwright';
5
+
6
+ export default defineConfig({
7
+ plugins: [react()],
8
+ build: {
9
+ outDir: 'dist',
10
+ emptyOutDir: true,
11
+ },
12
+ test: {
13
+ include: ['src/**/*.test.{ts,tsx}'],
14
+ browser: {
15
+ enabled: true,
16
+ headless: true,
17
+ screenshotDirectory: path.resolve('./temp/vitest/__screenshots__'),
18
+ instances: [
19
+ {
20
+ browser: 'chromium',
21
+ provider: playwright({
22
+ launchOptions: {
23
+ args: ['--disable-web-security'],
24
+ },
25
+ }),
26
+ },
27
+ ],
28
+ },
29
+ },
30
+ });
@@ -0,0 +1,69 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ //#region src/templates/web-app/index.ts
4
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
+ const getWebAppTemplate = (_opts) => {
6
+ return {
7
+ name: "web-app",
8
+ description: "A React application with MUI and TanStack Query, powered by Vite.",
9
+ components: [
10
+ {
11
+ name: "React",
12
+ description: "Powerful library for building component-based user interfaces."
13
+ },
14
+ {
15
+ name: "MUI",
16
+ description: "Rich set of Material Design UI components for React."
17
+ },
18
+ {
19
+ name: "TanStack React Query",
20
+ description: "Powerful asynchronous state management for React."
21
+ },
22
+ {
23
+ name: "Vite",
24
+ description: "Next-generation frontend tooling."
25
+ },
26
+ {
27
+ name: "Vitest",
28
+ description: "Testing framework with cross-browser support."
29
+ },
30
+ {
31
+ name: "Playwright",
32
+ description: "End-to-end testing for modern web apps."
33
+ }
34
+ ],
35
+ dependencies: {
36
+ react: "react",
37
+ "react-dom": "react-dom",
38
+ "@mui/material": "@mui/material",
39
+ "@mui/icons-material": "@mui/icons-material",
40
+ "@emotion/react": "@emotion/react",
41
+ "@emotion/styled": "@emotion/styled",
42
+ "@tanstack/react-query": "@tanstack/react-query"
43
+ },
44
+ devDependencies: {
45
+ "@types/react": "@types/react",
46
+ "@types/react-dom": "@types/react-dom",
47
+ vite: "vite",
48
+ "@vitejs/plugin-react": "@vitejs/plugin-react",
49
+ vitest: "vitest",
50
+ "@vitest/browser": "@vitest/browser",
51
+ "@vitest/browser-playwright": "@vitest/browser-playwright",
52
+ playwright: "playwright",
53
+ "@playwright/test": "@playwright/test"
54
+ },
55
+ scripts: {
56
+ dev: "vite",
57
+ build: "vite build",
58
+ preview: "vite preview",
59
+ test: "vitest run",
60
+ "test:ui": "vitest",
61
+ "test:e2e": "playwright test",
62
+ start: "vite preview"
63
+ },
64
+ files: [],
65
+ templateDir: path.resolve(__dirname, "files")
66
+ };
67
+ };
68
+ //#endregion
69
+ export { getWebAppTemplate };
@@ -0,0 +1,10 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>{{projectName}}</title>
5
+ </head>
6
+ <body>
7
+ <div id="root"></div>
8
+ <script type="module" src="/src/main.tsx"></script>
9
+ </body>
10
+ </html>
@@ -3,8 +3,8 @@
3
3
  "version": "0.1.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "build": "tsdown",
7
- "dev": "tsdown --watch",
6
+ "build": "vite build",
7
+ "dev": "vite",
8
8
  "test": "vitest run"
9
9
  }
10
10
  }
@@ -47,11 +47,7 @@ export const AuthProvider = ({children}: {children: ReactNode}) => {
47
47
  setUser(null);
48
48
  };
49
49
 
50
- return (
51
- <AuthContext.Provider value={{user, token, isLoading, login, logout}}>
52
- {children}
53
- </AuthContext.Provider>
54
- );
50
+ return <AuthContext.Provider value={{user, token, isLoading, login, logout}}>{children}</AuthContext.Provider>;
55
51
  };
56
52
 
57
53
  export const useAuth = () => {