diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..a838fcd --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +# Formatting-only commits, ignored by GitHub blame and `git blame` (git config blame.ignoreRevsFile .git-blame-ignore-revs) + +# Format MyApp.Client with Oxfmt +f031f77c7dda50e1d54ddd7c6fa7316f6e21b66a diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 79ec6f4..6b5ebcf 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -65,16 +65,13 @@ jobs: echo "client_exists=false" >> $GITHUB_OUTPUT fi - - name: Setup Node.js + - name: Setup Vite+ and install npm dependencies if: steps.check_client.outputs.client_exists == 'true' - uses: actions/setup-node@v7 + uses: voidzero-dev/setup-vp@v1.22.0 with: - node-version: 24 - - - name: Install npm dependencies - if: steps.check_client.outputs.client_exists == 'true' - working-directory: ./MyApp.Client - run: npm install + node-version: '24' + working-directory: ./MyApp.Client + cache: true - name: Build client if: steps.check_client.outputs.client_exists == 'true' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6873c14..f4d8f39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,3 +49,27 @@ jobs: fi working-directory: ./MyApp.Tests + client: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v7 + + - name: Setup Vite+ and install npm dependencies + uses: voidzero-dev/setup-vp@v1.22.0 + with: + node-version: '24' + working-directory: ./MyApp.Client + cache: true + + - name: check (format, lint, type check) + run: vp check + working-directory: ./MyApp.Client + + - name: test + run: vp test run + working-directory: ./MyApp.Client + + - name: build + run: npm run build + working-directory: ./MyApp.Client diff --git a/AGENTS.md b/AGENTS.md index 9374626..edee6ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,17 +11,18 @@ A full-stack .NET 10 + React 19 + Next.js template combining ServiceStack backen ### Development ```bash -# Start both .NET and Vite dev servers (from project root) +# Start both .NET and Next.js dev servers (from project root) dotnet watch -# After making changes to C# DTOs restart .NET before regenerating TypeScript DTOs by running: +# After changing C# DTOs, restart .NET: TypeScript DTOs (dtos.ts) are regenerated on startup. +# Manual regeneration is rarely needed (requires the .NET app to be running): cd MyApp.Client && npm run dtos ``` ### Building ```bash -# Build frontend (TypeScript + Vite) +# Build frontend (Next.js static export) cd MyApp.Client && npm run build # Build backend (.NET) @@ -31,10 +32,25 @@ dotnet build cd MyApp && npm run ui:build ``` +### Checking (format, lint, type check) + +The frontend uses the [Vite+](https://viteplus.dev) toolchain (`vp` CLI) for everything except building: Vitest, Oxlint and Oxfmt. +Next.js still runs the dev server and production build (`next dev` / `next build`). +All tool config (`lint`, `fmt`, `test`) lives in [vite.config.ts](MyApp.Client/vite.config.ts). There is no ESLint, Prettier or `tsc` step. + +```bash +cd MyApp.Client && npm run check # Format + lint + type check (run before committing) +cd MyApp.Client && npm run lint # Lint + type check only (Oxlint) +cd MyApp.Client && npm run typecheck # Type check only +cd MyApp.Client && npm run fmt # Format all files (Oxfmt) +``` + +`lib/dtos.ts` and `next-env.d.ts` are generated, so they are excluded from lint and format. + ### Testing ```bash -# Frontend tests (Vitest) +# Frontend tests (Vitest via Vite+), import from 'vite-plus/test' cd MyApp.Client && npm run test # Watch mode cd MyApp.Client && npm run test:ui # UI mode cd MyApp.Client && npm run test:run # Single run @@ -112,13 +128,14 @@ MyApp.Client/ # React Frontend ├── app/ # Next.js App Router pages ├── components/ # React components ├── lib/ # Utilities and helpers -│ ├── dtos.ts # Auto-generated from C# (via `npm run dtos`) +│ ├── dtos.ts # Auto-generated from C# on .NET App startup │ ├── gateway.ts # ServiceStack JsonServiceClient │ └── utils.ts # Utility functions ├── public/ # Static assets ├── dist/ # Build output (production) ├── styles/ # Tailwind CSS styles -└── next.config.mjs # Next.js config for dev mode +├── next.config.mjs # Next.js config for dev mode +└── vite.config.ts # Vite+ config: lint, fmt, test (not used to build) MyApp.ServiceModel/ # DTOs & API contracts ├── *.cs # C# Request/Response DTOs @@ -262,13 +279,15 @@ ServiceStack's AutoQuery generates full CRUD APIs from declarative request DTOs. ### TypeScript DTO Generation -After changing C# DTOs in `MyApp.ServiceModel/`, restart the .NET Server then run: +`MyApp.Client/lib/dtos.ts` is regenerated automatically every time the .NET App starts (e.g. `dotnet run` or a `dotnet watch` restart). +This is done by the `dtos` StartupTask registered in [Configure.StartupTasks.GenerateDtos.cs](MyApp/Configure.StartupTasks.GenerateDtos.cs). +So after changing C# DTOs in `MyApp.ServiceModel/`, restarting the .NET Server is all that's needed, and the Next.js dev server auto-reloads. + +Running `npm run dtos` manually is unnecessary, but it's available if needed. It calls the running .NET App's `/types/typescript` endpoint to update `dtos.ts`: ```bash cd MyApp.Client && npm run dtos ``` -This calls ServiceStack's `/types/typescript` endpoint and updates `dtos.ts` with type-safe client DTOs. The Vite dev server auto-reloads. - ### okai AutoQuery Code Generation The `npx okai` tool generates C# AutoQuery APIs and migrations from TypeScript data models (`.d.ts` files): @@ -577,11 +596,11 @@ Configured in [Configure.BackgroundJobs.cs](MyApp/Configure.BackgroundJobs.cs) u ## Development Workflow -1. **Start dev servers:** `dotnet watch` (starts both .NET and Vite) +1. **Start dev servers:** `dotnet watch` (starts both .NET and Next.js) 2. **Make backend changes:** Edit C# files in `MyApp.ServiceModel` or `MyApp.ServiceInterface` -3. **Restart .NET Server** -4. **Regenerate DTOs:** `cd MyApp.Client && npm run dtos` -5. **Make frontend changes:** Edit React files in `MyApp.Client/src` +3. **Restart .NET Server:** this also regenerates `dtos.ts` (`npm run dtos` isn't needed) +4. **Use updated DTOs** from `@/lib/dtos` in the frontend +5. **Make frontend changes:** Edit React files in `MyApp.Client`, then `npm run check` 6. **Add new CRUD feature:** - `npx okai init Feature` - Edit `MyApp.ServiceModel/Feature.d.ts` diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index eef4bd2..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -@AGENTS.md \ No newline at end of file diff --git a/MyApp.Client/.gitignore b/MyApp.Client/.gitignore index 046716d..02ec697 100644 --- a/MyApp.Client/.gitignore +++ b/MyApp.Client/.gitignore @@ -33,3 +33,4 @@ yarn-error.log* # vercel .vercel +.vitest/ diff --git a/MyApp.Client/AGENTS.md b/MyApp.Client/AGENTS.md new file mode 100644 index 0000000..1af9261 --- /dev/null +++ b/MyApp.Client/AGENTS.md @@ -0,0 +1,41 @@ + + +# Using Vite+, the Unified Toolchain for the Web + +This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, and it invokes Vite through `vp dev` and `vp build`. Run `vp help` to print a list of commands and `vp --help` for information about a specific command. + +Docs are local at `node_modules/vite-plus/docs` or online at https://viteplus.dev/guide/. + +## Built-in Commands vs Scripts + +`vp ` runs a built-in command. `vp run ` runs a `package.json` script or a `vite.config.ts` task. Scripts cannot overwrite built-ins, so `vp dev` and `vp run dev` may do different things. Check `package.json` and `vite.config.ts` first, and run `vp run ` when the project defines a script or task with that name. + +## Running Scripts + +Run TypeScript and JavaScript files with `vpx `, for example `vpx ./scripts/seed.ts --dry-run`. It handles enums, decorators, JSX, and tsconfig `paths`, so do not add `tsx` or `ts-node` to run scripts. `vpx --watch ` reruns the file when a file it uses changes, in place of `tsx watch`. `vp node ` runs plain Node.js. + +## Tool Versions + +Run `vp toolchain` to show versions and relationships in the active Vite+ +release. Add a tool name to select part of the graph. For example, run +`vp toolchain vite`. Use `--global` to ignore the local `vite-plus` package. Use +`vp why ` to show the package-manager dependency graph. + +## Review Checklist + +- [ ] Run `vp install` after pulling remote changes and before getting started. +- [ ] Run `vp check` and `vp test` to format, lint, type check and test changes. +- [ ] Check if there are `vite.config.ts` tasks or `package.json` scripts necessary for validation, run via `vp run