@polymorphism-tech/morph-spec 4.16.0 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CLAUDE.md +36 -0
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +3 -0
  4. package/bin/task-manager.js +999 -962
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +1 -1
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/agents/ai-agents/vector-search-expert.md +247 -233
  9. package/framework/agents/backend/ms-agent-expert.md +1 -1
  10. package/framework/agents/backend/neon-expert.md +379 -0
  11. package/framework/agents/frontend/gsap-animator.md +131 -0
  12. package/framework/agents/integrations/neon-auth.md +151 -0
  13. package/framework/agents.json +1183 -1085
  14. package/framework/commands/morph-preflight.md +200 -192
  15. package/framework/hooks/claude-code/session-start/inject-morph-context.js +1 -1
  16. package/framework/rules/gsap-standards.md +13 -0
  17. package/framework/rules/neon-auth-standards.md +13 -0
  18. package/framework/rules/neon-standards.md +26 -0
  19. package/framework/skills/level-0-meta/mcp-registry.json +1 -1
  20. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +472 -472
  21. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -1
  22. package/framework/skills/level-0-meta/morph-init/SKILL.md +12 -12
  23. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +5 -5
  24. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +5 -5
  25. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +7 -7
  26. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +24 -24
  27. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +12 -12
  28. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +9 -9
  29. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  30. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  31. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -143
  32. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
  33. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  34. package/framework/standards/STANDARDS.json +197 -116
  35. package/framework/standards/ai-agents/production.md +1 -0
  36. package/framework/standards/ai-agents/setup.md +3 -2
  37. package/framework/standards/ai-agents/workflows.md +1 -0
  38. package/framework/standards/architecture/vertical-slice/vertical-slice.md +4 -4
  39. package/framework/standards/backend/database/postgresql/database.md +63 -83
  40. package/framework/standards/backend/dotnet/scalar-ui.md +172 -172
  41. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -274
  42. package/framework/standards/backend/integrations/asaas/asaas-api.md +2 -2
  43. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +364 -0
  44. package/framework/standards/frontend/design-system/animations.md +9 -0
  45. package/framework/standards/frontend/gsap/gsap-core.md +463 -0
  46. package/framework/standards/frontend/gsap/gsap-plugins.md +294 -0
  47. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +318 -0
  48. package/framework/standards/frontend/nextjs/motion-patterns.md +1 -0
  49. package/framework/standards/frontend/nextjs/nextjs-patterns.md +47 -37
  50. package/framework/standards/infrastructure/docker/easypanel-deploy.md +4 -8
  51. package/framework/standards/infrastructure/neon/neon-pgrag.md +239 -0
  52. package/framework/standards/infrastructure/neon/neon-pgvector.md +236 -0
  53. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +310 -0
  54. package/framework/standards/infrastructure/neon/neon-setup.md +186 -0
  55. package/framework/standards/integration/mcp/mcp-tools.md +32 -34
  56. package/framework/templates/README.md +20 -20
  57. package/framework/templates/REGISTRY.json +54 -101
  58. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  59. package/framework/templates/code/dotnet/backend/repository.cs +148 -148
  60. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  61. package/framework/templates/code/dotnet/database/vector-entity.cs +93 -0
  62. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +1 -1
  63. package/framework/templates/code/sql/{supabase-migration.sql → postgresql-migration.sql} +12 -21
  64. package/framework/templates/code/sql/{supabase-migration.template.sql → postgresql-migration.template.sql} +13 -18
  65. package/framework/templates/code/sql/{rls-policy.sql → postgresql-rls-policy.sql} +6 -9
  66. package/framework/templates/code/typescript/contracts.ts +167 -168
  67. package/framework/templates/context/CONTEXT.md +3 -3
  68. package/framework/templates/docs/proposal.md +6 -6
  69. package/framework/templates/docs/ui-components.md +1 -1
  70. package/framework/templates/feature/decisions.md +122 -121
  71. package/framework/templates/feature/recap.md +145 -145
  72. package/framework/templates/feature/tasks.md +199 -199
  73. package/framework/templates/frontend/nextjs/gsap-scroll-section.tsx.hbs +44 -0
  74. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -67
  75. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  76. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  77. package/framework/templates/infrastructure/docker/easypanel.template.json +46 -54
  78. package/framework/templates/infrastructure/github/README.md +56 -56
  79. package/framework/templates/integrations/neon-auth-config.cs +133 -0
  80. package/framework/templates/integrations/semantic-kernel-neon.cs +125 -0
  81. package/framework/workflows/README.md +1 -1
  82. package/framework/workflows/docs/full-morph.md +69 -69
  83. package/package.json +1 -1
  84. package/src/commands/agents/dispatch-agents.js +19 -15
  85. package/src/commands/state/advance-phase.js +5 -0
  86. package/src/commands/tasks/task.js +3 -0
  87. package/src/core/state/state-manager.js +45 -1
  88. package/src/core/templates/template-registry.js +1 -66
  89. package/src/lib/detectors/index.js +4 -4
  90. package/src/lib/generators/architecture-scanner.js +639 -640
  91. package/src/lib/installers/mcp-installer.js +1 -1
  92. package/src/lib/tasks/task-classifier.js +15 -1
  93. package/src/lib/tasks/test-runner.js +5 -1
  94. package/src/lib/validators/content/content-validator.js +9 -10
  95. package/src/lib/validators/validation-runner.js +7 -5
  96. package/framework/agents/backend/supabase-expert.md +0 -256
  97. package/framework/agents/integrations/clerk-auth.md +0 -109
  98. package/framework/rules/clerk-standards.md +0 -13
  99. package/framework/rules/supabase-standards.md +0 -29
  100. package/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
  101. package/framework/standards/infrastructure/supabase/mcp-setup.md +0 -142
  102. package/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  103. package/framework/standards/infrastructure/supabase/supabase-custom-jwt.md +0 -206
  104. package/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  105. package/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  106. package/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
  107. package/framework/templates/integrations/clerk-config.cs +0 -217
