From 10220ca00080432f1da7778b6658531d73c5ed60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Ba=CC=88chler?= Date: Tue, 26 May 2026 10:53:49 +0200 Subject: [PATCH] feat: Reduce the files in the example --- CONTRIBUTING.md | 16 +- create/main.js | 110 ++++-- .../.cursor/rules/accessibility.mdc | 24 -- .../react-router/.cursor/rules/react.mdc | 18 - .../react-router/.cursor/rules/tests.mdc | 11 - example-templates/react-router/.env.example | 2 - example-templates/react-router/.gitignore | 47 --- example-templates/react-router/.gitlab-ci.yml | 188 ---------- .../react-router/.licenses/isc.md | 17 - .../react-router/.lintstagedrc.js | 3 - example-templates/react-router/.nvmrc | 1 - example-templates/react-router/.prettierrc.js | 30 -- .../react-router/.vscode/settings.json | 3 - example-templates/react-router/LICENSE.md | 18 - .../react-router/api/commons/enums.ts | 12 - .../react-router/api/commons/types.ts | 42 --- .../react-router/api/eslint.config.js | 15 - .../react-router/api/package.json | 38 +- .../react-router/api/tsconfig.json | 12 - .../react-router/config/eslint/README.md | 3 - .../react-router/config/eslint/base.js | 61 --- .../react-router/config/eslint/package.json | 25 -- .../react-router/config/eslint/react.js | 42 --- .../react-router/config/typescript/base.json | 23 -- .../config/typescript/node-library.json | 12 - .../config/typescript/package.json | 9 - .../config/typescript/react-app.json | 13 - .../config/typescript/react-library.json | 10 - .../react-router/docs/antora-playbook.yml | 22 -- .../react-router/docs/antora.yml | 5 - .../ROOT/images/Prototyp-Repo.drawio.png | Bin 24086 -> 0 bytes .../react-router/docs/modules/ROOT/nav.adoc | 11 - .../docs/modules/ROOT/pages/architecture.adoc | 145 -------- .../modules/ROOT/pages/design-system.adoc | 57 --- .../modules/ROOT/pages/documentation.adoc | 93 ----- .../modules/ROOT/pages/getting-started.adoc | 139 ------- .../docs/modules/ROOT/pages/index.adoc | 78 ---- .../docs/modules/ROOT/pages/login.adoc | 62 ---- .../docs/modules/ROOT/pages/mock-data.adoc | 46 --- .../docs/modules/ROOT/pages/monorepo.adoc | 64 ---- .../docs/modules/ROOT/pages/prototype.adoc | 105 ------ .../docs/modules/ROOT/pages/tailwind.adoc | 22 -- .../docs/modules/ROOT/partials/monorepo.puml | 42 --- .../react-router/docs/package.json | 22 -- .../react-router/frontend/package.json | 12 - .../react-router/mocks/AGENTS.md | 128 ------- .../react-router/mocks/eslint.config.js | 12 - .../react-router/mocks/package.json | 63 ---- .../react-router/mocks/src/static/README.md | 1 - .../react-router/mocks/tsconfig.json | 12 - .../react-router/mocks/vite.config.ts | 8 - example-templates/react-router/msw/AGENTS.md | 167 --------- .../react-router/msw/eslint.config.js | 12 - .../react-router/msw/package.json | 61 --- .../react-router/msw/src/utils.ts | 39 -- .../react-router/msw/tsconfig.json | 12 - example-templates/react-router/package.json | 53 --- .../react-router/prototype/.cursorrules.md | 18 - .../prototype/app/entry.client.tsx | 17 - .../prototype/app/hooks/useBreakpoint.ts | 36 -- .../react-router/prototype/app/lib/utils.ts | 35 -- .../prototype/app/mocks/browser.ts | 9 - .../prototype/app/styles/tailwind.css | 70 ---- .../react-router/prototype/app/vite-env.d.ts | 11 - .../react-router/prototype/components.json | 21 -- .../react-router/prototype/eslint.config.mjs | 38 -- .../react-router/prototype/package.json | 58 --- .../react-router/prototype/postcss.config.js | 6 - .../react-router/prototype/public/favicon.ico | Bin 16958 -> 0 bytes .../prototype/public/mockServiceWorker.js | 349 ------------------ .../react-router/prototype/public/robots.txt | 2 - .../prototype/react-router.config.ts | 6 - .../react-router/prototype/tailwind.config.js | 10 - .../react-router/prototype/tsconfig.json | 20 - example-templates/react-router/turbo.json | 59 --- example-templates/react-router/ui/README.md | 6 - .../react-router/ui/eslint.config.mjs | 21 -- .../react-router/ui/package.json | 53 --- .../react-router/ui/src/lib/utils.ts | 20 - .../react-router/ui/src/ui/empty-state.tsx | 19 - .../react-router/ui/src/ui/scroll-area.tsx | 44 --- .../react-router/ui/tailwind.config.js | 60 --- .../react-router/ui/tsconfig.json | 8 - .../ui/turbo/generators/config.ts | 30 -- .../turbo/generators/templates/component.hbs | 8 - .../docs/modules/ROOT/pages/architecture.adoc | 7 +- .../modules/ROOT/pages/getting-started.adoc | 64 +++- .../docs/modules/ROOT/pages/mock-data.adoc | 34 +- .../docs/modules/ROOT/pages/monorepo.adoc | 5 +- .../docs/modules/ROOT/pages/prototype.adoc | 20 + 90 files changed, 194 insertions(+), 3268 deletions(-) delete mode 100644 example-templates/react-router/.cursor/rules/accessibility.mdc delete mode 100644 example-templates/react-router/.cursor/rules/react.mdc delete mode 100644 example-templates/react-router/.cursor/rules/tests.mdc delete mode 100644 example-templates/react-router/.env.example delete mode 100644 example-templates/react-router/.gitignore delete mode 100644 example-templates/react-router/.gitlab-ci.yml delete mode 100644 example-templates/react-router/.licenses/isc.md delete mode 100644 example-templates/react-router/.lintstagedrc.js delete mode 100644 example-templates/react-router/.nvmrc delete mode 100644 example-templates/react-router/.prettierrc.js delete mode 100644 example-templates/react-router/.vscode/settings.json delete mode 100644 example-templates/react-router/LICENSE.md delete mode 100644 example-templates/react-router/api/commons/enums.ts delete mode 100644 example-templates/react-router/api/commons/types.ts delete mode 100644 example-templates/react-router/api/eslint.config.js delete mode 100644 example-templates/react-router/api/tsconfig.json delete mode 100644 example-templates/react-router/config/eslint/README.md delete mode 100644 example-templates/react-router/config/eslint/base.js delete mode 100644 example-templates/react-router/config/eslint/package.json delete mode 100644 example-templates/react-router/config/eslint/react.js delete mode 100644 example-templates/react-router/config/typescript/base.json delete mode 100644 example-templates/react-router/config/typescript/node-library.json delete mode 100644 example-templates/react-router/config/typescript/package.json delete mode 100644 example-templates/react-router/config/typescript/react-app.json delete mode 100644 example-templates/react-router/config/typescript/react-library.json delete mode 100644 example-templates/react-router/docs/antora-playbook.yml delete mode 100644 example-templates/react-router/docs/antora.yml delete mode 100644 example-templates/react-router/docs/modules/ROOT/images/Prototyp-Repo.drawio.png delete mode 100644 example-templates/react-router/docs/modules/ROOT/nav.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/architecture.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/design-system.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/documentation.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/getting-started.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/index.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/login.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/mock-data.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/monorepo.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/prototype.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/pages/tailwind.adoc delete mode 100644 example-templates/react-router/docs/modules/ROOT/partials/monorepo.puml delete mode 100644 example-templates/react-router/docs/package.json delete mode 100644 example-templates/react-router/frontend/package.json delete mode 100644 example-templates/react-router/mocks/AGENTS.md delete mode 100644 example-templates/react-router/mocks/eslint.config.js delete mode 100644 example-templates/react-router/mocks/package.json delete mode 100644 example-templates/react-router/mocks/src/static/README.md delete mode 100644 example-templates/react-router/mocks/tsconfig.json delete mode 100644 example-templates/react-router/mocks/vite.config.ts delete mode 100644 example-templates/react-router/msw/AGENTS.md delete mode 100644 example-templates/react-router/msw/eslint.config.js delete mode 100644 example-templates/react-router/msw/package.json delete mode 100644 example-templates/react-router/msw/src/utils.ts delete mode 100644 example-templates/react-router/msw/tsconfig.json delete mode 100644 example-templates/react-router/package.json delete mode 100644 example-templates/react-router/prototype/.cursorrules.md delete mode 100644 example-templates/react-router/prototype/app/entry.client.tsx delete mode 100644 example-templates/react-router/prototype/app/hooks/useBreakpoint.ts delete mode 100644 example-templates/react-router/prototype/app/lib/utils.ts delete mode 100644 example-templates/react-router/prototype/app/mocks/browser.ts delete mode 100644 example-templates/react-router/prototype/app/styles/tailwind.css delete mode 100644 example-templates/react-router/prototype/app/vite-env.d.ts delete mode 100644 example-templates/react-router/prototype/components.json delete mode 100644 example-templates/react-router/prototype/eslint.config.mjs delete mode 100644 example-templates/react-router/prototype/package.json delete mode 100644 example-templates/react-router/prototype/postcss.config.js delete mode 100644 example-templates/react-router/prototype/public/favicon.ico delete mode 100644 example-templates/react-router/prototype/public/mockServiceWorker.js delete mode 100644 example-templates/react-router/prototype/public/robots.txt delete mode 100644 example-templates/react-router/prototype/react-router.config.ts delete mode 100644 example-templates/react-router/prototype/tailwind.config.js delete mode 100644 example-templates/react-router/prototype/tsconfig.json delete mode 100644 example-templates/react-router/turbo.json delete mode 100644 example-templates/react-router/ui/README.md delete mode 100644 example-templates/react-router/ui/eslint.config.mjs delete mode 100644 example-templates/react-router/ui/package.json delete mode 100644 example-templates/react-router/ui/src/lib/utils.ts delete mode 100644 example-templates/react-router/ui/src/ui/empty-state.tsx delete mode 100644 example-templates/react-router/ui/src/ui/scroll-area.tsx delete mode 100644 example-templates/react-router/ui/tailwind.config.js delete mode 100644 example-templates/react-router/ui/tsconfig.json delete mode 100644 example-templates/react-router/ui/turbo/generators/config.ts delete mode 100644 example-templates/react-router/ui/turbo/generators/templates/component.hbs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8164503..f7fd4b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,27 +4,15 @@ To verify the generator before publishing: -1. Run `npm pack` in this repository to produce a tarball (for example `create-tinker-stack-0.2.8.tgz`). +1. Run `npm pack` in this repository to produce a tarball (for example `create-tinker-stack-0.2.9.tgz`). 2. Run the generator from this repository, passing a target directory as a positional argument: ```bash -npx --yes create-tinker-stack@file://$(pwd)/create-tinker-stack-0.2.8.tgz my-project +npx --yes create-tinker-stack@file://$(pwd)/create-tinker-stack-0.2.9.tgz my-project ``` This scaffolds a clean starter into `./my-project`. -### With the example bundle - -Pass `--with-example` to also generate the `react-router` example, or name a specific example with `--example`: - -```bash -# Default example (react-router) -npx --yes create-tinker-stack@file://$(pwd)/create-tinker-stack-0.2.8.tgz my-project --with-example - -# Named example -npx --yes create-tinker-stack@file://$(pwd)/create-tinker-stack-0.2.8.tgz my-project --example react-router -``` - The example is placed in `my-project/examples/react-router/` and is independent of the root workspace. ### Notes diff --git a/create/main.js b/create/main.js index 4c74160..553149d 100644 --- a/create/main.js +++ b/create/main.js @@ -22,30 +22,6 @@ export async function main({ cwd, templateDir, exampleTemplatesDir, targetDir, e errorOnExist: true, }); - if (examples.length > 0) { - const examplesDir = path.join(targetDir, 'examples'); - await fs.mkdir(examplesDir, { recursive: true }); - - for (const example of examples) { - const sourceDir = path.join(exampleTemplatesDir, example); - - try { - const stat = await fs.stat(sourceDir); - if (!stat.isDirectory()) { - throw new Error(`Example template path is not a directory: ${sourceDir}`); - } - } catch (error) { - throw new Error(`Unknown example template "${example}"`); - } - - await fs.cp(sourceDir, path.join(examplesDir, example), { - recursive: true, - force: false, - errorOnExist: true, - }); - } - } - const EXAMPLE_ENV_PATH = path.join(targetDir, '.env.example'); const ENV_PATH = path.join(targetDir, '.env'); const PKG_PATH = path.join(targetDir, 'package.json'); @@ -97,6 +73,54 @@ export async function main({ cwd, templateDir, exampleTemplatesDir, targetDir, e fs.writeFile(PKG_PATH, JSON.stringify(packageJson, null, 2)), ]); + if (examples.length > 0) { + const examplesDir = path.join(targetDir, 'examples'); + await fs.mkdir(examplesDir, { recursive: true }); + + for (const example of examples) { + const sourceDir = path.join(exampleTemplatesDir, example); + + try { + const stat = await fs.stat(sourceDir); + if (!stat.isDirectory()) { + throw new Error(`Example template path is not a directory: ${sourceDir}`); + } + } catch (error) { + throw new Error(`Unknown example template "${example}"`); + } + + const exampleTargetDir = path.join(examplesDir, example); + + // Copy from templateDir (not targetDir) to avoid a circular-copy error — + // Node rejects copying a directory into its own subdirectory at the path-check + // level, before any filter function is called. + await fs.cp(templateDir, exampleTargetDir, { + recursive: true, + force: false, + errorOnExist: true, + }); + + // Apply the same token replacements as for the main project, remapped to exampleTargetDir. + const remap = (f) => path.join(exampleTargetDir, path.relative(targetDir, f)); + await replaceTokensInFiles(filesWithAppTitle.map(remap), appTitleRegex, APP_TITLE); + await replaceTokensInFiles(filesWithAppName.map(remap), appNameRegex, APP_NAME); + + // Mirror the package.json cleanup and .env setup. + const exPkgPath = path.join(exampleTargetDir, 'package.json'); + const exPkg = JSON.parse(await fs.readFile(exPkgPath, 'utf-8')); + exPkg.name = APP_NAME; + delete exPkg.author; + delete exPkg.license; + await Promise.all([ + fs.copyFile(path.join(exampleTargetDir, '.env.example'), path.join(exampleTargetDir, '.env')), + fs.writeFile(exPkgPath, JSON.stringify(exPkg, null, 2)), + ]); + + // Overlay example-specific files on top. + await mergeExampleFiles(sourceDir, exampleTargetDir); + } + } + if (!process.env.SKIP_SETUP) { execSync('npm install', { cwd: targetDir, stdio: 'inherit' }); execSync('npm run typecheck', { cwd: targetDir, stdio: 'inherit' }); @@ -124,6 +148,44 @@ What's next? ); } +async function mergeExampleFiles(sourceDir, targetDir) { + const entries = await fs.readdir(sourceDir, { recursive: true, withFileTypes: true }); + for (const entry of entries) { + if (!entry.isFile()) continue; + const relativePath = path.relative(sourceDir, path.join(entry.parentPath, entry.name)); + const sourcePath = path.join(sourceDir, relativePath); + const targetPath = path.join(targetDir, relativePath); + + if (relativePath.endsWith('.json')) { + const base = JSON.parse(await fs.readFile(targetPath, 'utf-8')); + const delta = JSON.parse(await fs.readFile(sourcePath, 'utf-8')); + await fs.writeFile(targetPath, JSON.stringify(deepMerge(base, delta), null, 2)); + } else { + await fs.mkdir(path.dirname(targetPath), { recursive: true }); + await fs.copyFile(sourcePath, targetPath); + } + } +} + +function deepMerge(base, override) { + const result = { ...base }; + for (const [key, value] of Object.entries(override)) { + if ( + value !== null && + typeof value === 'object' && + !Array.isArray(value) && + result[key] !== null && + typeof result[key] === 'object' && + !Array.isArray(result[key]) + ) { + result[key] = deepMerge(result[key], value); + } else { + result[key] = value; + } + } + return result; +} + async function replaceTokensInFiles(files, pattern, replacement) { for (const file of files) { try { diff --git a/example-templates/react-router/.cursor/rules/accessibility.mdc b/example-templates/react-router/.cursor/rules/accessibility.mdc deleted file mode 100644 index 9774ae0..0000000 --- a/example-templates/react-router/.cursor/rules/accessibility.mdc +++ /dev/null @@ -1,24 +0,0 @@ ---- -description: All tasks that are related to improving accessibility (a11y) -globs: -alwaysApply: false ---- - -# Accessibility Rules - -All UI components in must comply with the WCAG 2.1 AA standard. - -- For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. -- Non-native user interactive components need their `role` attribute set. Pay attention to nested components and also take the role of parent components into account. -- Non-native user interactive components which can be in different UI states, need to be annotated with WAI-ARIA state and property attributes where possible. -- Interactive components need to be labelled either via label elements or through `aria-label` or `aria-labelledby`. -- Do not add noise and information that is not relevant to a user. -- Avoid redundancy. Verify that there are no duplicated annotations. Also check parent and child components. -- Keyboard navigation needs to work in all components. -- User focus needs to be properly guided. -- New titles need to be localized. -- Interactive elements cannot contain other interactive elements. - -Do not forget to also update the tests for a component. - -Use the class `sr-only` for elements that should only be visible to screenreaders. \ No newline at end of file diff --git a/example-templates/react-router/.cursor/rules/react.mdc b/example-templates/react-router/.cursor/rules/react.mdc deleted file mode 100644 index eab9da8..0000000 --- a/example-templates/react-router/.cursor/rules/react.mdc +++ /dev/null @@ -1,18 +0,0 @@ ---- -description: -globs: *.tsx -alwaysApply: false ---- - -# Rules for authoring React components - -- React is not just a UI framework but also a concept of how a UI is composed. Information should only flow downwards (One-Way dataflow). Never break this concept. -- Only trigger updates through events / actions or handlers. -- Avoid Refs to a child component. Use Props / Context instead and have the child component react to a change in props. Never trigger changes on a different component explicitly. -- React uses functional concepts instead of OOP concepts. -- Components and Hooks must be pure. -- Prefer useReducer over multiple useStates in the same component. -- Document the code in a way that you still understand it a year later. - - - diff --git a/example-templates/react-router/.cursor/rules/tests.mdc b/example-templates/react-router/.cursor/rules/tests.mdc deleted file mode 100644 index 0cf4039..0000000 --- a/example-templates/react-router/.cursor/rules/tests.mdc +++ /dev/null @@ -1,11 +0,0 @@ ---- -description: -globs: *.spec.tsx -alwaysApply: false ---- - -# Tests - -- This project is using Testing-Library -- Use semantic selectors from testing-library over querySelector(). -- Prefer user-event over fireEvent. diff --git a/example-templates/react-router/.env.example b/example-templates/react-router/.env.example deleted file mode 100644 index 0827589..0000000 --- a/example-templates/react-router/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -VITE_BUILD_NUMBER=Vite -VITE_VERSION=dev \ No newline at end of file diff --git a/example-templates/react-router/.gitignore b/example-templates/react-router/.gitignore deleted file mode 100644 index afda6bb..0000000 --- a/example-templates/react-router/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# Dependencies -node_modules -.pnp -.pnp.js - -# Local env files -.env -.env.local -.env.development.local -.env.test.local -.env.production.local - -# Testing -coverage - -# Turbo -.turbo - -# Vercel -.vercel - -# Build Outputs -.next/ -out/ -build -dist -/.cache -.react-router/ -/public/build -tsconfig.tsbuildinfo -data-mocks/ - -# Debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -vite.config.ts.timestamp-* - -# Misc -.DS_Store -*.pem -.idea/ - - -catalyst-ui-kit/ \ No newline at end of file diff --git a/example-templates/react-router/.gitlab-ci.yml b/example-templates/react-router/.gitlab-ci.yml deleted file mode 100644 index ce76e08..0000000 --- a/example-templates/react-router/.gitlab-ci.yml +++ /dev/null @@ -1,188 +0,0 @@ -# Root CI File - -include: - - component: $CI_SERVER_HOST/$CI_COMPONENT_DIR/gitlab-environments/preview@1.0 - inputs: - build_job: 'build prototype' - stage: publish - build_folder: 'prototype/build/client' - -default: - image: node:22 - interruptible: true - # Usage of global_cache key to override the default push-pull policy - # https://docs.gitlab.com/ee/ci/caching/index.html - cache: &npm_cache - key: - files: - - package-lock.json - policy: pull - paths: - - 'node_modules/' - - './*/node_modules/' - - 'config/*/node_modules/' - timeout: 2 minutes - -stages: - - install - - verify - - build - - publish - -variables: - TURBO_TELEMETRY_DISABLED: 1 - VITE_BUILD_NUMBER: ${CI_PIPELINE_IID} - VITE_VERSION: ${CI_COMMIT_SHORT_SHA} - -workflow: - rules: - - if: $CI_MERGE_REQUEST_IID - - if: $CI_COMMIT_TAG - when: always - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TAG == null - - if: $CI_PIPELINE_SOURCE == "schedule" - -############################################################ -# -# Install stage -# -############################################################ - -# Install dependencies -install dependencies: - stage: install - interruptible: false - cache: - - <<: *npm_cache - policy: pull-push - script: - - node -v - - echo "Installing Dependencies" - - 'find . -name "node_modules" -type d -prune -exec rm -rf "{}" +' - - time npm clean-install - # We need to install the linux version of rollup here. https://github.com/npm/cli/issues/4828 - - npm i -O @rollup/rollup-linux-x64-gnu - rules: - - if: $CI_COMMIT_REF_PROTECTED == "true" - - if: $CI_MERGE_REQUEST_IID - changes: - - 'package-lock.json' - allow_failure: false - - if: $CI_PIPELINE_SOURCE == "schedule" - -force install dependencies: - extends: install dependencies - rules: - - when: manual - allow_failure: true - script: - - node -v - - 'find . -name "node_modules" -type d -prune -exec rm -rf "{}" +' - - npm install --frozen-lockfile --no-progress --non-interactive - - npm i -O @rollup/rollup-linux-x64-gnu - -############################################################ -# -# Verify stage -# -############################################################ - -# Run Type Checks on all changed modules. -verify: - stage: verify - interruptible: true - variables: - ESLINT_CODE_QUALITY_REPORT: 'gl-code-quality-report.json' - cache: - - <<: *npm_cache - - key: verify-$CI_COMMIT_REF_SLUG - paths: - - '.turbo/' - - '**/.turbo/' - needs: - - job: install dependencies - optional: true - script: - - node --version - - npm --version - - npm ci - - ./node_modules/.bin/turbo run typecheck - - ./node_modules/.bin/turbo run lint - artifacts: - when: always - expire_in: 5 days - paths: - - gl-code-quality-report.json - reports: - codequality: 'gl-code-quality-report.json' - -test: - stage: verify - interruptible: true - needs: - - job: install dependencies - optional: true - script: - - ./node_modules/.bin/turbo run test - -############################################################ -# -# Build stage -# -############################################################ - -build prototype: - interruptible: true - stage: build - script: - - npm ci - - npm run build:prototype - artifacts: - paths: - - prototype/build - -############################################################ -# -# Publish stage -# -############################################################ - -pages: - stage: publish - needs: - - job: install dependencies - optional: true - allow_failure: true - script: - - npm ci - - npm run docs - artifacts: - paths: - - docs/build - publish: docs/build - rules: - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - changes: - - 'docs/**/*' - -publish prototype continuous: - extends: create preview - variables: - CI_MERGE_REQUEST_ID: p${CI_PROJECT_ID}-cont - rules: - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - environment: - name: 'prototype/${CI_PROJECT_PATH_SLUG}/continuous' - url: $CI_MERGE_REQUEST_REVIEW_URL - on_stop: 'stop prototype continuous' - -stop prototype continuous: - extends: stop preview - variables: - CI_MERGE_REQUEST_ID: p${CI_PROJECT_ID}-cont - environment: - name: 'prototype/${CI_PROJECT_PATH_SLUG}/continuous' - action: stop - rules: - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - when: manual diff --git a/example-templates/react-router/.licenses/isc.md b/example-templates/react-router/.licenses/isc.md deleted file mode 100644 index 31b673a..0000000 --- a/example-templates/react-router/.licenses/isc.md +++ /dev/null @@ -1,17 +0,0 @@ -# ISC License - -- Lucide - -Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All -other copyright (c) for Lucide are held by Lucide Contributors 2022. - -Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee -is hereby granted, provided that the above copyright notice and this permission notice appear in all -copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. diff --git a/example-templates/react-router/.lintstagedrc.js b/example-templates/react-router/.lintstagedrc.js deleted file mode 100644 index 90e682a..0000000 --- a/example-templates/react-router/.lintstagedrc.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - '*.{js,jsx,ts,tsx,json,css,scss,md}': ['prettier --write'], -} diff --git a/example-templates/react-router/.nvmrc b/example-templates/react-router/.nvmrc deleted file mode 100644 index e4f846d..0000000 --- a/example-templates/react-router/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v22.10.0 diff --git a/example-templates/react-router/.prettierrc.js b/example-templates/react-router/.prettierrc.js deleted file mode 100644 index 5af14a2..0000000 --- a/example-templates/react-router/.prettierrc.js +++ /dev/null @@ -1,30 +0,0 @@ -/** @type {import("prettier").Options} */ -export default { - arrowParens: 'avoid', - bracketSameLine: false, - bracketSpacing: true, - embeddedLanguageFormatting: 'auto', - endOfLine: 'lf', - htmlWhitespaceSensitivity: 'css', - insertPragma: false, - jsxSingleQuote: false, - printWidth: 100, - proseWrap: 'always', - quoteProps: 'consistent', - requirePragma: false, - semi: true, - singleAttributePerLine: false, - singleQuote: true, - tabWidth: 2, - trailingComma: 'all', - useTabs: true, - overrides: [ - { - files: ['**/*.json', '**/*.yaml', '**/*.yml', '/**/*.adoc', '**/*.md'], - options: { - useTabs: false, - }, - }, - ], - plugins: ['prettier-plugin-organize-imports'], -}; diff --git a/example-templates/react-router/.vscode/settings.json b/example-templates/react-router/.vscode/settings.json deleted file mode 100644 index 335f886..0000000 --- a/example-templates/react-router/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.defaultFormatter": "esbenp.prettier-vscode" -} \ No newline at end of file diff --git a/example-templates/react-router/LICENSE.md b/example-templates/react-router/LICENSE.md deleted file mode 100644 index 55654ce..0000000 --- a/example-templates/react-router/LICENSE.md +++ /dev/null @@ -1,18 +0,0 @@ -MIT License - -Copyright (c) 2025 ti&m - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES -OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/example-templates/react-router/api/commons/enums.ts b/example-templates/react-router/api/commons/enums.ts deleted file mode 100644 index 3984b3c..0000000 --- a/example-templates/react-router/api/commons/enums.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Granular Permissions. - * The UI only uses these permissions which are derived from the roles in the JWT. - * The key is the permission name and the value is the permission description. - */ -export const permissions = { - 'reports-create': 'Create reports', - 'reports-approve': 'Approve reports', - 'admin': 'Administrative privileges', -}; - -export type Permission = keyof typeof permissions; diff --git a/example-templates/react-router/api/commons/types.ts b/example-templates/react-router/api/commons/types.ts deleted file mode 100644 index 3df1886..0000000 --- a/example-templates/react-router/api/commons/types.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Image Object - */ -export type Image = { - url: string; - alt?: string; - width?: number; - height?: number; -}; - -/** - * Calendar Date String (YYYY-MM-DD) - */ -export type IsoDateString = string; -/** - * ISO 8601 Timestamp String - */ -export type IsoTimestampString = string; - -/** - * Spring Boot Paginated Response - */ -export type PaginatedResponse = { - content: T[]; - pageable: { - pageNumber: number; - pageSize: number; - }; - totalPages: number; - totalElements: number; - first: boolean; - last: boolean; - size: number; - number: number; -}; - -export type File = { - readonly type: string; - readonly name: string; - readonly size: number; - readonly createdAt: IsoTimestampString; -}; diff --git a/example-templates/react-router/api/eslint.config.js b/example-templates/react-router/api/eslint.config.js deleted file mode 100644 index 75d444b..0000000 --- a/example-templates/react-router/api/eslint.config.js +++ /dev/null @@ -1,15 +0,0 @@ -import baseConfig from '@repo/eslint-config/base'; - -export default [ - { - ignores: ['**/node_modules/**', '**/dist/**', '**/.turbo/**'], - }, - ...baseConfig, - { - languageOptions: { - parserOptions: { - tsconfigRootDir: import.meta.dirname, - }, - }, - }, -]; diff --git a/example-templates/react-router/api/package.json b/example-templates/react-router/api/package.json index c297c84..088691e 100644 --- a/example-templates/react-router/api/package.json +++ b/example-templates/react-router/api/package.json @@ -1,43 +1,7 @@ { - "name": "@repo/api", - "description": "Domain Types und Enums", - "version": "0.1.0", - "sideEffects": false, - "type": "module", - "scripts": { - "build": "rimraf dist && tsc && tsc-alias", - "dev": "tsc && (concurrently \"tsc -w\" \"tsc-alias -w\")", - "clean": "rimraf dist && rimraf .turbo", - "format": "prettier --write .", - "typecheck": "tsc && tsc-alias", - "lint": "eslint .", - "lint-staged": "lint-staged" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*" - }, - "engines": { - "node": ">=22.0.0" - }, "exports": { - "./commons/types": { - "types": "./dist/commons/types.d.ts" - }, - "./commons/enums": { - "types": "./dist/commons/enums.d.ts", - "import": "./dist/commons/enums.js" - }, "./demo/types": { "types": "./dist/demo/types.d.ts" } - }, - "lint-staged": { - "*.{js,ts,tsx}": [ - "prettier --write" - ], - "*.{json,md}": [ - "prettier --write" - ] } -} \ No newline at end of file +} diff --git a/example-templates/react-router/api/tsconfig.json b/example-templates/react-router/api/tsconfig.json deleted file mode 100644 index 1c4452b..0000000 --- a/example-templates/react-router/api/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "@repo/typescript-config/node-library.json", - "include": ["./**/*.ts"], - "compilerOptions": { - "baseUrl": ".", - "paths": { - "#/*": ["./*"] - }, - "outDir": "dist" - }, - "exclude": ["node_modules", "dist", ".turbo"] -} diff --git a/example-templates/react-router/config/eslint/README.md b/example-templates/react-router/config/eslint/README.md deleted file mode 100644 index 8b42d90..0000000 --- a/example-templates/react-router/config/eslint/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@turbo/eslint-config` - -Collection of internal eslint configurations. diff --git a/example-templates/react-router/config/eslint/base.js b/example-templates/react-router/config/eslint/base.js deleted file mode 100644 index d14dd65..0000000 --- a/example-templates/react-router/config/eslint/base.js +++ /dev/null @@ -1,61 +0,0 @@ -import eslint from '@eslint/js'; -import eslintConfigPrettier from 'eslint-config-prettier'; -import importPlugin from 'eslint-plugin-import'; -import globals from 'globals'; -import tseslint from 'typescript-eslint'; - -/** - * This is the basic rule set for all projects. - * Make sure to add the languageOptions.parserOptions.tsconfigRootDir to the project you want to lint. - * @returns { import('typescript-eslint').FlatConfig.ConfigArray } - */ -export default tseslint.config( - eslint.configs.recommended, - importPlugin.flatConfigs.recommended, - importPlugin.flatConfigs.typescript, - ...tseslint.configs.recommendedTypeChecked, - ...tseslint.configs.stylisticTypeChecked, - { - languageOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - parserOptions: { - projectService: { - allowDefaultProject: ['*.js'], - defaultProject: 'tsconfig.json', - }, - ecmaFeatures: { - jsx: true, - }, - }, - globals: { - // ...globals.browser, - ...globals.serviceworker, - }, - }, - settings: { - 'import/internal-regex': '^#/', - }, - rules: { - '@typescript-eslint/no-empty-object-type': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/consistent-type-definitions': 'off', - '@typescript-eslint/only-throw-error': 'off', - '@typescript-eslint/no-duplicate-type-constituents': [ - 'error', - { - ignoreUnions: true, - ignoreIntersections: true, - }, - ], - '@typescript-eslint/consistent-type-imports': [ - 'error', - { fixStyle: 'separate-type-imports', prefer: 'type-imports' }, - ], - 'import/no-unresolved': 'off', // does not properly work with nodenext yet. - 'import/no-relative-packages': 'error', - 'import/no-relative-parent-imports': 'error', - }, - }, - eslintConfigPrettier, -); diff --git a/example-templates/react-router/config/eslint/package.json b/example-templates/react-router/config/eslint/package.json deleted file mode 100644 index 7bf38de..0000000 --- a/example-templates/react-router/config/eslint/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@repo/eslint-config", - "version": "0.0.0", - "private": true, - "files": [ - "base.js", - "react.js" - ], - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^8.49.0", - "@typescript-eslint/parser": "^8.49.0", - "eslint-config-prettier": "^10.1.8", - "eslint-config-turbo": "^2.6.3", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.0.1", - "typescript": "^5.9.3", - "typescript-eslint": "^8.49.0" - }, - "type": "module", - "exports": { - "./base": "./base.js", - "./react": "./react.js" - } -} diff --git a/example-templates/react-router/config/eslint/react.js b/example-templates/react-router/config/eslint/react.js deleted file mode 100644 index d163295..0000000 --- a/example-templates/react-router/config/eslint/react.js +++ /dev/null @@ -1,42 +0,0 @@ -import baseConfig from '@repo/eslint-config/base'; -import reactPlugin from 'eslint-plugin-react'; -import reactHooksPlugin from 'eslint-plugin-react-hooks'; -import tseslint from 'typescript-eslint'; - -/** - * This config adds additional rules for React and JSX. - * @returns { import('typescript-eslint').FlatConfig.ConfigArray } - */ -export default tseslint.config( - ...baseConfig, - { - settings: { - react: { - version: 'detect', - }, - }, - }, - reactPlugin.configs.flat.recommended, - reactPlugin.configs.flat['jsx-runtime'], - // enable a11y rules for the frontend and UI only - // jsxA11yPlugin.flatConfigs.recommended, - // React - { - files: ['**/*.{tsx}'], - settings: { - formComponents: ['Form'], - linkComponents: [ - { name: 'Link', linkAttribute: 'to' }, - { name: 'NavLink', linkAttribute: 'to' }, - ], - }, - plugins: { - 'react-hooks': reactHooksPlugin, - }, - rules: { - 'react/react-in-jsx-scope': 'off', - ...reactHooksPlugin.configs.recommended.rules, - 'react-hooks/rules-of-hooks': 'error', - }, - }, -); diff --git a/example-templates/react-router/config/typescript/base.json b/example-templates/react-router/config/typescript/base.json deleted file mode 100644 index 20d7e23..0000000 --- a/example-templates/react-router/config/typescript/base.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "display": "Default", - "compilerOptions": { - "composite": true, - "esModuleInterop": true, - "incremental": true, - "isolatedModules": true, - "lib": ["ESNext"], - "forceConsistentCasingInFileNames": true, - "module": "NodeNext", - "moduleDetection": "force", - "moduleResolution": "NodeNext", - "noUncheckedIndexedAccess": true, - "resolveJsonModule": true, - "allowImportingTsExtensions": false, - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "target": "ESNext", - "noEmit": true - } -} diff --git a/example-templates/react-router/config/typescript/node-library.json b/example-templates/react-router/config/typescript/node-library.json deleted file mode 100644 index 9fb6019..0000000 --- a/example-templates/react-router/config/typescript/node-library.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "display": "Node Library", - "extends": "./base.json", - "compilerOptions": { - "noEmit": false, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "target": "ESNext", - } - } \ No newline at end of file diff --git a/example-templates/react-router/config/typescript/package.json b/example-templates/react-router/config/typescript/package.json deleted file mode 100644 index 27c0e60..0000000 --- a/example-templates/react-router/config/typescript/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@repo/typescript-config", - "version": "0.0.0", - "private": true, - "license": "MIT", - "publishConfig": { - "access": "public" - } -} diff --git a/example-templates/react-router/config/typescript/react-app.json b/example-templates/react-router/config/typescript/react-app.json deleted file mode 100644 index 37e1448..0000000 --- a/example-templates/react-router/config/typescript/react-app.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "display": "React App", - "extends": "./base.json", - "compilerOptions": { - "jsx": "react-jsx", - "lib": ["ESNext", "DOM", "DOM.Iterable", "WebWorker"], - "noEmit": true, - "module": "ESNext", - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true - } -} diff --git a/example-templates/react-router/config/typescript/react-library.json b/example-templates/react-router/config/typescript/react-library.json deleted file mode 100644 index 2543a7f..0000000 --- a/example-templates/react-router/config/typescript/react-library.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "display": "React Library", - "extends": "./base.json", - "compilerOptions": { - "jsx": "react-jsx", - "lib": ["ESNext", "DOM", "DOM.Iterable"], - "allowImportingTsExtensions": true, - } -} diff --git a/example-templates/react-router/docs/antora-playbook.yml b/example-templates/react-router/docs/antora-playbook.yml deleted file mode 100644 index dfc9cb1..0000000 --- a/example-templates/react-router/docs/antora-playbook.yml +++ /dev/null @@ -1,22 +0,0 @@ -site: - title: PLANNING STACK TEMPLATE Dokumentation - start_page: planning-stack-template-frontend::index.adoc - url: https://frontend-6dd0b0.pages.ti8m.ch -content: - sources: - - url: ../ - branches: HEAD - start_path: docs -ui: - bundle: - url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable - snapshot: true -output: - dir: ./build -asciidoc: - attributes: - # makes the extension download and store diagrams in Antora's _images folder (in output dir) - kroki-fetch-diagram: true - product: PLANNING STACK TEMPLATE - extensions: - - asciidoctor-kroki diff --git a/example-templates/react-router/docs/antora.yml b/example-templates/react-router/docs/antora.yml deleted file mode 100644 index 18fdf82..0000000 --- a/example-templates/react-router/docs/antora.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: 'planning-stack-template-frontend' -title: 'PLANNING STACK TEMPLATE Frontend' -version: true -nav: - - modules/ROOT/nav.adoc diff --git a/example-templates/react-router/docs/modules/ROOT/images/Prototyp-Repo.drawio.png b/example-templates/react-router/docs/modules/ROOT/images/Prototyp-Repo.drawio.png deleted file mode 100644 index 3e73d5a9d44f9bb9bf3fc79ace5d15ea263d57d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24086 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≧aj4 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 T8Sp=Phmn<3lqh*@81VlAoYLA% diff --git a/example-templates/react-router/docs/modules/ROOT/nav.adoc b/example-templates/react-router/docs/modules/ROOT/nav.adoc deleted file mode 100644 index f8c4bf7..0000000 --- a/example-templates/react-router/docs/modules/ROOT/nav.adoc +++ /dev/null @@ -1,11 +0,0 @@ -:product: PLANNING STACK TEMPLATE - -* xref:index.adoc[Übersicht] -** xref:getting-started.adoc[Erste Schritte] -** xref:architecture.adoc[Architektur] -** xref:monorepo.adoc[Monorepo] -** xref:prototype.adoc[Prototyp] -** xref:mocks.adoc[Testdaten] -** xref:design-system.adoc[Design System] -** xref:login.adoc[Login Flow] -** xref:tailwind.adoc[Tailwind] \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/architecture.adoc b/example-templates/react-router/docs/modules/ROOT/pages/architecture.adoc deleted file mode 100644 index a940995..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/architecture.adoc +++ /dev/null @@ -1,145 +0,0 @@ -= Architektur -:experimental: -:plantuml-server-url: http://www.plantuml.com/plantuml -:source-highlighter: highlight.js - -== Überblick - -Das PLANNING STACK TEMPLATE Frontend ist als Monorepo mit mehreren Packages aufgebaut. Der Fokus liegt auf: - -* Schnelle Iteration durch Prototyping -* Wiederverwendbare Komponenten -* Typsicherheit durch TypeScript -* Realistische Testdaten - -== Architekturprinzipien - -=== Domain-Driven Design - - - - -=== Prototypen-getriebene Entwicklung - -Der Entwicklungsprozess folgt einem iterativen Ansatz: - -1. Features werden zuerst im Prototyp implementiert -2. Designer-, Stakeholder- und Benutzer-Feedback wird eingeholt -3. Validierte Features werden in die produktive Anwendung übernommen - -Dies ermöglicht: - -* Reduzierung von Entwicklungsrisiken -* Validierung von UX-Konzepten -* Schnelles Feedback von Benutzern - -=== Typsicherheit - -* Strikte TypeScript Konfiguration -* Zentrale Definition von Domain Types -* Shared Types zwischen Packages - -=== Komponenten-Bibliothek - -Die UI-Komponenten sind in einem separaten Package (`@repo/ui`) organisiert: - -* Basis auf shadcn/ui, Tailwind UI und Tailwind -* Wiederverwendbar zwischen Prototyp und Produktion -* Einheitliches Design-System basierend auf Tailwind UI und dem Figma Design System - -== Technische Architektur - -Siehe auch xref:monorepo.adoc#aufbau[Monorepo]. - -=== Frontend Stack - -[cols="1,2,2"] -|=== -|Technologie |Verwendung |Begründung - -|React -|UI Framework -|Etabliert, grosses Ökosystem - -|React Router -|Full-Stack Framework -|Gute DX, Server Components - -|Tailwind -|CSS Framework -|Utility-First, Wartbar - -|shadcn/ui -|UI-Komponenten -|Zugänglich, Anpassbar - -|TypeScript -|Programmiersprache -|Typsicherheit, DX -|=== - -=== Mock Backend - -[plantuml,msw,svg] ----- -@startuml -actor Browser -participant "React Router App" as App -participant "MSW" as MSW -database "Mock Data" as Data - -Browser -> App: Request -App -> MSW: API Call -MSW -> Data: Load Data -Data --> MSW: Data -MSW --> App: Response -App --> Browser: Render -@enduml ----- - -* MSW (Mock Service Worker) für API-Simulation -* Realistische HTTP-Requests -* Einfacher Wechsel zu echtem Backend - -== Entwicklungsprozess - -=== Feature Entwicklung - -1. Feature-Anforderung -2. Prototyp Implementation -3. User Testing -4. Feedback Integration -5. Production Implementation - -=== Code Organisation - -* Feature-basierte Ordnerstruktur -* Shared Logic in Utils -* Typed API Boundaries - -== Deployment - -=== Prototype - -* Automatisches Deployment bei Push auf `main` -** URL: -** Aktuelle Entwicklungsversion -* Deployment bei Tag-Commit -** URL: -** Stabile Version für User-Testing - -=== Documentation - -* Antora Site Generator -* Deployed zusammen mit Prototype -* Automatische Updates - -== Supporting Subdomain - - -== Zukünftige Entwicklung - -* Migration zu Production App -* API Integration -* E2E Tests -* Performance Monitoring \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/design-system.adoc b/example-templates/react-router/docs/modules/ROOT/pages/design-system.adoc deleted file mode 100644 index ffa094c..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/design-system.adoc +++ /dev/null @@ -1,57 +0,0 @@ -= Design System -:experimental: - -== Überblick - - -== Komponenten - - -=== Verwendung - -[source,tsx] ----- -import { Button } from '@repo/ui/components/button' -import { LucideIcon } from 'lucide-react' - -export function IconButton({ icon: Icon }) { - return ( - - ) -} ----- - -== Theming - -=== Figma Integration - -* Designs aus Figma Projekt -* Farben und Typography synchron halten -* Komponenten-Patterns übernehmen - -=== Tailwind Konfiguration - -* Custom Colors aus CI -* Spacing und Typography nach Design System -* Erweiterbare Struktur - -Siehe auch xref:tailwind.adoc[Tailwind Dokumentation] für Best Practices. - -== Komponenten entwickeln - -=== Workflow - -1. Figma Design reviewen -2. shadcn/ui Komponente als Basis nehmen -3. Mit Tailwind UI Patterns abgleichen -4. An Design System anpassen -5. Dokumentation erstellen - -=== Guidelines - -* Accessibility first -* Responsive Design -* Konsistente Props API -* Dokumentation in Storybook diff --git a/example-templates/react-router/docs/modules/ROOT/pages/documentation.adoc b/example-templates/react-router/docs/modules/ROOT/pages/documentation.adoc deleted file mode 100644 index 4478161..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/documentation.adoc +++ /dev/null @@ -1,93 +0,0 @@ -= Dokumentation -:experimental: -:url-antora-docs: https://docs.antora.org/antora/latest/ -:url-kroki-docs: https://docs.kroki.io/kroki/ - -== Überblick - -Die Entwicklerdokumentation wird mit {url-antora-docs}[Antora] erstellt und über GitLab Pages bereitgestellt. - -* URL: -* Automatisches Deployment bei Push auf `main` -* Versionierung über Git - -== Struktur - -[source] ----- -docs/ -├── antora.yml # Antora Projekt-Konfiguration -├── antora-playbook.yml # Site Generator Konfiguration -└── modules/ - └── ROOT/ - ├── nav.adoc # Navigation - ├── pages/ # Dokumentationsseiten - └── partials/ # Wiederverwendbare Inhalte ----- - -== Diagramme - -Die Dokumentation unterstützt verschiedene Diagrammtypen über {url-kroki-docs}[Kroki]: - -=== PlantUML - -[source,asciidoc] ----- -[plantuml,format=svg] ----- -@startuml -package "Frontend" { - [Components] - [Routes] -} -[Components] --> [Routes] -@enduml ----- ----- - -=== Weitere Diagrammtypen - -* Mermaid -* C4 (mit PlantUML) -* GraphViz -* ... - -Siehe {url-kroki-docs}#diagram-types[Kroki Diagram Types] für eine vollständige Liste. - -== Lokale Entwicklung - -=== Voraussetzungen - -* Node.js >= 22.0.0 -* npm >= 10.0.0 - -=== Dokumentation lokal generieren - -[source,bash] ----- -# Im docs Verzeichnis -npm run docs ----- - -Die generierte Dokumentation ist dann unter `docs/build` verfügbar. - -== Best Practices - -* Neue Features parallel zur Implementierung dokumentieren -* Diagramme für komplexe Zusammenhänge nutzen -* Wiederverwendbare Inhalte in `partials` auslagern -* Interne Links mit `xref:` erstellen - -== Deployment - -Das Deployment erfolgt automatisch über die GitLab CI/CD Pipeline: - -* Trigger: Push auf `main` -* Output: Statische Seiten -* Hosting: GitLab Pages - -== Nützliche Links - -* {url-antora-docs}[Antora Dokumentation] -* {url-antora-docs}asciidoc/page/[AsciiDoc Syntax Guide] -* {url-kroki-docs}[Kroki Dokumentation] \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/getting-started.adoc b/example-templates/react-router/docs/modules/ROOT/pages/getting-started.adoc deleted file mode 100644 index 7229b2a..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/getting-started.adoc +++ /dev/null @@ -1,139 +0,0 @@ -= Erste Schritte -:experimental: -:icons: font - - - -== Voraussetzungen - -Für die Entwicklung werden folgende Tools benötigt: - -* Node.js >= 22 -* npm >= 10 -* Git - -== Repository klonen - -[source,bash] ----- -git clone TODO -cd planning-stack-template ----- - -== Installation - -Das Projekt verwendet npm Workspaces. Alle Abhängigkeiten können mit einem Befehl installiert werden: - -[source,bash] ----- -npm install ----- - -== Entwicklungsumgebung einrichten - -=== Mock-Daten generieren - -Vor dem ersten Start müssen die Mock-Daten generiert werden: - -[source,bash] ----- -npm run build:data ----- - -=== Entwicklungsserver starten - -Der Entwicklungsserver kann mit folgendem Befehl im Root-Verzeichnis des Repos gestartet werden: - -[source,bash] ----- -npm run dev ----- - -Dies startet: - -* Den https://reactrouter.com/home[React Router] Entwicklungsserver (Prototyp) -* Einen Watcher für die Mock-Daten -* Einen Watcher für die UI-Komponenten - -Die Anwendung ist dann unter http://localhost:5173 erreichbar. - -== Projektstruktur - -[source] ----- -. -├── api/ # Domain Types & Enums -├── config/ -│ ├── eslint/ # ESLint Konfigurationen -│ ├── typescript/ # Typescript Konfigurationen -├── docs/ # Dokumentation -├── frontend/ # Produktives Frontend (noch nicht eingerichtet) -├── mocks/ # Testdaten Generator -├── mock-api/ # Mock Backend -├── prototype/ # Klickbarer UX-Prototyp -└── ui/ # Design-System Komponenten ----- - - -== IDE Konfiguration - -=== VS Code - -Empfohlene Extensions: - -* ESLint -* Prettier -* Tailwind CSS IntelliSense -* AsciiDoc - -Die Projekteinstellungen für VS Code sind bereits im Repository enthalten. - -=== WebStorm - -Für WebStorm müssen folgende Plugins installiert werden: - -* Tailwind CSS -* AsciiDoc - -== Typische Entwicklungsabläufe - -=== Neue Feature im Prototyp entwickeln - -1. Feature-Branch erstellen -2. Route in `prototype/app/routes` anlegen -3. UI mit shadcn/ui Komponenten aufbauen -4. Mock-Daten in `mocks` erweitern falls nötig -5. Feature testen und iterieren -6. Pull Request erstellen - -=== UI-Komponente hinzufügen - -1. Komponente in `packages/ui/src/components` erstellen -2. Storybook Story schreiben -3. Tests hinzufügen -4. Komponente exportieren und im Prototyp verwenden - -== Nächste Schritte - -* xref:architecture.adoc[Architektur] verstehen -* xref:prototype.adoc[Prototyp] kennenlernen -* xref:design-system.adoc[Design System] erkunden - -== Troubleshooting - -=== Bekannte Probleme - -[qanda] -Typescript Fehler nach npm install:: - Führen Sie `npm run build` aus, um alle Packages zu bauen. - -Mock-Daten werden nicht aktualisiert:: - Löschen Sie den `.cache` Ordner und führen Sie `npm run build:data` erneut aus. - -=== Support - -Bei Problemen: - -1. Prüfen Sie die bekannten Probleme -2. Suchen Sie in den GitHub Issues -3. Erstellen Sie ein neues Issue \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/index.adoc b/example-templates/react-router/docs/modules/ROOT/pages/index.adoc deleted file mode 100644 index 4d0ccaa..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/index.adoc +++ /dev/null @@ -1,78 +0,0 @@ -= PLANNING STACK TEMPLATE Frontend Dokumentation -:description: Entwicklerdokumentation für das PLANNING STACK TEMPLATE Frontend -:experimental: - -== Über dieses Projekt - -Beschreibung des Projekts - -== Module - -.Frontend-Struktur -image::Prototyp-Repo.drawio.png[Repository-Struktur] - -Das Projekt ist als Monorepo mit folgenden Hauptmodulen aufgebaut: - -[cols="1,4"] -|=== -|Modul |Beschreibung - -|@repo/api -|Domain-Typen und Enums - -|@repo/docs -|Diese Dokumentation - -|@repo/e2e -|End-to-End und Integrations-Tests (Browser-Tests) - -|@repo/frontend -|Frontend-Anwendung - -|@repo/msw -|Mock-Backend mit MSW - -|@repo/mocks -|Synthetische Testdaten-Generator - -|@repo/prototype -|Klickbarer UX-Prototyp für schnelles Feedback - -|@repo/ui -|Design-System und Komponenten-Bibliothek - -|=== - -Das Mock-API muss mit dem Backend synchron gehalten werden. Somit ist es möglich, die Frontend-Anwendung lokal zu entwickeln und gleichzeitig das Backend zu testen. - -Ausserdem ist es dadurch möglich, mit dem Prototypen gegen das echte Backend zu testen. - - -== Technologie-Stack - -Das Frontend basiert auf folgenden Haupttechnologien: - -* *React* mit TypeScript für die UI-Entwicklung -* *Tailwind CSS* mit shadcn/ui für das Design-System -* *Turborepo* für das Monorepo-Management -* *MSW* (Mock Service Worker) für das Mock-Backend -* *Antora* für die Dokumentation - -Die Technologie für das Frontend ist noch offen. Empfohlen wird -React Router v7 als Framework (Isomorph). - -Der Prototyp verwendet React Router SPA, damit er auf einem Shared-Host deployed werden kann. - -== Erste Schritte - -Siehe xref:getting-started.adoc[Erste Schritte] für Setup-Anweisungen und einen Überblick über die Entwicklungsumgebung. - -== Architektur - -Die Anwendung folgt einer prototypen-getriebenen Entwicklung: - -1. Schnelle Iteration über Features im Prototyp -2. Feedback von Benutzern einholen -3. Validierte Features in die produktive Anwendung übernehmen - -Mehr Details zur Architektur unter xref:architecture.adoc[Architektur]. \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/login.adoc b/example-templates/react-router/docs/modules/ROOT/pages/login.adoc deleted file mode 100644 index 627d3a5..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/login.adoc +++ /dev/null @@ -1,62 +0,0 @@ -= Login Flow (Prototyp) -:experimental: - -== Überblick - -Im Prototyp wird ein vereinfachtes Login-System verwendet: - -* Cookie-basierte Authentifizierung -* Mock Implementation mit MSW -* Vordefinierte Test-Benutzer - -== Implementation - -=== Mock Service Worker - -[plantuml,mock-auth,svg] ----- -@startuml -participant "Browser" as Browser -participant "MSW Handler" as MSW -database "Mock Data" as Data - -Browser -> MSW: POST /auth/login -note right: Form Data mit Username -MSW -> Data: Token lookup -Data --> MSW: JWT Payload -MSW -> MSW: Permissions aus\nRollen ermitteln -MSW --> Browser: Set-Cookie: authToken -@enduml ----- - -=== Test-Benutzer - -[cols="1,2,1"] -|=== -|Persona |Organisation |Permissions - -|Administrator -|Primär-Organisation -|Alle Org-Berechtigungen - -|=== - -== Authentifizierung - -Die Auth-Prüfung erfolgt in den MSW Handlers: - -[source,typescript] ----- -// Beispiel eines geschützten msw Endpoints -http.post('/reports/approve', async ({ cookies }) => { - const { sub, orgId, permissions } = auth(cookies); - // ... Handler Implementation -}); ----- - -== Hinweise - -* Diese Implementation ist nur für den Prototyp, sollte aber ähnlich sein zu der späteren Produktiv-Implementation -* Keine echte Sicherheit -* Dient nur der Feature-Entwicklung -* Produktive Implementation erfolgt später mit IAM \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/mock-data.adoc b/example-templates/react-router/docs/modules/ROOT/pages/mock-data.adoc deleted file mode 100644 index e871f62..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/mock-data.adoc +++ /dev/null @@ -1,46 +0,0 @@ -= Testdaten -:experimental: - -== Überblick - -Das `@repo/mocks` Package generiert synthetische Testdaten für die Entwicklung. Die Daten sind: - -* Realistisch und konsistent -* Typsicher durch TypeScript -* Reproduzierbar durch feste Seeds - -Die Daten werden im Entwicklungs-Modus On-The-Fly beim Reload der Applikation generiert. - -== Generator - -=== Technologie - -* https://fakerjs.dev/[Faker.js] für realistische Daten -* TypeScript für Typsicherheit -* 3 vorgegebene Konfigurationen für unterschiedliche Datenmengen - ** `small`: Für manuelle Prüfung der erstellten Daten. - ** `medium`: Für automatisches Testen und Entwicklung. - ** `full`: Alle Organisationen, für vollständige Tests. - - -=== Verwendung - -Siehe `@repo/mocks/README.md` - -Der Ordner enthält Generator-Klassen für die einzelnen Entitäten. - -In der Datei `dataset.ts` werden die einzelnen Generatoren zu einem Datensatz zusammengefasst. - -== Daten erweitern - -1. Domain-Types in `@repo/api` definieren und falls nötig im lokalen Repository anpassen. -2. Generator in `@repo/mocks/src/generators` erstellen -3. In `dataset.ts` integrieren -4. Build mit `npm run build:data` - -== Best Practices - -* Realistische Wertebereiche verwenden -* Beziehungen zwischen Entitäten beachten -* Lokale Besonderheiten berücksichtigen (z.B. Schweizer Adressen) -* Reproduzierbarkeit durch Seeds sicherstellen \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/monorepo.adoc b/example-templates/react-router/docs/modules/ROOT/pages/monorepo.adoc deleted file mode 100644 index f31d30c..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/monorepo.adoc +++ /dev/null @@ -1,64 +0,0 @@ -= Monorepo - -Siehe auch README.md. - -Wir verwenden Turborepo mit der https://turbo.build/repo/docs/core-concepts/internal-packages#compiled-packages[Compiled Packages] Strategie. - -Alle Pakete sind ESM-Module und verwenden den `@repo` Scope. - -Dieses Monorepo enthält die folgenden Pakete/Apps: - -== Apps und Pakete - -- `@repo/frontend`: das Frontend für die PLANNING STACK TEMPLATE Anwendung (noch zu erstellen). -- `@repo/prototype`: ein Prototyp für die PLANNING STACK TEMPLATE Anwendung. -- `@repo/api`: ein Paket, das die Domain-Typen und -Enums bereitstellt. -- `@repo/docs`: Dokumentationen für die PLANNING STACK TEMPLATE Anwendung im Antora-Format. -- `@repo/mocks`: ein Paket, das synthetische Daten für die Anwendungen bereitstellt. -- `@repo/mock-api`: ein Paket, das eine Mock-API über Service-Worker bereitstellt. -- `@repo/ui`: eine Basis-React-Komponentenbibliothek, die von den Anwendungen `FAS` und `prototype` - gemeinsam genutzt wird -- `@repo/eslint-config`: `eslint`-Konfigurationen -- `@repo/typescript-config`: `tsconfig.json`s, die im gesamten Monorepo verwendet werden - -== Build - -Die Builds sind alle von https://turbo.build[Turborepo] gesteuert und sollten aus dem -Root-Verzeichnis heraus aufgerufen werden. werden. - -Um alle Apps und Pakete zu bauen, führe den folgenden Befehl aus: - -``` -npm run build -``` - -Es ist auch möglich, nur ein bestimmtes Paket oder eine bestimmte App zu bauen: - -``` -npm run build:data - -npm run build:msw - -npm run build:prototype -``` - -### Entwicklung - -Aktuell ist standardmässig der Prototyp aktiviert. Um die Entwicklung zu starten, führe den -folgenden Befehl aus. Dieser startet einen lokalen Server und watcher für die Abhängigen Pakete. - -``` -npm run dev -``` - - - -== Aufbau - -[plantuml,monorepo,svg,role=component] ----- -include::partial$monorepo.puml[] ----- - -Das Monorepo verwendet die export und import Direktiven von node ESM Modulen. -Alle exportierten Namespaces müssen in der package.json Datei aufgelistet werden. \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/prototype.adoc b/example-templates/react-router/docs/modules/ROOT/pages/prototype.adoc deleted file mode 100644 index a0d1223..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/prototype.adoc +++ /dev/null @@ -1,105 +0,0 @@ -= Prototyp -:experimental: - -== Zweck - -Der PLANNING STACK TEMPLATE Prototyp dient als: - -* Testumgebung für neue Features und UX-Konzepte -* Basis für Benutzerfeedback und Iterationen -* Proof-of-Concept für technische Lösungen - -== Struktur - -Die Ordnerstruktur des Prototypen orientiert sich an den Modulen des Produktionssystems. -Zusätzlich gibt es den Ordner 'components' für Modulübergreifende UI-Komponenten und 'hooks' für wiederverwendbare Logik. -Der Ordner 'lib' enthält Hilfsfunktionen. Der Ordner 'mocks' die Logik für die Mock-Daten. - -Die Routen sind über eine Route-Konfiguration in app/routes.ts definiert. -Die Route-Komponenten sind in den entsprechenden Modul-Ordnern. - -== API - -Der Prototyp verwendet das `ky` Paket für HTTP-Anfragen. - - -=== Technischer Aufbau - -* React Router SPA mit TypeScript -* Mock-Backend via MSW -* Synthetische Testdaten -* shadcn/ui Komponenten - -== Entwicklungsprozess - -=== Feature-Entwicklung - -1. Feature-Anforderung erfassen -2. Schnelle Implementierung im Prototyp -3. Review mit Stakeholdern -4. Feedback einarbeiten -5. User-Stories updaten -6. Feature für Produktion freigeben - -=== Guidelines - -* Fokus auf Benutzerinteraktion, nicht auf Datenvalidierung -* TODOs für fehlende Produktionsanforderungen -* Schnelle Iteration über perfekte Implementation -* Realistische Testdaten verwenden - -== Deployment - -Das Deployment erfolgt automatisch über die CI/CD Pipeline: - -=== Umgebungen - -[cols="1,3"] -|=== -|Umgebung |Beschreibung - -|Continuous Integration -|* Deployment bei Push auf `main` -* URL: -* Aktuelle Entwicklungsversion - -|Acceptance Test -|* Deployment bei Tag-Commit -* URL: -* Stabile Version für User-Testing - - -|Preview -|* Preview-Umgebung, z.B. für Merge-Requests -* URL: -* Alternative Version für A/B Tests. -|=== - -Die nötigen Zugangsdaten müssen in den Umgebungsvariablen gesetzt werden. Siehe `.env.example`. - -Das Deployment auf Preview kann bei einem Merge-Request manuell ausgelöst werden. - -=== Zugriff - -* Die Hosts sind über einen IP-Filter geschützt. Die Konfiguration ist in der .htaccess Datei im Ordner `prototype/app/public`. - -* Der Host für die Dokumentation kann nur vom internen Netzwerk aus erreicht werden. - - -== Limitationen - -* Keine echte Backend-Anbindung -* Eingeschränkte Validierung -* Vereinfachte Berechtigungen -* Keine Performance-Optimierung - -== Nächste Schritte - -* Integration von Benutzer-Feedback -* Priorisierung der Features für Produktion -* Identifikation technischer Herausforderungen - -== Bekannte Probleme - -* msw in einer Version höher als 2.6.3 (getestet bis 2.6.6) funktioniert nicht mit dem dev server. Das CSS kann nicht geladen werden. -Aktuell ist die Version auf 2.6.3 gepinnt. Allenfalls später nochmals testen und ggf. einen Github-Issue erstellen. \ No newline at end of file diff --git a/example-templates/react-router/docs/modules/ROOT/pages/tailwind.adoc b/example-templates/react-router/docs/modules/ROOT/pages/tailwind.adoc deleted file mode 100644 index 2359bef..0000000 --- a/example-templates/react-router/docs/modules/ROOT/pages/tailwind.adoc +++ /dev/null @@ -1,22 +0,0 @@ -= Tailwind Tipps und Tricks - -Tailwind Docs: https://tailwindcss.com/docs/ - -== State -Die Seite soll barrierefrei sein, daher bietet es sich an, die States falls möglich -auf den jeweiligen Aria-States zu basieren. - -.Beispiel Button -```tsx -