Skip to content

Commit cd19e32

Browse files
committed
Update README.md
1 parent 104a9f4 commit cd19e32

File tree

1 file changed

+287
-49
lines changed

1 file changed

+287
-49
lines changed

README.md

Lines changed: 287 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -49,44 +49,6 @@ dotnet watch
4949
- Static files served directly from ASP.NET Core's `/wwwroot`
5050
- No separate Node.js server required in production
5151

52-
### Project Structure
53-
54-
```
55-
MyApp/ # Main ASP.NET Core host
56-
├── Configure.*.cs # Modular startup configuration
57-
├── Program.cs # Application entry point
58-
└── wwwroot/ # Static files (production)
59-
60-
MyApp.Client/ # Vite React SPA frontend
61-
├── src/
62-
│ ├── pages/ # React Router pages
63-
│ ├── components/ # React components
64-
│ ├── lib/ # Utilities and helpers
65-
│ └── styles/ # Tailwind CSS styles
66-
├── public/ # Static assets
67-
├── dist/ # Build output (production)
68-
└── vite.config.ts # Vite configuration
69-
70-
MyApp.ServiceInterface/ # Service implementations
71-
├── MyServices.cs # Example services
72-
└── Data/ # EF Core DbContext
73-
74-
MyApp.ServiceModel/ # DTOs and service contracts
75-
├── Bookings.cs # AutoQuery CRUD example
76-
└── Hello.cs # Example service contract
77-
78-
MyApp.Tests/ # Integration and unit tests
79-
80-
config/ # Deployment configuration
81-
└── deploy.yml # Kamal deployment settings
82-
83-
.github/ # GitHub Actions workflows
84-
└── workflows/
85-
├── build.yml # CI build and test
86-
├── build-container.yml # Container image build
87-
└── release.yml # Production deployment with Kamal
88-
```
89-
9052
## Features
9153

9254
### 🔐 Identity Authentication
@@ -208,18 +170,18 @@ Built-in theme support:
208170

209171
## Example Pages
210172

211-
| Page | Description |
212-
|------|-------------|
213-
| `/` | Home page with getting started guide |
214-
| `/todomvc` | TodoMVC example with ServiceStack APIs |
215-
| `/bookings-auto` | AutoQueryGrid with automatic columns |
173+
| Page | Description |
174+
|--------------------|-------------|
175+
| `/` | Home page with getting started guide |
176+
| `/todomvc` | TodoMVC example with ServiceStack APIs |
177+
| `/bookings-auto` | AutoQueryGrid with automatic columns |
216178
| `/bookings-custom` | Custom booking form with validation |
217-
| `/admin` | Protected admin page (requires Admin role) |
218-
| `/profile` | User profile management |
219-
| `/blog` | MDX blog listing |
220-
| `/shadcn-ui` | shadcn/ui component showcase |
221-
| `/about` | About page (MDX) |
222-
| `/privacy` | Privacy policy page (MDX) |
179+
| `/admin` | Protected admin page (requires Admin role) |
180+
| `/profile` | User profile management |
181+
| `/blog` | MDX blog listing |
182+
| `/shadcn-ui` | shadcn/ui component showcase |
183+
| `/about` | About page (MDX) |
184+
| `/privacy` | Privacy policy page (MDX) |
223185

224186
## Admin UIs
225187

@@ -233,6 +195,282 @@ Access built-in admin dashboards at:
233195
- `/admin-ui/apikeys` - API key management
234196
- `/admin-ui/chat` - AI chat analytics
235197