@@ -1,11 +1,11 @@
1
- # Supabase Database Standards
1
+ # Neon PostgreSQL Database Standards
2
2
 
3
- > **Scope:** nextjs-supabase
3
+ > **Scope:** nextjs-neon
4
4
  > **Layer:** 2 (on keyword)
5
- > **Keywords:** postgresql, postgres, sql, supabase, database schema
6
- > **Load When:** supabase or postgresql keywords detected
5
+ > **Keywords:** postgresql, postgres, sql, neon, database schema
6
+ > **Load When:** neon or postgresql keywords detected
7
7
 
8
- Database schema design, migrations, and Row Level Security (RLS) patterns for Supabase.
8
+ Database schema design, migrations, and Row Level Security (RLS) patterns for Neon PostgreSQL.
9
9
 
10
10
  ---
11
11
 
@@ -68,7 +68,7 @@ alter table public.profiles enable row level security;
68
68
  ```sql
69
69
  create policy "Users can view own profile"
70
70
  on public.profiles for select
71
- using (auth.uid() = user_id);
71
+ using (auth.user_id() = user_id);
72
72
  ```
73
73
 
74
74
  #### User can update own profile
@@ -76,8 +76,8 @@ create policy "Users can view own profile"
76
76
  ```sql
77
77
  create policy "Users can update own profile"
78
78
  on public.profiles for update
79
- using (auth.uid() = user_id)
80
- with check (auth.uid() = user_id);
79
+ using (auth.user_id() = user_id)
80
+ with check (auth.user_id() = user_id);
81
81
  ```
82
82
 
83
83
  #### User can insert own profile
@@ -85,7 +85,7 @@ create policy "Users can update own profile"
85
85
  ```sql
86
86
  create policy "Users can insert own profile"
87
87
  on public.profiles for insert
88
- with check (auth.uid() = user_id);
88
+ with check (auth.user_id() = user_id);
89
89
  ```
