@polymorphism-tech/morph-spec 2.3.0 → 3.0.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.
- package/CLAUDE.md +446 -1730
- package/README.md +515 -516
- package/bin/morph-spec.js +366 -294
- package/bin/task-manager.js +429 -368
- package/bin/validate.js +369 -268
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-deploy.md +529 -0
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/skills/infra/azure-deploy-specialist.md +699 -0
- package/content/.claude/skills/level-0-meta/README.md +7 -0
- package/content/.claude/skills/level-0-meta/code-review.md +226 -0
- package/content/.claude/skills/level-0-meta/morph-checklist.md +117 -0
- package/content/.claude/skills/level-0-meta/simulation-checklist.md +77 -0
- package/content/.claude/skills/level-1-workflows/README.md +7 -0
- package/content/.claude/skills/level-1-workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/level-1-workflows/phase-clarify.md} +131 -184
- package/content/.claude/{commands/morph-design.md → skills/level-1-workflows/phase-design.md} +213 -275
- package/content/.claude/skills/level-1-workflows/phase-setup.md +106 -0
- package/content/.claude/skills/level-1-workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/level-1-workflows/phase-uiux.md} +169 -211
- package/content/.claude/skills/level-2-domains/README.md +14 -0
- package/content/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +192 -0
- package/content/.claude/skills/{specialists → level-2-domains/architecture}/po-pm-advisor.md +197 -197
- package/content/.claude/skills/level-2-domains/architecture/standards-architect.md +156 -0
- package/content/.claude/skills/level-2-domains/backend/dotnet-senior.md +287 -0
- package/content/.claude/skills/level-2-domains/backend/ef-modeler.md +113 -0
- package/content/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +126 -0
- package/content/.claude/skills/level-2-domains/backend/ms-agent-expert.md +109 -0
- package/content/.claude/skills/level-2-domains/frontend/blazor-builder.md +210 -0
- package/content/.claude/skills/level-2-domains/frontend/nextjs-expert.md +154 -0
- package/content/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +191 -0
- package/content/.claude/skills/{specialists → level-2-domains/infrastructure}/azure-architect.md +142 -142
- package/content/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +126 -0
- package/content/.claude/skills/level-2-domains/infrastructure/container-specialist.md +131 -0
- package/content/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +119 -0
- package/content/.claude/skills/level-2-domains/integrations/asaas-financial.md +130 -0
- package/content/.claude/skills/level-2-domains/integrations/azure-identity.md +142 -0
- package/content/.claude/skills/level-2-domains/integrations/clerk-auth.md +108 -0
- package/content/.claude/skills/level-2-domains/integrations/resend-email.md +119 -0
- package/content/.claude/skills/level-2-domains/quality/code-analyzer.md +235 -0
- package/content/.claude/skills/level-2-domains/quality/testing-specialist.md +126 -0
- package/content/.claude/skills/level-3-technologies/README.md +7 -0
- package/content/.claude/skills/level-4-patterns/README.md +7 -0
- package/content/.claude/skills/specialists/prompt-engineer.md +189 -0
- package/content/.claude/skills/specialists/seo-growth-hacker.md +320 -0
- package/content/.morph/config/agents.json +762 -242
- package/content/.morph/config/config.template.json +122 -108
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/enforcement-pipeline.md +668 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/hooks/README.md +348 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/task-completed.js +73 -0
- package/content/.morph/hooks/teammate-idle.js +68 -0
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/agent-teams-workflow.md +474 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/templates/CONTEXT-FEATURE.md +276 -0
- package/content/.morph/templates/CONTEXT.md +170 -0
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/infra/azure-pipelines-deploy.yml +480 -0
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/CLAUDE.md +150 -442
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/src/commands/advance-phase.js +266 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/deploy.js +780 -0
- package/src/commands/detect-agents.js +167 -0
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate-context.js +40 -0
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/task.js +78 -75
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/context-generator.js +513 -0
- package/src/lib/continuous-validator.js +421 -440
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-detector.js +187 -0
- package/src/lib/design-system-scaffolder.js +299 -0
- package/src/lib/hook-executor.js +256 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/spec-validator.js +258 -0
- package/src/lib/standards-context-injector.js +287 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/team-orchestrator.js +322 -0
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/validation-runner.js +283 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/design-system-validator.js +231 -0
- package/src/utils/file-copier.js +187 -139
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-setup.md +0 -100
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/infra/bicep-architect.md +0 -419
- package/content/.claude/skills/infra/container-specialist.md +0 -437
- package/content/.claude/skills/infra/devops-engineer.md +0 -405
- package/content/.claude/skills/integrations/asaas-financial.md +0 -333
- package/content/.claude/skills/integrations/azure-identity.md +0 -309
- package/content/.claude/skills/integrations/clerk-auth.md +0 -290
- package/content/.claude/skills/specialists/ai-system-architect.md +0 -604
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/specialists/ef-modeler.md +0 -211
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +0 -255
- package/content/.claude/skills/specialists/ms-agent-expert.md +0 -263
- package/content/.claude/skills/specialists/standards-architect.md +0 -78
- package/content/.claude/skills/specialists/ui-ux-designer.md +0 -1100
- package/content/.claude/skills/stacks/dotnet-blazor.md +0 -606
- package/content/.claude/skills/stacks/dotnet-nextjs.md +0 -402
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Agent Framework Expert
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** agent, ai, llm, openai, chat, prompt, tool, function calling, rag, embedding, workflow, orchestration, mcp, a2a, middleware
|
|
4
|
+
|
|
5
|
+
Microsoft Agent Framework for .NET 10. **Replaces Semantic Kernel.** Packages: `Microsoft.Agents.AI`, `Microsoft.Agents.AI.OpenAI`, `Microsoft.Agents.AI.Hosting`.
|
|
6
|
+
|
|
7
|
+
> **Ref:** `agent-framework-setup.md` — Full setup guide
|
|
8
|
+
> **Ref:** `agent-framework-workflows.md` — Orchestration patterns
|
|
9
|
+
> **Ref:** `agent-framework-production.md` — Middleware, A2A, MCP, caching
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```csharp
|
|
14
|
+
AIAgent agent = new AzureOpenAIClient(
|
|
15
|
+
new Uri(endpoint), new AzureCliCredential())
|
|
16
|
+
.GetChatClient("gpt-4o-mini")
|
|
17
|
+
.AsAIAgent(instructions: "You are a helpful assistant.");
|
|
18
|
+
|
|
19
|
+
Console.WriteLine(await agent.RunAsync("Analyze this."));
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Agent with Tools
|
|
23
|
+
|
|
24
|
+
```csharp
|
|
25
|
+
public class OrderFunctions
|
|
26
|
+
{
|
|
27
|
+
private readonly IOrderService _orderService;
|
|
28
|
+
|
|
29
|
+
public OrderFunctions(IOrderService orderService) => _orderService = orderService;
|
|
30
|
+
|
|
31
|
+
[Description("Get order by number")]
|
|
32
|
+
public async Task<Order?> GetOrderAsync(
|
|
33
|
+
[Description("Order number")] string orderNumber, CancellationToken ct = default)
|
|
34
|
+
=> await _orderService.GetByNumberAsync(orderNumber, ct);
|
|
35
|
+
|
|
36
|
+
[Description("Calculate customer discount")]
|
|
37
|
+
public decimal CalculateDiscount(
|
|
38
|
+
[Description("Customer ID")] int customerId,
|
|
39
|
+
[Description("Order total")] decimal orderTotal) => orderTotal * 0.1m;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Register agent with tools via DI
|
|
43
|
+
builder.AddAIAgent("OrderAgent", (sp, key) =>
|
|
44
|
+
{
|
|
45
|
+
var chatClient = sp.GetRequiredService<IChatClient>();
|
|
46
|
+
var orderFunctions = sp.GetRequiredService<OrderFunctions>();
|
|
47
|
+
|
|
48
|
+
return new ChatClientAgent(chatClient, name: key,
|
|
49
|
+
instructions: "You are an order assistant. Use tools to help users.",
|
|
50
|
+
tools: [
|
|
51
|
+
AIFunctionFactory.Create(orderFunctions.GetOrderAsync),
|
|
52
|
+
AIFunctionFactory.Create(orderFunctions.CalculateDiscount)]);
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Workflow (Sequential)
|
|
57
|
+
|
|
58
|
+
```csharp
|
|
59
|
+
Workflow workflow = AgentWorkflowBuilder.BuildSequential(writer, editor);
|
|
60
|
+
AIAgent workflowAgent = await workflow.AsAgentAsync();
|
|
61
|
+
var response = await workflowAgent.RunAsync("Write a report.");
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Middleware (Error Handling)
|
|
65
|
+
|
|
66
|
+
```csharp
|
|
67
|
+
var agent = originalAgent.AsBuilder()
|
|
68
|
+
.Use(async (agent, context, next, ct) =>
|
|
69
|
+
{
|
|
70
|
+
try { return await next(context, ct); }
|
|
71
|
+
catch (Exception ex) { return $"Error: {ex.Message}"; }
|
|
72
|
+
})
|
|
73
|
+
.Build();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Prompt Template
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
# Identity: You are {AgentName}, expert in {Domain}.
|
|
80
|
+
# Context: {ContextDescription}
|
|
81
|
+
# Rules: {BulletList}
|
|
82
|
+
# Response Format: {Format}
|
|
83
|
+
# Examples: Input: {In} → Output: {Out}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Model Selection
|
|
87
|
+
|
|
88
|
+
| Use Case | Model | Cost |
|
|
89
|
+
|----------|-------|------|
|
|
90
|
+
| Simple tasks (default) | gpt-4o-mini | $0.15/1M input |
|
|
91
|
+
| Complex analysis | gpt-4o | $2.50/1M input |
|
|
92
|
+
| Embeddings | text-embedding-3-small | $0.02/1M |
|
|
93
|
+
|
|
94
|
+
## Checklist
|
|
95
|
+
|
|
96
|
+
- [ ] `Microsoft.Agents.AI` + `Microsoft.Agents.AI.OpenAI` installed
|
|
97
|
+
- [ ] `IChatClient` configured via DI (singleton)
|
|
98
|
+
- [ ] Agents use `ChatClientAgent` or `.AsAIAgent()`
|
|
99
|
+
- [ ] Agents registered with `builder.AddAIAgent()` (keyed services)
|
|
100
|
+
- [ ] Tools use `AIFunctionFactory.Create()` + `[Description]`
|
|
101
|
+
- [ ] Middleware for error handling and logging
|
|
102
|
+
- [ ] gpt-4o-mini as default model
|
|
103
|
+
- [ ] API keys in Key Vault
|
|
104
|
+
- [ ] OpenTelemetry enabled: `agent.WithOpenTelemetry()`
|
|
105
|
+
- [ ] **Do NOT use Semantic Kernel** (`Kernel`, `KernelFunction`, `InvokePromptAsync`)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# .NET + Blazor Stack
|
|
2
|
+
|
|
3
|
+
Stack principal para aplicações web com .NET e Blazor Server.
|
|
4
|
+
|
|
5
|
+
| Aspecto | Tecnologia |
|
|
6
|
+
|---------|------------|
|
|
7
|
+
| **Backend** | .NET 10 / C# 14 |
|
|
8
|
+
| **Frontend** | Blazor Server |
|
|
9
|
+
| **Database** | EF Core 10 + Azure SQL |
|
|
10
|
+
| **Hosting** | Azure Container Apps |
|
|
11
|
+
| **Background** | Hangfire |
|
|
12
|
+
| **AI** | Microsoft Agent Framework |
|
|
13
|
+
|
|
14
|
+
**Triggers:** `blazor`, `razor`, `server-side`, `.net`, `csharp`, `dotnet`
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Critical Standards (Read FIRST)
|
|
19
|
+
|
|
20
|
+
| Standard | What |
|
|
21
|
+
|----------|------|
|
|
22
|
+
| `framework/standards/coding.md` | **C# naming conventions, code style, .editorconfig template** |
|
|
23
|
+
| `framework/standards/architecture.md` | **Clean Architecture layers, SOLID, service patterns** |
|
|
24
|
+
| `framework/standards/blazor-efcore.md` | DbContext concurrency, Repository Factory, background ops, migrations |
|
|
25
|
+
| `framework/standards/blazor-pitfalls.md` | Common Blazor issues & solutions |
|
|
26
|
+
| `framework/standards/fluent-ui-blazor.md` | Fluent UI APIs, icon sizes, dialog patterns |
|
|
27
|
+
| `framework/standards/blazor-lifecycle.md` | Component lifecycle patterns |
|
|
28
|
+
| `framework/standards/program-cs-checklist.md` | Required Program.cs setup |
|
|
29
|
+
|
|
30
|
+
### Quick Checklist
|
|
31
|
+
- [ ] Background ops: Use `IDbContextFactory` / Repository Factory (ref: blazor-efcore.md)
|
|
32
|
+
- [ ] JSRuntime: ONLY in `OnAfterRenderAsync(firstRender)`
|
|
33
|
+
- [ ] Program.cs: `UseStaticFiles()` BEFORE `UseAntiforgery()`
|
|
34
|
+
- [ ] File Upload: Specify `maxAllowedSize` in `OpenReadStream()`
|
|
35
|
+
- [ ] RenderMode: NO `@rendermode` on MainLayout
|
|
36
|
+
- [ ] Package Versions: MudBlazor >= 8.15.0 for .NET 10
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Mandatory Code Patterns
|
|
41
|
+
|
|
42
|
+
### Status Validation
|
|
43
|
+
|
|
44
|
+
```csharp
|
|
45
|
+
// ✅ Validate INVALID states (allows future extensions)
|
|
46
|
+
if (order.Status >= OrderStatus.Completed || order.Status == OrderStatus.Failed)
|
|
47
|
+
throw new InvalidOperationException("Cannot process completed or failed order");
|
|
48
|
+
|
|
49
|
+
// ❌ Never assume single valid flow
|
|
50
|
+
if (order.Status != OrderStatus.PendingPayment)
|
|
51
|
+
throw new InvalidOperationException("Invalid status");
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Enums with Logical Order
|
|
55
|
+
|
|
56
|
+
```csharp
|
|
57
|
+
public enum OrderStatus
|
|
58
|
+
{
|
|
59
|
+
Created = 0, PendingPayment = 1, Processing = 2, Completed = 3, // Normal flow
|
|
60
|
+
Failed = 100, Cancelled = 101, Refunded = 102 // Error states (high values)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Service Pattern
|
|
65
|
+
|
|
66
|
+
```csharp
|
|
67
|
+
public async Task<Result<Order>> ProcessAsync(Guid orderId, CancellationToken ct)
|
|
68
|
+
{
|
|
69
|
+
_logger.LogInformation("Processing order {OrderId}", orderId);
|
|
70
|
+
var order = await _repository.GetByIdAsync(orderId, ct);
|
|
71
|
+
if (order == null) return Result.Failure<Order>("Order not found");
|
|
72
|
+
if (order.Status >= OrderStatus.Completed)
|
|
73
|
+
return Result.Failure<Order>("Order already completed");
|
|
74
|
+
// ... process ...
|
|
75
|
+
return Result.Success(order);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Rules:** Logging at critical points, CancellationToken propagated, Result pattern for business errors, exceptions for infrastructure.
|
|
80
|
+
|
|
81
|
+
**More patterns:** See `code-review.md` for DTOs/contracts naming and service checklists.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Project Structure
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
src/
|
|
89
|
+
├── {App}.Domain/ # Entities, Value Objects, Enums, Exceptions
|
|
90
|
+
├── {App}.Application/ # Services, DTOs, Interfaces, Validators
|
|
91
|
+
├── {App}.Infrastructure/ # EF Core (DbContext, Configs, Migrations), External Services
|
|
92
|
+
├── {App}.Web/ # Blazor Server (Program.cs, Components, Pages, wwwroot)
|
|
93
|
+
└── tests/ # UnitTests, IntegrationTests
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Program.cs Essentials
|
|
97
|
+
|
|
98
|
+
```csharp
|
|
99
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
100
|
+
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
|
|
101
|
+
builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(connString));
|
|
102
|
+
builder.Services.AddDbContextFactory<AppDbContext>(o => o.UseSqlServer(connString));
|
|
103
|
+
// Register services, factories, Hangfire...
|
|
104
|
+
|
|
105
|
+
var app = builder.Build();
|
|
106
|
+
app.UseHttpsRedirection();
|
|
107
|
+
app.UseStaticFiles(); // BEFORE UseAntiforgery!
|
|
108
|
+
app.UseAntiforgery();
|
|
109
|
+
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
|
|
110
|
+
app.Run();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Blazor Component Patterns
|
|
116
|
+
|
|
117
|
+
### Page with List
|
|
118
|
+
|
|
119
|
+
```razor
|
|
120
|
+
@page "/orders"
|
|
121
|
+
@inject IOrderService OrderService
|
|
122
|
+
|
|
123
|
+
@if (_orders is null) { <Loading /> }
|
|
124
|
+
else if (!_orders.Any()) { <EmptyState Message="No orders found" /> }
|
|
125
|
+
else
|
|
126
|
+
{
|
|
127
|
+
@foreach (var order in _orders)
|
|
128
|
+
{
|
|
129
|
+
<FluentCard>@order.OrderNumber - @order.Total.ToString("C")</FluentCard>
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@code {
|
|
134
|
+
private List<OrderDto>? _orders;
|
|
135
|
+
protected override async Task OnInitializedAsync()
|
|
136
|
+
=> _orders = await OrderService.GetAllAsync();
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Form with Validation
|
|
141
|
+
|
|
142
|
+
```razor
|
|
143
|
+
@page "/orders/new"
|
|
144
|
+
<EditForm Model="_model" OnValidSubmit="HandleSubmit">
|
|
145
|
+
<DataAnnotationsValidator />
|
|
146
|
+
<InputSelect @bind-Value="_model.CustomerId">...</InputSelect>
|
|
147
|
+
<ValidationMessage For="() => _model.CustomerId" />
|
|
148
|
+
<button type="submit" disabled="@_isSubmitting">Save</button>
|
|
149
|
+
</EditForm>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## UI Libraries
|
|
155
|
+
|
|
156
|
+
> **Decision matrix:** See `ui-ux-designer.md` skill for full comparison.
|
|
157
|
+
|
|
158
|
+
| Library | When | Key Advantage |
|
|
159
|
+
|---------|------|---------------|
|
|
160
|
+
| **Fluent UI** | AI-first, Microsoft stack | Performance (~200KB), AI components |
|
|
161
|
+
| **MudBlazor** | Complex dashboards | 140+ components, charts |
|
|
162
|
+
| **Hybrid** | SaaS with AI + analytics | Best of both |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## .NET 10 Features
|
|
167
|
+
|
|
168
|
+
### PersistentState (new)
|
|
169
|
+
```razor
|
|
170
|
+
@code {
|
|
171
|
+
[PersistentState]
|
|
172
|
+
private int Count { get; set; } = 0; // Survives pre-rendering & circuit disconnections
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Circuit Pause/Resume (new)
|
|
177
|
+
```javascript
|
|
178
|
+
document.addEventListener('visibilitychange', () => {
|
|
179
|
+
document.hidden ? Blazor.pauseCircuit() : Blazor.resumeCircuit();
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Nested Model Validation (new)
|
|
184
|
+
```csharp
|
|
185
|
+
builder.Services.AddValidation(); // Enables automatic nested model validation
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Blazor Metrics
|
|
189
|
+
```csharp
|
|
190
|
+
builder.Services.AddOpenTelemetry()
|
|
191
|
+
.WithTracing(t => t.AddSource("Microsoft.AspNetCore.Components.Server"))
|
|
192
|
+
.WithMetrics(m => m.AddMeter("Microsoft.AspNetCore.Components.Server"));
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Project Checklist
|
|
198
|
+
|
|
199
|
+
- [ ] Clean Architecture layers (Domain, Application, Infrastructure, Web)
|
|
200
|
+
- [ ] EF Core with migrations + IDbContextFactory
|
|
201
|
+
- [ ] Repository Factory for background ops (ref: blazor-efcore.md)
|
|
202
|
+
- [ ] Blazor Server with reusable components
|
|
203
|
+
- [ ] Services with DI + structured logging
|
|
204
|
+
- [ ] Validation (FluentValidation or DataAnnotations)
|
|
205
|
+
- [ ] Hangfire for background jobs
|
|
206
|
+
- [ ] Dockerfile for containerization
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# .NET + Next.js Stack
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** nextjs, next.js, react, api, frontend, spa, typescript
|
|
4
|
+
|
|
5
|
+
| Aspect | Technology |
|
|
6
|
+
|--------|------------|
|
|
7
|
+
| **Backend** | .NET 10 Web API / C# 14 |
|
|
8
|
+
| **Frontend** | Next.js 15+ / React 19 |
|
|
9
|
+
| **Database** | EF Core 10 + Azure SQL |
|
|
10
|
+
| **API** | REST + OpenAPI |
|
|
11
|
+
| **Hosting** | Azure Container Apps |
|
|
12
|
+
|
|
13
|
+
## Project Structure
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/
|
|
17
|
+
├── backend/
|
|
18
|
+
│ ├── src/{Api,Application,Domain,Infrastructure}/
|
|
19
|
+
│ ├── tests/
|
|
20
|
+
│ └── Backend.sln
|
|
21
|
+
├── frontend/
|
|
22
|
+
│ ├── src/{app,components,lib,hooks}/
|
|
23
|
+
│ ├── package.json
|
|
24
|
+
│ └── next.config.js
|
|
25
|
+
├── docker-compose.yml
|
|
26
|
+
└── infra/main.bicep
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Backend (.NET Minimal API)
|
|
32
|
+
|
|
33
|
+
```csharp
|
|
34
|
+
// Program.cs
|
|
35
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
36
|
+
builder.Services.AddEndpointsApiExplorer();
|
|
37
|
+
builder.Services.AddSwaggerGen();
|
|
38
|
+
builder.Services.AddCors(o => o.AddPolicy("Frontend", p =>
|
|
39
|
+
p.WithOrigins(builder.Configuration["Frontend:Url"]!)
|
|
40
|
+
.AllowAnyHeader().AllowAnyMethod().AllowCredentials()));
|
|
41
|
+
builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(connString));
|
|
42
|
+
|
|
43
|
+
var app = builder.Build();
|
|
44
|
+
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
|
|
45
|
+
app.UseCors("Frontend");
|
|
46
|
+
app.UseAuthentication();
|
|
47
|
+
app.UseAuthorization();
|
|
48
|
+
app.MapOrderEndpoints();
|
|
49
|
+
app.Run();
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Minimal API Endpoints
|
|
53
|
+
|
|
54
|
+
```csharp
|
|
55
|
+
public static class OrderEndpoints
|
|
56
|
+
{
|
|
57
|
+
public static void MapOrderEndpoints(this WebApplication app)
|
|
58
|
+
{
|
|
59
|
+
var group = app.MapGroup("/api/orders").WithTags("Orders").RequireAuthorization();
|
|
60
|
+
group.MapGet("/", GetAll);
|
|
61
|
+
group.MapGet("/{id:int}", GetById);
|
|
62
|
+
group.MapPost("/", Create);
|
|
63
|
+
group.MapPut("/{id:int}", Update);
|
|
64
|
+
group.MapDelete("/{id:int}", Delete);
|
|
65
|
+
}
|
|
66
|
+
// Each handler: inject IService + params → return Results.Ok/NotFound/Created/NoContent
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Frontend (Next.js)
|
|
73
|
+
|
|
74
|
+
### API Client
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const API_URL = process.env.NEXT_PUBLIC_API_URL!;
|
|
78
|
+
|
|
79
|
+
async function fetchApi<T>(endpoint: string, options?: RequestInit): Promise<T> {
|
|
80
|
+
const res = await fetch(`${API_URL}${endpoint}`, {
|
|
81
|
+
...options,
|
|
82
|
+
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
83
|
+
credentials: 'include',
|
|
84
|
+
});
|
|
85
|
+
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
|
86
|
+
return res.json();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const api = {
|
|
90
|
+
orders: {
|
|
91
|
+
getAll: (params?) => fetchApi<PaginatedResult<Order>>(`/api/orders?${new URLSearchParams(params)}`),
|
|
92
|
+
getById: (id: number) => fetchApi<Order>(`/api/orders/${id}`),
|
|
93
|
+
create: (data) => fetchApi<Order>('/api/orders', { method: 'POST', body: JSON.stringify(data) }),
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Types (generated from OpenAPI)
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
export interface Order { id: number; orderNumber: string; total: number; status: OrderStatus; }
|
|
102
|
+
export type OrderStatus = 'Pending' | 'Processing' | 'Completed' | 'Cancelled';
|
|
103
|
+
export interface PaginatedResult<T> { items: T[]; totalCount: number; page: number; totalPages: number; }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Server Component (App Router)
|
|
107
|
+
```tsx
|
|
108
|
+
export default async function OrdersPage() {
|
|
109
|
+
const orders = await api.orders.getAll();
|
|
110
|
+
return <OrderList initialOrders={orders} />;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Client Component
|
|
115
|
+
```tsx
|
|
116
|
+
'use client';
|
|
117
|
+
// Use useState + api calls for client-side pagination/interaction
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Docker Compose
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
services:
|
|
126
|
+
backend:
|
|
127
|
+
build: { context: ./backend }
|
|
128
|
+
ports: ["5000:8080"]
|
|
129
|
+
environment:
|
|
130
|
+
- ConnectionStrings__Default=Server=db;Database=App;User=sa;Password=Pass!;TrustServerCertificate=true
|
|
131
|
+
- Frontend__Url=http://localhost:3000
|
|
132
|
+
frontend:
|
|
133
|
+
build: { context: ./frontend }
|
|
134
|
+
ports: ["3000:3000"]
|
|
135
|
+
environment: [NEXT_PUBLIC_API_URL=http://localhost:5000]
|
|
136
|
+
db:
|
|
137
|
+
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
138
|
+
environment: [ACCEPT_EULA=Y, SA_PASSWORD=YourStrong!Passw0rd]
|
|
139
|
+
ports: ["1433:1433"]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Checklist
|
|
143
|
+
- [ ] Backend with Minimal APIs
|
|
144
|
+
- [ ] OpenAPI/Swagger configured
|
|
145
|
+
- [ ] CORS configured for frontend
|
|
146
|
+
- [ ] Frontend with App Router (Next.js 15+)
|
|
147
|
+
- [ ] API client typed
|
|
148
|
+
- [ ] Types generated from OpenAPI
|
|
149
|
+
- [ ] Docker Compose for dev
|
|
150
|
+
- [ ] Environment variables configured
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# UI/UX Designer
|
|
2
|
+
|
|
3
|
+
Especialista em design de interfaces, UX e componentes Blazor. Domina **Fluent UI Blazor** e **MudBlazor**.
|
|
4
|
+
|
|
5
|
+
> **FASE 1.5: UI/UX DESIGN** - Obrigatória para features com front-end.
|
|
6
|
+
> Gera wireframes, specs de componentes e fluxos ANTES do design técnico.
|
|
7
|
+
> **Ref:** `framework/standards/fluent-ui-blazor.md` para API details e armadilhas.
|
|
8
|
+
|
|
9
|
+
## Triggers
|
|
10
|
+
|
|
11
|
+
Keywords: `blazor`, `component`, `page`, `ui`, `ux`, `design`, `layout`, `wizard`, `dashboard`, `form`, `chart`, `table`, `dialog`, `modal`, `tela`, `interface`, `formulário`
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Design Moderno (2025+)
|
|
16
|
+
|
|
17
|
+
### Visual Trends
|
|
18
|
+
- **Glassmorphism**: `backdrop-filter: blur(10px)`, semi-transparent backgrounds
|
|
19
|
+
- **Gradients**: Purple (#667eea → #764ba2), Blue-Purple (#4facfe → #00f2fe)
|
|
20
|
+
- **Soft Shadows**: `box-shadow: 0 4px 6px rgba(0,0,0,0.1)`
|
|
21
|
+
- **Rounded Corners**: `border-radius: 12px-16px`
|
|
22
|
+
- **Micro-interactions**: Hover effects, transitions (transform, scale, opacity)
|
|
23
|
+
|
|
24
|
+
### Component Patterns
|
|
25
|
+
- Cards with elevation + hover lift
|
|
26
|
+
- Skeleton loaders (not just spinners)
|
|
27
|
+
- Toast notifications (bottom-right, auto-dismiss)
|
|
28
|
+
- Empty states with illustration + CTA
|
|
29
|
+
- Dark mode support (always design for both)
|
|
30
|
+
|
|
31
|
+
### Layout Principles
|
|
32
|
+
- Whitespace: 32px-48px container padding
|
|
33
|
+
- Grid: 12-column, gap 24px-32px
|
|
34
|
+
- Typography: xs:12, sm:14, base:16, lg:18, xl:20, 2xl:24
|
|
35
|
+
- Contrast: WCAG AA (4.5:1 text, 3:1 UI)
|
|
36
|
+
|
|
37
|
+
### Design References
|
|
38
|
+
Linear (linear.app), Vercel (vercel.com), Stripe (stripe.com), Dribbble dashboards
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## FASE 1.5 Workflow
|
|
43
|
+
|
|
44
|
+
### Step 1: Collect User Input (ALWAYS ask first)
|
|
45
|
+
|
|
46
|
+
1. Layout ideas or reference sites?
|
|
47
|
+
2. Visual references (screenshots, mockups)?
|
|
48
|
+
3. User flow expectations?
|
|
49
|
+
4. Design system defined (colors, fonts, spacing)?
|
|
50
|
+
5. Image examples to analyze?
|
|
51
|
+
|
|
52
|
+
If user provides screenshots → Read tool → extract patterns (layout, components, colors).
|
|
53
|
+
If HTML prototype exists → extract patterns automatically, skip wireframes, map HTML → Blazor.
|
|
54
|
+
|
|
55
|
+
### Step 2: Generate Deliverables
|
|
56
|
+
|
|
57
|
+
| File | Content |
|
|
58
|
+
|------|---------|
|
|
59
|
+
| `ui-design-system.md` | Colors, typography, spacing |
|
|
60
|
+
| `ui-mockups.md` | ASCII wireframes + descriptions per screen |
|
|
61
|
+
| `ui-components.md` | Component specs (library-agnostic first, library choice in FASE 2) |
|
|
62
|
+
| `ui-flows.md` | User flow diagrams + edge cases |
|
|
63
|
+
|
|
64
|
+
**Important:** Generate specs AGNOSTIC of UI library. Use generic names ("primary button", "card", "table"). Library choice happens in FASE 2: DESIGN.
|
|
65
|
+
|
|
66
|
+
### Step 3: Present for Approval
|
|
67
|
+
|
|
68
|
+
Show deliverable summary → **⛔ PAUSE** with 3 options (approve / adjust wireframes / add flows).
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Fluent UI vs MudBlazor Decision Matrix
|
|
73
|
+
|
|
74
|
+
| Criterion | Fluent UI Blazor | MudBlazor |
|
|
75
|
+
|-----------|------------------|-----------|
|
|
76
|
+
| AI-first projects | Ideal (native components) | Requires customization |
|
|
77
|
+
| Performance | ~200KB | ~500KB |
|
|
78
|
+
| Microsoft Stack | Perfect integration | Works well |
|
|
79
|
+
| Complex components | Limited | Very complete |
|
|
80
|
+
| Community | Smaller (newer) | Larger |
|
|
81
|
+
| Maturity | v4.0 (recent) | v6.x (stable) |
|
|
82
|
+
|
|
83
|
+
**Use Fluent UI if:** AI-first, Microsoft stack, modern M365 design, performance critical.
|
|
84
|
+
**Use MudBlazor if:** Complex dashboards, Material Design, need TreeView/advanced DataGrid, larger community.
|
|
85
|
+
**Hybrid:** Fluent UI (base) + MudBlazor (specific complex components).
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Fluent UI Quick Reference
|
|
90
|
+
|
|
91
|
+
> **Full details:** `framework/standards/fluent-ui-blazor.md`
|
|
92
|
+
|
|
93
|
+
### Common Pitfalls
|
|
94
|
+
|
|
95
|
+
| Issue | Wrong | Correct |
|
|
96
|
+
|-------|-------|---------|
|
|
97
|
+
| Icon sizes | `Size16`, `Size14` | `Size20`, `Size24`, `Size28`, `Size32`, `Size48` |
|
|
98
|
+
| Icon namespace | `@using ...Icons` | `@using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons` |
|
|
99
|
+
| Toast methods | `await ShowSuccessAsync()` | `ToastService.ShowSuccess()` (sync!) |
|
|
100
|
+
| Dialog show | `await _dialog.ShowAsync()` | `_dialog.Show()` (sync!) |
|
|
101
|
+
| Dialog close | `_dialog.Hide()` | `await _dialog.CloseAsync()` (async!) |
|
|
102
|
+
| Dialog init | `<FluentDialog>` | `<FluentDialog Hidden="true">` (must hide initially!) |
|
|
103
|
+
|
|
104
|
+
### Key Components
|
|
105
|
+
|
|
106
|
+
| Component | Use Case |
|
|
107
|
+
|-----------|----------|
|
|
108
|
+
| `FluentCard` + `FluentStack` | Containers, dashboards |
|
|
109
|
+
| `FluentDataGrid` | Data tables with sorting |
|
|
110
|
+
| `FluentWizard` | Multi-step flows |
|
|
111
|
+
| `FluentDialog` | Modals, confirmations |
|
|
112
|
+
| `FluentMessageBar` | Chat, notifications |
|
|
113
|
+
| `FluentProgress` | Loading, streaming |
|
|
114
|
+
| `FluentTextField` | Text inputs |
|
|
115
|
+
| `FluentToast` | System feedback |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## MudBlazor Key Components
|
|
120
|
+
|
|
121
|
+
| Component | Advantage over Fluent |
|
|
122
|
+
|-----------|----------------------|
|
|
123
|
+
| `MudDataGrid` | Grouping, advanced filtering |
|
|
124
|
+
| `MudTreeView` | More complete hierarchies |
|
|
125
|
+
| `MudChart` | Native charts (Fluent has none) |
|
|
126
|
+
| `MudFileUpload` | More upload features |
|
|
127
|
+
| `MudAutocomplete` | Better performance |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Design System Defaults
|
|
132
|
+
|
|
133
|
+
```css
|
|
134
|
+
/* Colors */
|
|
135
|
+
--primary: #3b82f6; --secondary: #6b7280;
|
|
136
|
+
--success: #10b981; --warning: #f59e0b;
|
|
137
|
+
--danger: #ef4444; --info: #06b6d4;
|
|
138
|
+
|
|
139
|
+
/* Spacing (4px system) */
|
|
140
|
+
--space-1: 0.25rem; --space-2: 0.5rem; --space-4: 1rem;
|
|
141
|
+
--space-6: 1.5rem; --space-8: 2rem;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Generating Deliverables
|
|
147
|
+
|
|
148
|
+
### ui-mockups.md Structure
|
|
149
|
+
|
|
150
|
+
Per screen: ASCII wireframe + description (purpose, components, interactions, states) + responsiveness (desktop/mobile).
|
|
151
|
+
|
|
152
|
+
### ui-components.md Structure
|
|
153
|
+
|
|
154
|
+
Per component: Library, component name, main props, events, states (default/loading/error/empty), accessibility (ARIA, keyboard).
|
|
155
|
+
|
|
156
|
+
### ui-flows.md Structure
|
|
157
|
+
|
|
158
|
+
Per flow: Trigger, steps, happy path, edge cases, ASCII flowchart diagram.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Accessibility (A11y)
|
|
163
|
+
|
|
164
|
+
- Contrast: 4.5:1 text minimum (WCAG AA)
|
|
165
|
+
- Focus visible: Outline on focusable elements
|
|
166
|
+
- Labels: Every input with associated label
|
|
167
|
+
- ARIA: Roles and labels where needed
|
|
168
|
+
- Keyboard nav: Logical tab order
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Checklist
|
|
173
|
+
|
|
174
|
+
### FASE 1.5 Deliverables
|
|
175
|
+
- [ ] `ui-mockups.md`: Wireframes for ALL screens + states (loading, error, empty) + responsiveness
|
|
176
|
+
- [ ] `ui-components.md`: Library justified + all components mapped with props/events/states
|
|
177
|
+
- [ ] `ui-flows.md`: Happy paths + edge cases + ASCII diagrams
|
|
178
|
+
- [ ] `decisions.md`: Updated with UI library ADR
|
|
179
|
+
|
|
180
|
+
### UI Quality
|
|
181
|
+
- [ ] Visual hierarchy clear
|
|
182
|
+
- [ ] Consistent spacing (4px multiples)
|
|
183
|
+
- [ ] Responsive (mobile-first)
|
|
184
|
+
- [ ] States: hover, focus, disabled, error
|
|
185
|
+
- [ ] Loading states (skeleton/spinner)
|
|
186
|
+
- [ ] Empty states with CTA
|
|
187
|
+
- [ ] WCAG AA accessibility
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
*MORPH-SPEC by Polymorphism Tech*
|