198+
### Project Structure
199+
200+
```
201+
MyApp/ # Main ASP.NET Core host
202+
├── Configure.*.cs # Modular startup configuration
203+
├── Program.cs # Application entry point
204+
└── wwwroot/ # Static files (production)
205+
206+
MyApp.Client/ # Vite React SPA frontend
207+
├── src/
208+
│ ├── pages/ # React Router pages
209+
│ ├── components/ # React components
210+
│ ├── lib/ # Utilities and helpers
211+
│ └── styles/ # Tailwind CSS styles
212+
├── public/ # Static assets
213+
├── dist/ # Build output (production)
214+
└── vite.config.ts # Vite configuration
215+
216+
MyApp.ServiceInterface/ # Service implementations
217+
├── MyServices.cs # Example services
218+
└── Data/ # EF Core DbContext
219+
220+
MyApp.ServiceModel/ # DTOs and service contracts
221+
├── Bookings.cs # AutoQuery CRUD example
222+
└── Hello.cs # Example service contract
223+
224+
MyApp.Tests/ # Integration and unit tests
225+
226+
config/ # Deployment configuration
227+
└── deploy.yml # Kamal deployment settings
228+
229+
.github/ # GitHub Actions workflows
230+
└── workflows/
231+
├── build.yml # CI build and test
232+
├── build-container.yml # Container image build
233+
└── release.yml # Production deployment with Kamal
234+
```
235+
236+
237+
## Development Workflow
238+
239+
### 1. Start Development
240+
241+
```bash
242+
dotnet watch
243+
```
244+
245+
This automatically starts both .NET and Vite dev servers.
246+
247+
### 2. Generate TypeScript DTOs
248+
249+
After modifying C# service models, regenerate TypeScript dtos.ts in `MyApp` or `MyApp.Client` with:
250+
251+
```bash
252+
npm run dtos
253+
```
254+
255+
### 3. Database Migrations
256+
257+
**OrmLite and Entity Framework:**
258+
259+
```bash
260+
npm run migrate
261+
```
262+
263+
**OrmLite (for application data):**
264+
265+
Create migration classes in `MyApp/Migrations/` following the pattern in `Migration1000.cs`.
266+
267+
### 4. Testing
268+
269+
**Frontend:**
270+
```bash
271+
cd MyApp.Client
272+
npm run test # Run tests in watch mode
273+
npm run test:ui # Run tests with UI
274+
npm run test:run # Run tests once
275+
```
276+
277+
## Configuration
278+
279+
### Key Configuration Files
280+
281+
- **MyApp/appsettings.json** - Application configuration
282+
- **MyApp.Client/next.config.mjs** - Next.js configuration
283+
- **MyApp.Client/styles/index.css** - Tailwind CSS configuration
284+
- **config/deploy.yml** - Kamal deployment settings
285+
286+
### App Settings
287+
288+
Configure in `appsettings.json` or environment:
289+
290+
```json
291+
{
292+
"ConnectionStrings": {
293+
"DefaultConnection": "DataSource=App_Data/app.db;Cache=Shared"
294+
},
295+
"SmtpConfig": {
296+
"Host": "smtp.example.com",
297+
"Port": 587,
298+
"FromEmail": "[email protected]",
299+
"FromName": "MyApp"
300+
},
301+
"AppConfig": {
302+
"BaseUrl": "https://myapp.example.com"
303+
}
304+
}
305+
```
306+
307+
### App Settings Secrets
308+
309+
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:
310+
311+
```json
312+
[
313+
{
314+
"op":"replace",
315+
"path":"/ConnectionStrings/DefaultConnection",
316+
"value":"Server=service-postgres;Port=5432;User Id=dbuser;Password=dbpass;Database=dbname;Pooling=true;"
317+
},
318+
{ "op":"add", "path":"/SmtpConfig", "value":{
319+
"UserName": "SmptUser",
320+
"Password": "SmptPass",
321+
"Host": "email-smtp.us-east-1.amazonaws.com",
322+
"Port": 587,
323+
"From": "[email protected]",
324+
"FromName": "MyApp",
325+
326+
}
327+
},
328+
{ "op":"add", "path":"/Admins", "value": ["[email protected]","[email protected]"] },
329+
{ "op":"add", "path":"/CorsFeature/allowOriginWhitelist/-", "value":"https://servicestack.net" }
330+
]
331+
```
332+
333+
### SMTP Email
334+
335+
Enable email sending by uncommenting in `Program.cs`:
336+
337+
```csharp
338+
services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>();
339+
```
340+
341+
## Upgrading to Enterprise Database
342+
343+
To switch from SQLite to PostgreSQL/SQL Server/MySQL:
344+
345+
1. Install preferred RDBMS (ef-postgres, ef-mysql, ef-sqlserver), e.g:
346+
347+
```bash
348+
npx add-in ef-postgres
349+
```
350+
351+
2. Install `db-identity` to use RDBMS `DatabaseJobsFeature` for background jobs and `DbRequestLogger` for Request Logs:
352+
353+
```bash
354+
npx add-in db-identity
355+
```
356+
357+
## Deployment
358+
359+
### Docker + Kamal
360+
361+
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.
362+
363+
### GitHub Action Secrets
364+
365+
**Required - App Specific*:
366+
367+
The only secret needed to be configured per Repository.
368+
369+
| Variable | Example | Description |
370+
|----------|---------|-------------|
371+
| `KAMAL_DEPLOY_HOST` | `example.org` | Hostname used for SSL certificate and Kamal proxy |
372+
373+
**Required** (Organization Secrets):
374+
375+
Other Required variables can be globally configured in your GitHub Organization or User secrets which will
376+
enable deploying all your Repositories to the same server.
377+
378+
| Variable | Example | Description |
379+
|----------|----------|-------------|
380+
| `KAMAL_DEPLOY_IP` | `100.100.100.100` | IP address of the server to deploy to |
381+
| `SSH_PRIVATE_KEY` | `ssh-rsa ...` | SSH private key to access the server |
382+
| `LETSENCRYPT_EMAIL` | `[email protected]` | Email for Let's Encrypt SSL certificate |
383+
384+
**Optional**:
385+
386+
| Variable | Example | Description |
387+
|----------|---------|-------------|
388+
| `SERVICESTACK_LICENSE` | `...` | ServiceStack license key |
389+
390+
**Inferred** (from GitHub Action context):
391+
392+
These are inferred from the GitHub Action context and don't need to be configured.
393+
394+
| Variable | Source | Description |
395+
|----------|--------|-------------|
396+
| `GITHUB_REPOSITORY` | `${{ github.repository }}` | e.g. `acme/example.org` - used for service name and image |
397+
| `KAMAL_REGISTRY_USERNAME` | `${{ github.actor }}` | GitHub username for container registry |
398+
| `KAMAL_REGISTRY_PASSWORD` | `${{ secrets.GITHUB_TOKEN }}` | GitHub token for container registry auth |
399+
400+
#### Features
401+
402+
- **Docker containerization** with optimized .NET images
403+
- **SSL auto-certification** via Let's Encrypt
404+
- **GitHub Container Registry** integration
405+
- **Volume persistence** for App_Data including any SQLite database
406+
407+
## AutoQuery CRUD Dev Workflow
408+
409+
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.
410+
411+
### Cheat Sheet
412+
413+
### Create a new Table
414+
415+
Create a new Table use `init <Table>`, e.g:
416+
417+
```bash
418+
npx okai init Table
419+
```
420+
421+
This will generate an empty `MyApp.ServiceModel/<Table>.d.ts` file along with stub AutoQuery APIs and DB Migration implementations.
422+
423+
### Use AI to generate the TypeScript Data Model
424+
425+
Or to get you started quickly you can also use AI to generate the initial TypeScript Data Model with:
426+
427+
```bash
428+
npx okai "Table to store Customer Stripe Subscriptions"
429+
```
430+
431+
This launches a TUI that invokes ServiceStack's okai API to fire multiple concurrent requests to frontier cloud
432+
and OSS models to generate the TypeScript Data Models required to implement this feature.
433+
You'll be able to browse and choose which of the AI Models you prefer which you can accept by pressing `a`
434+
to `(a) accept`. These are the data models [Claude Sonnet 4.5 generated](https://servicestack.net/text-to-blazor?id=1764337230546) generated for this prompt.
435+
436+
#### Regenerate AutoQuery APIs and DB Migrations
437+
438+
After modifying the `Table.d.ts` TypeScript Data Model to include the desired fields, re-run the `okai` tool to re-generate the AutoQuery APIs and DB Migrations:
439+
440+
```bash
441+
npx okai Table.d.ts
442+
```
443+
444+
> Command can be run anywhere within your Solution
445+
446+
After you're happy with your Data Model you can run DB Migrations to run the DB Migration and create your RDBMS Table:
447+
448+
```bash
449+
npm run migrate
450+
```
451+
452+
#### Making changes after first migration
453+
454+
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:
455+
456+
```bash
457+
npm run rerun:last
458+
```
459+
460+
#### Removing a Data Model and all generated code
461+
462+
If you changed your mind and want to get rid of the RDBMS Table you can revert the last migration:
463+
464+
```bash
465+
npm run revert:last
466+
```
467+
468+
Which will drop the table and then you can get rid of the AutoQuery APIs, DB Migrations and TypeScript Data model with:
469+
470+
```bash
471+
npx okai rm Transaction.d.ts
472+
```
473+
236474
## Learn More
237475

238476
- [react-templates.net](https://react-templates.net)

0 commit comments

Comments
 (0)