90
90
 
91
91
  #### Admin can do anything
@@ -96,7 +96,7 @@ create policy "Admins have full access"
96
96
  using (
97
97
  exists (
98
98
  select 1 from public.user_roles
99
- where user_id = auth.uid() and role = 'admin'
99
+ where user_id = auth.user_id() and role = 'admin'
100
100
  )
101
101
  );
102
102
  ```
@@ -113,16 +113,20 @@ create policy "Public profiles are viewable by everyone"
113
113
 
114
114
  ## Migrations
115
115
 
116
- ### Migration File Naming
116
+ ### Migration Management (EF Core)
117
117
 
118
- ```
119
- supabase/migrations/
120
- 20240101000000_create_users_table.sql
121
- 20240102000000_add_user_roles.sql
122
- 20240103000000_enable_rls_users.sql
118
+ ```bash
119
+ # Create a new migration
120
+ dotnet ef migrations add CreateUsersTable
121
+
122
+ # Apply migrations to Neon database
123
+ dotnet ef database update
124
+
125
+ # Generate SQL script for review
126
+ dotnet ef migrations script --idempotent
123
127
  ```
124
128
 
125
- ### Migration Template
129
+ ### Migration Template (SQL for manual migrations)
126
130
 
127
131
  ```sql
128
132
  -- Create table
@@ -250,89 +254,65 @@ create trigger users_soft_delete
250
254
 
251
255
  ---
252
256
 
253
- ## Supabase Client Queries
257
+ ## Database Queries (EF Core / SQL)
254
258
 
255
- ### Select
259
+ ### Select (EF Core)
256
260
 
257
- ```typescript
258
- const { data, error } = await supabase
259
- .from('users')
260
- .select('id, name, email')
261
- .eq('is_active', true)
262
- .order('created_at', { ascending: false })
263
- .limit(10)
261
+ ```csharp
262
+ var users = await db.Users
263
+ .Where(u => u.IsActive)
264
+ .OrderByDescending(u => u.CreatedAt)
265
+ .Take(10)
266
+ .Select(u => new { u.Id, u.Name, u.Email })
267
+ .ToListAsync(ct);
264
268
  ```
265
269
 
266
- ### Insert
270
+ ### Insert (EF Core)
267
271
 
268
- ```typescript
269
- const { data, error } = await supabase
270
- .from('users')
271
- .insert({ name: 'John', email: 'john@example.com' })
272
- .select()
273
- .single()
272
+ ```csharp
273
+ var user = new User { Name = "John", Email = "john@example.com" };
274
+ db.Users.Add(user);
275
+ await db.SaveChangesAsync(ct);
274
276
  ```
275
277
 
276
- ### Update
278
+ ### Update (EF Core)
277
279
 
278
- ```typescript
279
- const { data, error } = await supabase
280
- .from('users')
281
- .update({ name: 'John Doe' })
282
- .eq('id', userId)
283
- .select()
284
- .single()
280
+ ```csharp
281
+ var user = await db.Users.FindAsync([userId], ct);
282
+ if (user is not null)
283
+ {
284
+ user.Name = "John Doe";
285
+ await db.SaveChangesAsync(ct);
286
+ }
285
287
  ```
286
288
 
287
- ### Delete
289
+ ### Delete (EF Core)
288
290
 
289
- ```typescript
290
- const { error } = await supabase
291
- .from('users')
292
- .delete()
293
- .eq('id', userId)
291
+ ```csharp
292
+ await db.Users.Where(u => u.Id == userId).ExecuteDeleteAsync(ct);
294
293
  ```
295
294
 
296
- ### Joins (Foreign Tables)
295
+ ### Joins (Navigation Properties)
297
296
 
298
- ```typescript
299
- const { data } = await supabase
300
- .from('posts')
301
- .select(`
302
- id,
303
- title,
304
- author:users (
305
- id,
306
- name,
307
- avatar_url
308
- )
309
- `)
297
+ ```csharp
298
+ var posts = await db.Posts
299
+ .Include(p => p.Author)
300
+ .Select(p => new
301
+ {
302
+ p.Id,
303
+ p.Title,
304
+ Author = new { p.Author.Id, p.Author.Name, p.Author.AvatarUrl }
305
+ })
306
+ .ToListAsync(ct);
310
307
  ```
