|
1 | 1 | # vue-static |
2 | | -.NET 10 Minimal Vue Vite Identity Auth Template with Static Export |
| 2 | + |
| 3 | +A minimal full-stack .NET 10.0 + Vue Vite project template optimized for AI assisted development that combines the power of ServiceStack with Vue Vite static site generation and Vue 3. It provides a production-ready foundation for building scalable web applications with integrated authentication, database management, and background job processing. |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +> Browse [source code](https://github.com/NetCoreTemplates/vue-static), view live demo [vue-static.web-templates.io](http://vue-static.web-templates.io) and install with: |
| 8 | +
|
| 9 | +## Quick Start |
| 10 | + |
| 11 | +```bash |
| 12 | +npx create-net vue-static MyProject |
| 13 | +``` |
| 14 | + |
| 15 | +## Jumpstart with Copilot |
| 16 | + |
| 17 | +Instantly [scaffold a new App with this template](https://github.com/new?template_name=vue-static&template_owner=NetCoreTemplates) using GitHub Copilot, just describe the features you want and watch Copilot build it! |
| 18 | + |
| 19 | +## Getting Started |
| 20 | + |
| 21 | +Run Server .NET Project (automatically starts both .NET and Vite React dev servers): |
| 22 | + |
| 23 | +```bash |
| 24 | +cd MyProject |
| 25 | +dotnet watch |
| 26 | +``` |
| 27 | + |
| 28 | +## Architecture |
| 29 | + |
| 30 | +### Hybrid Development Approach |
| 31 | + |
| 32 | +**Development Mode:** |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +- ASP.NET Core proxies requests to Vite dev server (running on port 5173) |
| 37 | +- Hot Module Replacement (HMR) support for instant UI updates |
| 38 | +- WebSocket proxying for Vite HMR functionality |
| 39 | + |
| 40 | +**Production Mode:** |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +- Vite React app is statically exported to `/dist` |
| 45 | +- Static files served directly from ASP.NET Core's `/wwwroot` |
| 46 | +- No separate Node.js server required in production |
| 47 | + |
| 48 | +## Core Technologies |
| 49 | + |
| 50 | +### Frontend |
| 51 | + |
| 52 | +- **Vue 3** - A JavaScript library for building user interfaces |
| 53 | +- **Vite 7** - Next Generation Frontend Tooling |
| 54 | +- **Tailwind CSS v4** - CSS-first configuration with `@tailwindcss/vite` plugin |
| 55 | +- **TypeScript 5** - JavaScript with syntax for types |
| 56 | +- **Vitest** - Modern testing framework |
| 57 | +- **ServiceStack Vue Components** - Pre-built UI components |
| 58 | + |
| 59 | +### .NET Frontend (Integrated + Optional) |
| 60 | +- **Razor Pages** - For Identity Auth UI (`/Identity` routes) |
| 61 | + |
| 62 | +### Backend (.NET 10.0) |
| 63 | +- **ServiceStack 10.x** - High-performance web services framework |
| 64 | +- **ASP.NET Core Identity** - Complete authentication & authorization system |
| 65 | +- **Entity Framework Core** - For Identity data management |
| 66 | +- **OrmLite** - ServiceStack's fast, lightweight Typed ORM for application data |
| 67 | +- **SQLite** - Default database (easily upgradable to PostgreSQL/SQL Server/MySQL) |
| 68 | + |
| 69 | +## Major Features |
| 70 | + |
| 71 | +### 1. Authentication & Authorization |
| 72 | +- ASP.NET Core Identity integration with role-based access control |
| 73 | +- Custom user sessions with additional claims |
| 74 | +- Admin users feature for user management at `/admin-ui/users` |
| 75 | +- Email confirmation workflow (configurable SMTP) |
| 76 | +- Razor Pages for Identity UI (`/Identity` routes) |
| 77 | +- Credentials-based authentication |
| 78 | + |
| 79 | +### [2. AutoQuery CRUD](#autoquery-crud-dev-workflow) |
| 80 | +- Declarative API development with minimal code |
| 81 | +- Automatic audit trails (created/modified/deleted tracking) |
| 82 | +- Built-in validation and authorization |
| 83 | +- Type-safe TypeScript DTOs auto-generated from C# models |
| 84 | + |
| 85 | +### 3. Background Jobs |
| 86 | +- `BackgroundsJobFeature` for async task processing |
| 87 | +- Command pattern for job execution |
| 88 | +- Email sending via background jobs |
| 89 | +- Recurring job scheduling support |
| 90 | +- Upgradable to `DatabaseJobsFeature` for enterprise RDBMS |
| 91 | + |
| 92 | +### 4. Developer Experience |
| 93 | +- **Admin UI** at `/admin-ui` for App management |
| 94 | +- **Health checks** at `/up` endpoint |
| 95 | +- **Modular startup** configuration pattern |
| 96 | +- **Code-first migrations** with OrmLite |
| 97 | +- **Docker support** with container publishing |
| 98 | +- **Kamal deployment** configuration included |
| 99 | + |
| 100 | +### 5. Production Features |
| 101 | +- Static asset caching with intelligent cache invalidation |
| 102 | +- Clean URLs without `.html` extensions |
| 103 | +- HTTPS redirection and HSTS |
| 104 | +- Data protection with persistent keys |
| 105 | +- Health monitoring |
| 106 | +- Database developer page for EF Core errors |
| 107 | + |
| 108 | +## Project Structure |
| 109 | + |
| 110 | +``` |
| 111 | +MyApp/ # .NET Backend (hosts both .NET and Vite Vue |
| 112 | +├── Configure.*.cs # Modular startup configuration |
| 113 | +├── Migrations/ # EF Core Identity migrations + OrmLite app migrations |
| 114 | +├── Pages/ # Identity Auth Razor Pages |
| 115 | +└── wwwroot/ # Production static files (from MyApp.Client/dist) |
| 116 | +
|
| 117 | +MyApp.Client/ # Vue Frontend |
| 118 | +├── src/ |
| 119 | +│ ├── lib/ |
| 120 | +│ │ ├── dtos.ts # Auto-generated from C# (via `npm run dtos`) |
| 121 | +│ │ ├── gateway.ts # ServiceStack JsonServiceClient |
| 122 | +│ │ └── utils.ts # Utility functions |
| 123 | +│ ├── components/ # Vue components |
| 124 | +│ └── styles/ # Tailwind CSS |
| 125 | +└── vite.config.ts # Vite config for dev mode |
| 126 | +
|
| 127 | +MyApp.ServiceModel/ # DTOs & API contracts |
| 128 | +├── *.cs # C# Request/Response DTOs |
| 129 | +├── api.d.ts # TypeScript data models Schema |
| 130 | +└── *.d.ts # TypeScript data models for okai code generation |
| 131 | +
|
| 132 | +MyApp.ServiceInterface/ # Service implementations |
| 133 | +├── Data/ # EF Core DbContext and Identity models |
| 134 | +└── *Services.cs # ServiceStack service implementations |
| 135 | +
|
| 136 | +MyApp.Tests/ # .NET tests (NUnit) |
| 137 | +├── IntegrationTest.cs # API integration tests |
| 138 | +└── MigrationTasks.cs # Migration task runner |
| 139 | +
|
| 140 | +config/ |
| 141 | +└── deploy.yml # Kamal deployment settings |
| 142 | +.github/ |
| 143 | +└── workflows/ |
| 144 | + ├── build.yml # CI build and test |
| 145 | + ├── build-container.yml # Container image build |
| 146 | + └── release.yml # Production deployment with Kamal |
| 147 | +``` |
| 148 | + |
| 149 | + |
| 150 | +## Development Workflow |
| 151 | + |
| 152 | +### 1. Start Development |
| 153 | + |
| 154 | +```bash |
| 155 | +dotnet watch |
| 156 | +``` |
| 157 | + |
| 158 | +This automatically starts both .NET and Vite dev servers. |
| 159 | + |
| 160 | +### 2. Generate TypeScript DTOs |
| 161 | + |
| 162 | +After modifying C# service models, regenerate TypeScript dtos.ts in `MyApp` or `MyApp.Client` with: |
| 163 | + |
| 164 | +```bash |
| 165 | +npm run dtos |
| 166 | +``` |
| 167 | + |
| 168 | +### 3. Database Migrations |
| 169 | + |
| 170 | +**OrmLite and Entity Framework:** |
| 171 | + |
| 172 | +```bash |
| 173 | +npm run migrate |
| 174 | +``` |
| 175 | + |
| 176 | +**OrmLite (for application data):** |
| 177 | + |
| 178 | +Create migration classes in `MyApp/Migrations/` following the pattern in `Migration1000.cs`. |
| 179 | + |
| 180 | +### 4. Testing |
| 181 | + |
| 182 | +**Frontend:** |
| 183 | +```bash |
| 184 | +cd MyApp.Client |
| 185 | +npm run test # Run tests in watch mode |
| 186 | +npm run test:ui # Run tests with UI |
| 187 | +npm run test:run # Run tests once |
| 188 | +``` |
| 189 | + |
| 190 | +## Configuration |
| 191 | + |
| 192 | +### Key Configuration Files |
| 193 | + |
| 194 | +- **MyApp/appsettings.json** - Application configuration |
| 195 | +- **MyApp.Client/next.config.mjs** - Next.js configuration |
| 196 | +- **MyApp.Client/styles/index.css** - Tailwind CSS configuration |
| 197 | +- **config/deploy.yml** - Kamal deployment settings |
| 198 | + |
| 199 | +### App Settings |
| 200 | + |
| 201 | +Configure in `appsettings.json` or environment: |
| 202 | + |
| 203 | +```json |
| 204 | +{ |
| 205 | + "ConnectionStrings": { |
| 206 | + "DefaultConnection": "DataSource=App_Data/app.db;Cache=Shared" |
| 207 | + }, |
| 208 | + "SmtpConfig": { |
| 209 | + "Host": "smtp.example.com", |
| 210 | + "Port": 587, |
| 211 | + |
| 212 | + "FromName": "MyApp" |
| 213 | + }, |
| 214 | + "AppConfig": { |
| 215 | + "BaseUrl": "https://myapp.example.com" |
| 216 | + } |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +### App Settings Secrets |
| 221 | + |
| 222 | +Instead of polluting each GitHub Reposity with multiple App-specific GitHub Action Secrets, you can save all your secrets in a single `APPSETTINGS_PATCH` GitHub Action Secret to patch `appsettings.json` with environment-specific configuration using [JSON Patch](https://jsonpatch.com). E.g: |
| 223 | + |
| 224 | +```json |
| 225 | +[ |
| 226 | + { |
| 227 | + "op":"replace", |
| 228 | + "path":"/ConnectionStrings/DefaultConnection", |
| 229 | + "value":"Server=service-postgres;Port=5432;User Id=dbuser;Password=dbpass;Database=dbname;Pooling=true;" |
| 230 | + }, |
| 231 | + { "op":"add", "path":"/SmtpConfig", "value":{ |
| 232 | + "UserName": "SmptUser", |
| 233 | + "Password": "SmptPass", |
| 234 | + "Host": "email-smtp.us-east-1.amazonaws.com", |
| 235 | + "Port": 587, |
| 236 | + |
| 237 | + "FromName": "MyApp", |
| 238 | + |
| 239 | + } |
| 240 | + }, |
| 241 | + { "op": "add", "path": "/Admins", "value": [ "[email protected]", "[email protected]"] }, |
| 242 | + { "op":"add", "path":"/CorsFeature/allowOriginWhitelist/-", "value":"https://servicestack.net" } |
| 243 | +] |
| 244 | +``` |
| 245 | + |
| 246 | +### SMTP Email |
| 247 | + |
| 248 | +Enable email sending by uncommenting in `Program.cs`: |
| 249 | + |
| 250 | +```csharp |
| 251 | +services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>(); |
| 252 | +``` |
| 253 | + |
| 254 | +## Upgrading to Enterprise Database |
| 255 | + |
| 256 | +To switch from SQLite to PostgreSQL/SQL Server/MySQL: |
| 257 | + |
| 258 | +1. Install preferred RDBMS (ef-postgres, ef-mysql, ef-sqlserver), e.g: |
| 259 | + |
| 260 | +```bash |
| 261 | +npx add-in ef-postgres |
| 262 | +``` |
| 263 | + |
| 264 | +2. Install `db-identity` to use RDBMS `DatabaseJobsFeature` for background jobs and `DbRequestLogger` for Request Logs: |
| 265 | + |
| 266 | +```bash |
| 267 | +npx add-in db-identity |
| 268 | +``` |
| 269 | + |
| 270 | +## Deployment |
| 271 | + |
| 272 | +### Docker + Kamal |
| 273 | + |
| 274 | +This project includes GitHub Actions for CI/CD with automatic Docker image builds and production [deployment with Kamal](https://docs.servicestack.net/kamal-deploy). The `/config/deploy.yml` configuration is designed to be reusable across projects—it dynamically derives service names, image paths, and volume mounts from environment variables, so you only need to configure your server's IP and hostname using GitHub Action secrets. |
| 275 | + |
| 276 | +### GitHub Action Secrets |
| 277 | + |
| 278 | +**Required - App Specific*: |
| 279 | + |
| 280 | +The only secret needed to be configured per Repository. |
| 281 | + |
| 282 | +| Variable | Example | Description | |
| 283 | +|----------|---------|-------------| |
| 284 | +| `KAMAL_DEPLOY_HOST` | `example.org` | Hostname used for SSL certificate and Kamal proxy | |
| 285 | + |
| 286 | +**Required** (Organization Secrets): |
| 287 | + |
| 288 | +Other Required variables can be globally configured in your GitHub Organization or User secrets which will |
| 289 | +enable deploying all your Repositories to the same server. |
| 290 | + |
| 291 | +| Variable | Example | Description | |
| 292 | +|----------|----------|-------------| |
| 293 | +| `KAMAL_DEPLOY_IP` | `100.100.100.100` | IP address of the server to deploy to | |
| 294 | +| `SSH_PRIVATE_KEY` | `ssh-rsa ...` | SSH private key to access the server | |
| 295 | +| `LETSENCRYPT_EMAIL` | `[email protected]` | Email for Let's Encrypt SSL certificate | |
| 296 | + |
| 297 | +**Optional**: |
| 298 | + |
| 299 | +| Variable | Example | Description | |
| 300 | +|----------|---------|-------------| |
| 301 | +| `SERVICESTACK_LICENSE` | `...` | ServiceStack license key | |
| 302 | + |
| 303 | +**Inferred** (from GitHub Action context): |
| 304 | + |
| 305 | +These are inferred from the GitHub Action context and don't need to be configured. |
| 306 | + |
| 307 | +| Variable | Source | Description | |
| 308 | +|----------|--------|-------------| |
| 309 | +| `GITHUB_REPOSITORY` | `${{ github.repository }}` | e.g. `acme/example.org` - used for service name and image | |
| 310 | +| `KAMAL_REGISTRY_USERNAME` | `${{ github.actor }}` | GitHub username for container registry | |
| 311 | +| `KAMAL_REGISTRY_PASSWORD` | `${{ secrets.GITHUB_TOKEN }}` | GitHub token for container registry auth | |
| 312 | + |
| 313 | +#### Features |
| 314 | + |
| 315 | +- **Docker containerization** with optimized .NET images |
| 316 | +- **SSL auto-certification** via Let's Encrypt |
| 317 | +- **GitHub Container Registry** integration |
| 318 | +- **Volume persistence** for App_Data including any SQLite database |
| 319 | + |
| 320 | + |
| 321 | +## AutoQuery CRUD Dev Workflow |
| 322 | + |
| 323 | +For Rapid Development simple [TypeScript Data Models](https://docs.servicestack.net/autoquery/okai-models) can be used to generate C# AutoQuery APIs and DB Migrations. |
| 324 | + |
| 325 | +### Cheat Sheet |
| 326 | + |
| 327 | +Create a new Table use `init <Table>`, e.g: |
| 328 | + |
| 329 | +```bash |
| 330 | +npx okai init Table |
| 331 | +``` |
| 332 | + |
| 333 | +This will generate an empty `MyApp.ServiceModel/<Table>.d.ts` file along with stub AutoQuery APIs and DB Migration implementations. |
| 334 | + |
| 335 | +#### Regenerate AutoQuery APIs and DB Migrations |
| 336 | + |
| 337 | +After modifying the TypeScript Data Model to include the desired fields, re-run the `okai` tool to re-generate the AutoQuery APIs and DB Migrations: |
| 338 | + |
| 339 | +```bash |
| 340 | +npx okai Table.d.ts |
| 341 | +``` |
| 342 | + |
| 343 | +> Command can be run anywhere within your Solution |
| 344 | +
|
| 345 | +After you're happy with your Data Model you can run DB Migrations to run the DB Migration and create your RDBMS Table: |
| 346 | + |
| 347 | +```bash |
| 348 | +npm run migrate |
| 349 | +``` |
| 350 | + |
| 351 | +#### Making changes after first migration |
| 352 | + |
| 353 | +If you want to make further changes to your Data Model, you can re-run the `okai` tool to update the AutoQuery APIs and DB Migrations, then run the `rerun:last` npm script to drop and re-run the last migration: |
| 354 | + |
| 355 | +```bash |
| 356 | +npm run rerun:last |
| 357 | +``` |
| 358 | + |
| 359 | +#### Removing a Data Model and all generated code |
| 360 | + |
| 361 | +If you changed your mind and want to get rid of the RDBMS Table you can revert the last migration: |
| 362 | + |
| 363 | +```bash |
| 364 | +npm run revert:last |
| 365 | +``` |
| 366 | + |
| 367 | +Which will drop the table and then you can get rid of the AutoQuery APIs, DB Migrations and TypeScript Data model with: |
| 368 | + |
| 369 | +```bash |
| 370 | +npx okai rm Transaction.d.ts |
| 371 | +``` |
| 372 | + |
| 373 | +## Ideal Use Cases |
| 374 | + |
| 375 | +- SaaS applications requiring authentication |
| 376 | +- Admin dashboards with CRUD operations |
| 377 | +- Content-driven sites with dynamic APIs |
| 378 | +- Applications needing background job processing |
| 379 | +- Projects requiring both SSG benefits and API capabilities |
| 380 | +- Teams wanting type-safety across full stack |
| 381 | + |
| 382 | +## Learn More |
| 383 | + |
| 384 | +- [ServiceStack Vue Components](https://docs.servicestack.net/vue/) |
| 385 | +- [ServiceStack Documentation](https://docs.servicestack.net) |
| 386 | +- [Vite Documentation](https://vite.dev) |
| 387 | +- [Vue Documentation](https://vuejs.org) |
| 388 | +- [AutoQuery CRUD](https://react-templates.net/docs/autoquery/crud) |
| 389 | +- [Background Jobs](https://docs.servicestack.net/kamal-deploy) |
| 390 | +- [AI Chat API](https://docs.servicestack.net/ai-chat-api) |
0 commit comments