311
308
 
312
- ---
313
-
314
- ## Realtime Subscriptions
315
-
316
- ### Listen to Changes
309
+ ### Direct SQL via Npgsql (Next.js / serverless)
317
310
 
318
311
  ```typescript
319
- const channel = supabase
320
- .channel('posts-changes')
321
- .on(
322
- 'postgres_changes',
323
- {
324
- event: '*', // or 'INSERT', 'UPDATE', 'DELETE'
325
- schema: 'public',
326
- table: 'posts'
327
- },
328
- (payload) => {
329
- console.log('Change received!', payload)
330
- }
331
- )
332
- .subscribe()
333
-
334
- // Cleanup
335
- supabase.removeChannel(channel)
312
+ import { neon } from '@neondatabase/serverless';
313
+
314
+ const sql = neon(process.env.DATABASE_URL!);
315
+ const users = await sql`SELECT id, name, email FROM users WHERE is_active = true ORDER BY created_at DESC LIMIT 10`;
336
316
  ```
337
317
 
338
318
  ---
@@ -349,4 +329,4 @@ supabase.removeChannel(channel)
349
329
 
350
330
  ---
351
331
 
352
- *Supabase Database Standards - MORPH-SPEC by Polymorphism Tech*
332
+ *Neon PostgreSQL Database Standards - MORPH-SPEC by Polymorphism Tech*
@@ -1,172 +1,172 @@
1
- # Scalar.AspNetCore — API Documentation UI
2
-
3
- > **Scope:** dotnet-vsa
4
- > **Layer:** 0 (always load)
5
- > **Keywords:** scalar, openapi, swagger, api-docs, documentation
6
- > **Load When:** dotnet VSA projects
7
-
8
- ## Overview
9
-
10
- Scalar replaces Swagger UI as the API documentation frontend. It provides a modern UI with built-in request testing, client code generation, and dark themes. Works with ASP.NET Core's native OpenAPI support (`Microsoft.AspNetCore.OpenApi`).
11
-
12
- ---
13
-
14
- ## Package Setup
15
-
16
- ```xml
17
- <!-- .csproj -->
18
- <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
19
- <PackageReference Include="Scalar.AspNetCore" Version="2.12.40" />
20
- ```
21
-
22
- No Swashbuckle needed. ASP.NET Core 9+ has built-in OpenAPI document generation.
23
-
24
- ---
25
-
26
- ## Program.cs Configuration
27
-
28
- ```csharp
29
- using Scalar.AspNetCore;
30
-
31
- var builder = WebApplication.CreateBuilder(args);
32
-
33
- // Enable OpenAPI document generation
34
- builder.Services.AddOpenApi();
35
-
36
- var app = builder.Build();
37
-
38
- // Map the OpenAPI JSON endpoint (dev only)
39
- if (app.Environment.IsDevelopment())
40
- {
41
- app.MapOpenApi();
42
- }
43
-
44
- // Map Scalar UI at /scalar/v1
45
- app.MapScalarApiReference(options =>
46
- {
47
- options.WithTheme(ScalarTheme.DeepSpace);
48
-
49
- // Enable Developer Tools (request + client code panel)
50
- options.WithDefaultHttpClient(
51
- ScalarTarget.CSharp,
52
- ScalarClient.HttpClient);
53
- });
54
- ```
55
-
56
- **Access URL:** `https://localhost:{port}/scalar/v1`
57
-
58
- ---
59
-
60
- ## Available Themes
61
-
62
- | Theme | Description |
63
- |-------|-------------|
64
- | `ScalarTheme.Default` | Light theme |
65
- | `ScalarTheme.DeepSpace` | Dark blue (recommended) |
66
- | `ScalarTheme.Purple` | Purple accent |
67
- | `ScalarTheme.Moon` | Dark grey |
68
- | `ScalarTheme.Saturn` | Warm dark |
69
- | `ScalarTheme.Mars` | Red accent |
70
-
71
- ---
72
-
73
- ## ApiTags Organization
74
-
75
- Group endpoints by feature using a constants class and `.WithTags()`:
76
-
77
- ```csharp
78
- // Constants/ApiTags.cs
79
- public static class ApiTags
80
- {
81
- public const string Books = "books";
82
- public const string Authors = "authors";
83
- public const string Orders = "orders";
84
- }
85
- ```
86
-
87
- Apply tags in endpoints:
88
-
89
- ```csharp
90
- internal sealed class CreateBookEndpoint : IApiEndpoint
91
- {
92
- public void MapEndpoint(WebApplication app)
93
- {
94
- app.MapPost("books", async (
95
- IHandler<CreateBookRequest, Result<CreateBookResponse>> handler,
96
- CreateBookRequest command,
97
- CancellationToken cancellationToken) =>
98
- {
99
- var result = await handler.HandleAsync(command, cancellationToken);
100
- return result.Match(
101
- onSuccess: () => Results.Ok(result.Value),
102
- onFailure: error => Results.BadRequest(error));
103
- })
104
- .WithTags(ApiTags.Books)
105
- .Produces<CreateBookResponse>(StatusCodes.Status200OK)
106
- .Produces(StatusCodes.Status400BadRequest);
107
- }
108
- }
109
- ```
110
-
111
- ---
112
-
113
- ## Endpoint Metadata
114
-
115
- Use `.Produces<T>()` to document response types for OpenAPI:
116
-
117
- ```csharp
118
- app.MapGet("books/{id:guid}", async (...) => { ... })
119
- .WithTags(ApiTags.Books)
120
- .WithName("GetBookById")
121
- .WithSummary("Get a book by its unique identifier")
122
- .Produces<GetBookResponse>(StatusCodes.Status200OK)
123
- .Produces(StatusCodes.Status404NotFound);
124
-
125
- app.MapDelete("books/{id:guid}", async (...) => { ... })
126
- .WithTags(ApiTags.Books)
127
- .Produces(StatusCodes.Status204NoContent)
128
- .Produces(StatusCodes.Status404NotFound);
129
- ```
130
-
131
- ### Common Metadata Methods
132
-
133
- | Method | Purpose |
134
- |--------|---------|
135
- | `.WithTags("tag")` | Group in Scalar sidebar |
136
- | `.WithName("OperationId")` | Unique operation identifier |
137
- | `.WithSummary("...")` | Short description in endpoint list |
138
- | `.WithDescription("...")` | Long description in detail panel |
139
- | `.Produces<T>(statusCode)` | Document success response type |
140
- | `.Produces(statusCode)` | Document error response (no body) |
141
- | `.ProducesProblem(statusCode)` | Document ProblemDetails response |
142
- | `.RequireAuthorization()` | Marks as requiring auth in docs |
143
-
144
- ---
145
-
146
- ## Client Code Generation
147
-
148
- Scalar auto-generates client code for API calls. The `WithDefaultHttpClient` option selects the default language:
149
-
150
- | Target | Client | Description |
151
- |--------|--------|-------------|
152
- | `ScalarTarget.CSharp` | `ScalarClient.HttpClient` | .NET HttpClient |
153
- | `ScalarTarget.JavaScript` | `ScalarClient.Fetch` | Browser fetch() |
154
- | `ScalarTarget.Python` | `ScalarClient.Requests` | Python requests |
155
- | `ScalarTarget.Shell` | `ScalarClient.Curl` | cURL command |
156
-
157
- ---
158
-
159
- ## Anti-Patterns
160
-
161
- | Do NOT | Do Instead |
162
- |--------|------------|
163
- | Install Swashbuckle | Use `Microsoft.AspNetCore.OpenApi` + `Scalar.AspNetCore` |
164
- | Expose OpenAPI in production | Guard with `IsDevelopment()` check |
165
- | Skip `.WithTags()` on endpoints | Every endpoint needs a tag for organized docs |
166
- | Skip `.Produces<T>()` | Always document response types for accurate API docs |
167
- | Use magic strings for tags | Define tags in `Constants/ApiTags.cs` |
168
- | Map Scalar before `MapOpenApi()` | `MapOpenApi()` first, then `MapScalarApiReference()` |
169
-
170
- ---
171
-
172
- *MORPH-SPEC by Polymorphism Tech*
1
+ # Scalar.AspNetCore — API Documentation UI
2
+
3
+ > **Scope:** dotnet-vsa
4
+ > **Layer:** 0 (always load)
5
+ > **Keywords:** scalar, openapi, swagger, api-docs, documentation
6
+ > **Load When:** dotnet VSA projects
7
+
8
+ ## Overview
9
+
10
+ Scalar replaces Swagger UI as the API documentation frontend. It provides a modern UI with built-in request testing, client code generation, and dark themes. Works with ASP.NET Core's native OpenAPI support (`Microsoft.AspNetCore.OpenApi`).
11
+
12
+ ---
13
+
14
+ ## Package Setup
15
+
16
+ ```xml
17
+ <!-- .csproj -->
18
+ <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
19
+ <PackageReference Include="Scalar.AspNetCore" Version="2.12.40" />
20
+ ```
21
+
22
+ No Swashbuckle needed. ASP.NET Core 9+ has built-in OpenAPI document generation.
23
+
24
+ ---
25
+
26
+ ## Program.cs Configuration
27
+
28
+ ```csharp
29
+ using Scalar.AspNetCore;
30
+
31
+ var builder = WebApplication.CreateBuilder(args);
32
+
33
+ // Enable OpenAPI document generation
34
+ builder.Services.AddOpenApi();
35
+
36
+ var app = builder.Build();
37
+
38
+ // Map the OpenAPI JSON endpoint (dev only)
39
+ if (app.Environment.IsDevelopment())
40
+ {
41
+ app.MapOpenApi();
42
+ }
43
+
44
+ // Map Scalar UI at /scalar/v1
45
+ app.MapScalarApiReference(options =>
46
+ {
47
+ options.WithTheme(ScalarTheme.DeepSpace);
48
+
49
+ // Enable Developer Tools (request + client code panel)
50
+ options.WithDefaultHttpClient(
51
+ ScalarTarget.CSharp,
52
+ ScalarClient.HttpClient);
53
+ });
54
+ ```
55
+
56
+ **Access URL:** `https://localhost:{port}/scalar/v1`
57
+
58
+ ---
59
+
60
+ ## Available Themes
61
+
62
+ | Theme | Description |
63
+ |-------|-------------|
64
+ | `ScalarTheme.Default` | Light theme |
65
+ | `ScalarTheme.DeepSpace` | Dark blue (recommended) |
66
+ | `ScalarTheme.Purple` | Purple accent |
67
+ | `ScalarTheme.Moon` | Dark grey |
68
+ | `ScalarTheme.Saturn` | Warm dark |
69
+ | `ScalarTheme.Mars` | Red accent |
70
+
71
+ ---
72
+
73
+ ## ApiTags Organization
74
+
75
+ Group endpoints by feature using a constants class and `.WithTags()`:
76
+
77
+ ```csharp
78
+ // Constants/ApiTags.cs
79
+ public static class ApiTags
80
+ {
81
+ public const string Books = "books";
82
+ public const string Authors = "authors";
83
+ public const string Orders = "orders";
84
+ }
85
+ ```
86
+
87
+ Apply tags in endpoints:
88
+
89
+ ```csharp
90
+ internal sealed class CreateBookEndpoint : IApiEndpoint
91
+ {
92
+ public void MapEndpoint(IEndpointRouteBuilder app)
93
+ {
94
+ app.MapPost("books", async (
95
+ IHandler<CreateBookRequest, Result<CreateBookResponse>> handler,
96
+ CreateBookRequest command,
97
+ CancellationToken cancellationToken) =>
98
+ {
99
+ var result = await handler.HandleAsync(command, cancellationToken);
100
+ return result.Match(
101
+ onSuccess: () => Results.Ok(result.Value),
102
+ onFailure: error => Results.BadRequest(error));
103
+ })
104
+ .WithTags(ApiTags.Books)
105
+ .Produces<CreateBookResponse>(StatusCodes.Status200OK)
106
+ .Produces(StatusCodes.Status400BadRequest);
107
+ }
108
+ }
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Endpoint Metadata
114
+
115
+ Use `.Produces<T>()` to document response types for OpenAPI:
116
+
117
+ ```csharp
118
+ app.MapGet("books/{id:guid}", async (...) => { ... })
119
+ .WithTags(ApiTags.Books)
120
+ .WithName("GetBookById")
121
+ .WithSummary("Get a book by its unique identifier")
122
+ .Produces<GetBookResponse>(StatusCodes.Status200OK)
123
+ .Produces(StatusCodes.Status404NotFound);
124
+
125
+ app.MapDelete("books/{id:guid}", async (...) => { ... })
126
+ .WithTags(ApiTags.Books)
127
+ .Produces(StatusCodes.Status204NoContent)
128
+ .Produces(StatusCodes.Status404NotFound);
129
+ ```
130
+
131
+ ### Common Metadata Methods
132
+
133
+ | Method | Purpose |
134
+ |--------|---------|
135
+ | `.WithTags("tag")` | Group in Scalar sidebar |
136
+ | `.WithName("OperationId")` | Unique operation identifier |
137
+ | `.WithSummary("...")` | Short description in endpoint list |
138
+ | `.WithDescription("...")` | Long description in detail panel |
139
+ | `.Produces<T>(statusCode)` | Document success response type |
140
+ | `.Produces(statusCode)` | Document error response (no body) |
141
+ | `.ProducesProblem(statusCode)` | Document ProblemDetails response |
142
+ | `.RequireAuthorization()` | Marks as requiring auth in docs |
143
+
144
+ ---
145
+
146
+ ## Client Code Generation
147
+
148
+ Scalar auto-generates client code for API calls. The `WithDefaultHttpClient` option selects the default language:
149
+
150
+ | Target | Client | Description |
151
+ |--------|--------|-------------|
152
+ | `ScalarTarget.CSharp` | `ScalarClient.HttpClient` | .NET HttpClient |
153
+ | `ScalarTarget.JavaScript` | `ScalarClient.Fetch` | Browser fetch() |
154
+ | `ScalarTarget.Python` | `ScalarClient.Requests` | Python requests |
155
+ | `ScalarTarget.Shell` | `ScalarClient.Curl` | cURL command |
156
+
157
+ ---
158
+
159
+ ## Anti-Patterns
160
+
161
+ | Do NOT | Do Instead |
162
+ |--------|------------|
163
+ | Install Swashbuckle | Use `Microsoft.AspNetCore.OpenApi` + `Scalar.AspNetCore` |
164
+ | Expose OpenAPI in production | Guard with `IsDevelopment()` check |
165
+ | Skip `.WithTags()` on endpoints | Every endpoint needs a tag for organized docs |
166
+ | Skip `.Produces<T>()` | Always document response types for accurate API docs |
167
+ | Use magic strings for tags | Define tags in `Constants/ApiTags.cs` |
168
+ | Map Scalar before `MapOpenApi()` | `MapOpenApi()` first, then `MapScalarApiReference()` |
169
+
170
+ ---
171
+
172
+ *MORPH-SPEC by Polymorphism Tech*