From 629da9aacca19b7b4c64dbcf4c0d853693066df5 Mon Sep 17 00:00:00 2001 From: Kevin Bost Date: Mon, 27 Apr 2026 13:27:14 -0700 Subject: [PATCH 1/2] Add SKILL.md files and MCP server config to plugins - Add 10 skill definitions across 5 plugins using the official SKILL.md format (frontmatter with name/description + invocation instructions): - coalesce-accelerator: generate-migration, scaffold-entity, add-data-source - enterprise-bug-fixing: start-bug-fix, write-bug-tests - csharp-best-practices: review-async, check-naming - vuetify-components: scaffold-component, add-form - testing-essentials: write-unit-tests - Declare the skills path field in each updated plugin.json so the Copilot CLI can discover and invoke skills via /skills invoke - Add enterprise-bug-fixing/.mcp.json bundling the four MCP servers that BugFixerAgent.agent.md depends on (Azure DevOps, context7, nuget, playwright). Declare mcpServers and agents path fields in the enterprise-bug-fixing plugin.json. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- plugins/coalesce-accelerator/plugin.json | 1 + .../skills/add-data-source/SKILL.md | 74 ++++++++++++ .../skills/generate-migration/SKILL.md | 63 ++++++++++ .../skills/scaffold-entity/SKILL.md | 85 +++++++++++++ plugins/csharp-best-practices/plugin.json | 1 + .../skills/check-naming/SKILL.md | 92 ++++++++++++++ .../skills/review-async/SKILL.md | 84 +++++++++++++ plugins/enterprise-bug-fixing/.mcp.json | 32 +++++ plugins/enterprise-bug-fixing/plugin.json | 3 + .../skills/start-bug-fix/SKILL.md | 58 +++++++++ .../skills/write-bug-tests/SKILL.md | 71 +++++++++++ plugins/testing-essentials/plugin.json | 1 + .../skills/write-unit-tests/SKILL.md | 111 +++++++++++++++++ plugins/vuetify-components/plugin.json | 1 + .../skills/add-form/SKILL.md | 113 ++++++++++++++++++ .../skills/scaffold-component/SKILL.md | 90 ++++++++++++++ 16 files changed, 880 insertions(+) create mode 100644 plugins/coalesce-accelerator/skills/add-data-source/SKILL.md create mode 100644 plugins/coalesce-accelerator/skills/generate-migration/SKILL.md create mode 100644 plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md create mode 100644 plugins/csharp-best-practices/skills/check-naming/SKILL.md create mode 100644 plugins/csharp-best-practices/skills/review-async/SKILL.md create mode 100644 plugins/enterprise-bug-fixing/.mcp.json create mode 100644 plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md create mode 100644 plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md create mode 100644 plugins/testing-essentials/skills/write-unit-tests/SKILL.md create mode 100644 plugins/vuetify-components/skills/add-form/SKILL.md create mode 100644 plugins/vuetify-components/skills/scaffold-component/SKILL.md diff --git a/plugins/coalesce-accelerator/plugin.json b/plugins/coalesce-accelerator/plugin.json index f41b901..98e0efd 100644 --- a/plugins/coalesce-accelerator/plugin.json +++ b/plugins/coalesce-accelerator/plugin.json @@ -22,6 +22,7 @@ "TypeScript" ], "categories": ["Framework", "FullStack"], + "skills": "skills/", "contents": { "instructions": [ "instructions/coalesce-workflows.md", diff --git a/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md b/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md new file mode 100644 index 0000000..00b1943 --- /dev/null +++ b/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md @@ -0,0 +1,74 @@ +--- +name: add-data-source +description: Add a custom Coalesce IDataSource to filter or shape entity data for a specific use case +--- + +# Add Data Source Skill + +Create a custom Coalesce `IDataSource` implementation to provide filtered, shaped, or security-scoped access to an entity beyond the default CRUD behavior. + +## When to Use + +Invoke this skill when you need to: +- Expose a filtered subset of an entity (e.g., "only active records") +- Add includes/eager loading not present on the default source +- Scope data to the current user (tenancy, ownership) +- Return a projection or computed view of an entity + +## Data Source Pattern + +```csharp +using IntelliTect.Coalesce; +using IntelliTect.Coalesce.Api; +using IntelliTect.Coalesce.TypeDefinition; + +[Coalesce] +public class ActiveEntitySource : StandardDataSource +{ + public ActiveEntitySource(CrudContext context) : base(context) { } + + public override IQueryable GetQuery(IDataSourceParameters parameters) + => base.GetQuery(parameters) + .Where(e => e.IsActive) + .Include(e => e.RelatedEntity); +} +``` + +## Steps + +1. **Create the data source class** in a `DataSources/` folder beside your entity models +2. **Decorate with `[Coalesce]`** so the CLI picks it up during code generation +3. **Override `GetQuery`** — compose from `base.GetQuery()` to retain default filtering/sorting support +4. **Optionally override `TransformResults`** for post-query shaping +5. **Run `coalesce_generate`** to expose it in the API: + ```bash + coalesce_generate + ``` +6. **Verify the new data source appears** in the generated API and TypeScript service +7. **Write tests** that confirm filtering/scoping works correctly + +## User-Scoped Data Source Pattern + +```csharp +[Coalesce] +public class MyRecordsSource : StandardDataSource +{ + private readonly ICurrentUserService _currentUser; + + public MyRecordsSource(CrudContext context, ICurrentUserService currentUser) + : base(context) + { + _currentUser = currentUser; + } + + public override IQueryable GetQuery(IDataSourceParameters parameters) + => base.GetQuery(parameters) + .Where(r => r.OwnerId == _currentUser.UserId); +} +``` + +## Notes + +- Multiple data sources can exist for the same entity — each becomes a selectable source in the API +- The default data source is `StandardDataSource` — your custom sources supplement it +- Always test that unauthorized data cannot be reached through alternative data sources diff --git a/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md b/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md new file mode 100644 index 0000000..91aa3fc --- /dev/null +++ b/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md @@ -0,0 +1,63 @@ +--- +name: generate-migration +description: Generate an EF Core migration and run it for the current Coalesce project +--- + +# Generate Migration Skill + +Generate a new EF Core database migration after making changes to Coalesce entity models, then optionally apply it to the database. + +## When to Use + +Invoke this skill after you have: +- Added, renamed, or removed a property on a Coalesce entity +- Added or removed a navigation property or relationship +- Changed a `[StringLength]`, `[Required]`, or other schema-affecting attribute +- Added a new entity class to the `DbContext` + +## Steps + +1. **Verify the model compiles** + ```bash + dotnet build + ``` + Fix any compiler errors before proceeding. + +2. **Regenerate Coalesce artifacts** to keep the API and TypeScript types in sync: + ```bash + coalesce_generate + ``` + +3. **Add the EF Core migration** using a descriptive PascalCase name that describes the change: + ```bash + dotnet ef migrations add --project --startup-project + ``` + Examples: `AddCompanyPhoneNumber`, `RemoveOrderLegacyStatus`, `AddIndexOnUserEmail` + +4. **Review the generated migration file** in `Migrations/` — verify the `Up()` and `Down()` methods match your intent. Check for: + - Unexpected table drops or column drops + - Missing `nullable` settings + - Correct foreign key constraints + +5. **Apply the migration to the database**: + ```bash + dotnet ef database update --project --startup-project + ``` + +6. **Run tests** to confirm nothing regressed: + ```bash + dotnet test + ``` + +## Naming Conventions + +Migration names should be short, PascalCase, and describe **what changed**: +- ✅ `AddUserEmailIndex` +- ✅ `RenameCompanyAddressToStreet` +- ❌ `Update1`, `Migration20240101`, `Changes` + +## Notes + +- Always review the generated `.cs` migration file before applying — EF Core may infer destructive changes +- If the migration is complex, split it: one for schema changes, one for data changes +- For seed data changes, consider a separate data migration or a custom `IHostedService` diff --git a/plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md b/plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md new file mode 100644 index 0000000..33276df --- /dev/null +++ b/plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md @@ -0,0 +1,85 @@ +--- +name: scaffold-entity +description: Scaffold a new Coalesce entity class with EF Core annotations, navigation properties, and register it in the DbContext +--- + +# Scaffold Entity Skill + +Create a complete Coalesce-compatible C# entity class with appropriate EF Core data annotations, navigation properties, and DbContext registration. + +## When to Use + +Invoke this skill when you need to: +- Add a new domain entity to the Coalesce data model +- Create a related/child entity with a foreign key relationship +- Scaffold a lookup/reference table entity + +## Required Information + +Before scaffolding, gather: +1. **Entity name** — PascalCase noun (e.g., `Invoice`, `ProjectMilestone`) +2. **Properties** — names, types, and whether required/optional +3. **Relationships** — parent entity (if any), one-to-many or many-to-many +4. **Table name** — usually pluralized entity name (e.g., `Invoices`) + +## Scaffold Pattern + +```csharp +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using IntelliTect.Coalesce.DataAnnotations; + +[Table("EntityNamePlural")] +public class EntityName +{ + // Primary key — name must be {EntityName}Id + [Key] + public int EntityNameId { get; set; } + + // Required string property + [Required] + [StringLength(255)] + [Display(Name = "Friendly Label")] + public required string Name { get; set; } + + // Optional string property + [StringLength(1024)] + public string? Description { get; set; } + + // Foreign key + navigation (many-to-one) + public int ParentId { get; set; } + public Parent Parent { get; set; } = null!; + + // Audit fields + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime? UpdatedAt { get; set; } +} +``` + +## Steps + +1. **Create the entity file** in the `Models/` directory +2. **Add the DbSet** to the application's `DbContext`: + ```csharp + public DbSet EntityNames { get; set; } + ``` +3. **Run `coalesce_generate`** to generate the API and TypeScript types: + ```bash + coalesce_generate + ``` +4. **Create a migration** to add the table (use the `generate-migration` skill) +5. **Build and test**: + ```bash + dotnet build && dotnet test + ``` + +## Coalesce-Specific Annotations + +| Attribute | Effect | +|-----------|--------| +| `[Read(Roles = "Admin")]` | Restrict read access by role | +| `[Edit(Roles = "Admin")]` | Restrict edit access by role | +| `[Hidden]` | Exclude from generated list views | +| `[Search]` | Include property in text search | +| `[DefaultOrderBy]` | Set default sort property | +| `[ListText]` | Use as display text in dropdowns | diff --git a/plugins/csharp-best-practices/plugin.json b/plugins/csharp-best-practices/plugin.json index 4e76b0e..9d2e44c 100644 --- a/plugins/csharp-best-practices/plugin.json +++ b/plugins/csharp-best-practices/plugin.json @@ -23,6 +23,7 @@ "dotnet" ], "categories": ["Language", "Enterprise"], + "skills": "skills/", "contents": { "instructions": [ "instructions/csharp-patterns.md", diff --git a/plugins/csharp-best-practices/skills/check-naming/SKILL.md b/plugins/csharp-best-practices/skills/check-naming/SKILL.md new file mode 100644 index 0000000..18fb942 --- /dev/null +++ b/plugins/csharp-best-practices/skills/check-naming/SKILL.md @@ -0,0 +1,92 @@ +--- +name: check-naming +description: Check C# naming conventions in a file or selection against Microsoft and project standards +--- + +# Check Naming Skill + +Audit C# identifiers in the current file or selection for adherence to Microsoft naming conventions and enterprise project standards. + +## When to Use + +Invoke this skill when you: +- Want to validate naming before committing or opening a pull request +- Are reviewing code from someone unfamiliar with C# conventions +- Migrated code from another language and need a naming pass +- Want to enforce consistent style across a new file + +## Conventions Checked + +### Types (classes, interfaces, records, structs, enums) +```csharp +// ✅ PascalCase +public class UserAccountService { } +public interface IEmailSender { } +public record OrderSummary(int Id, decimal Total); +public enum OrderStatus { Pending, Active, Closed } + +// ❌ +public class userAccountService { } // camelCase +public interface EmailSender { } // missing I prefix +``` + +### Methods and properties +```csharp +// ✅ PascalCase +public string GetDisplayName() { } +public bool IsActive { get; set; } +public async Task GetUserAsync(int id) { } // Async suffix + +// ❌ +public string getDisplayName() { } // camelCase +public async Task GetUser(int id) { } // missing Async suffix +``` + +### Private fields +```csharp +// ✅ _camelCase with underscore prefix +private readonly ILogger _logger; +private string _cachedValue; + +// ❌ +private readonly ILogger logger; // no underscore +private string CachedValue; // PascalCase for field +``` + +### Constants and static readonly +```csharp +// ✅ PascalCase +public const int MaxRetryCount = 3; +private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); + +// ❌ +public const int MAX_RETRY_COUNT = 3; // SCREAMING_CASE +``` + +### Parameters and local variables +```csharp +// ✅ camelCase +public void Process(int userId, string displayName) { } +var orderCount = orders.Count(); + +// ❌ +public void Process(int UserId, string DisplayName) { } // PascalCase +``` + +### Generic type parameters +```csharp +// ✅ T, or TKey/TValue for multiple parameters +public class Repository where T : class { } +public class Dictionary { } + +// ❌ +public class Repository { } // descriptive word without T prefix +``` + +## Review Output + +For each violation found, report: +- **Identifier**: the name that violates the convention +- **Expected convention**: what it should be +- **Suggested name**: the corrected identifier +- **Location**: line number in the file diff --git a/plugins/csharp-best-practices/skills/review-async/SKILL.md b/plugins/csharp-best-practices/skills/review-async/SKILL.md new file mode 100644 index 0000000..b814932 --- /dev/null +++ b/plugins/csharp-best-practices/skills/review-async/SKILL.md @@ -0,0 +1,84 @@ +--- +name: review-async +description: Review async/await usage in a C# file or selection for common pitfalls and anti-patterns +--- + +# Review Async Skill + +Audit async/await usage in the current file or selected code for correctness, safety, and adherence to C# async best practices. + +## When to Use + +Invoke this skill when you: +- Want to check a file for async anti-patterns before code review +- Suspect a deadlock or performance issue caused by improper async usage +- Are migrating synchronous code to async and want a validation pass +- Added new async methods and want them reviewed + +## What This Skill Checks + +### 1. Blocking on async (deadlock risk) +```csharp +// ❌ Dangerous — can deadlock in non-console contexts +var result = GetDataAsync().Result; +var result = GetDataAsync().GetAwaiter().GetResult(); +Task.Run(() => GetDataAsync()).Wait(); + +// ✅ Correct +var result = await GetDataAsync(); +``` + +### 2. async void (fire-and-forget danger) +```csharp +// ❌ Exceptions are unobservable +public async void LoadData() { ... } + +// ✅ Use Task return type; async void only for event handlers +public async Task LoadDataAsync() { ... } +``` + +### 3. Missing ConfigureAwait(false) in library code +```csharp +// ❌ In a library — may cause deadlocks in UI/ASP.NET contexts +await _client.GetAsync(url); + +// ✅ In library code +await _client.GetAsync(url).ConfigureAwait(false); +``` + +### 4. Unnecessary async wrapper +```csharp +// ❌ Unnecessary state machine overhead +public async Task GetCountAsync() => await _repo.CountAsync(); + +// ✅ Just return the Task directly +public Task GetCountAsync() => _repo.CountAsync(); +``` + +### 5. Missing CancellationToken propagation +```csharp +// ❌ Ignores cancellation +public async Task ProcessAsync() { await _db.SaveChangesAsync(); } + +// ✅ Propagates cancellation +public async Task ProcessAsync(CancellationToken ct = default) + { await _db.SaveChangesAsync(ct); } +``` + +### 6. Unobserved task (fire-and-forget without handling) +```csharp +// ❌ Exception is swallowed +_ = DoWorkAsync(); + +// ✅ If fire-and-forget is intentional, handle exceptions +_ = DoWorkAsync().ContinueWith(t => _logger.LogError(t.Exception, "Background task failed"), + TaskContinuationOptions.OnlyOnFaulted); +``` + +## Review Output + +For each issue found, report: +- **Location**: file name and line number +- **Issue type**: one of the categories above +- **Severity**: Warning or Error +- **Suggested fix**: corrected code snippet diff --git a/plugins/enterprise-bug-fixing/.mcp.json b/plugins/enterprise-bug-fixing/.mcp.json new file mode 100644 index 0000000..5ec6a3f --- /dev/null +++ b/plugins/enterprise-bug-fixing/.mcp.json @@ -0,0 +1,32 @@ +{ + "mcpServers": { + "ado_with_filtered_domains": { + "description": "Azure DevOps MCP server for querying work items, boards, and pipelines. Required for work item retrieval in the bug-fix workflow.", + "notes": "Install from: https://github.com/microsoft/azure-devops-mcp — configure ADO_ORGANIZATION and ADO_PAT environment variables before use.", + "command": "npx", + "args": ["-y", "@microsoft/azure-devops-mcp"], + "env": { + "ADO_ORGANIZATION": "${ADO_ORGANIZATION}", + "ADO_PAT": "${ADO_PAT}" + } + }, + "context7": { + "description": "Context7 MCP server for accessing up-to-date library documentation (Coalesce, ASP.NET Core, EF Core). Used by the bug-fix agent to look up API references.", + "notes": "Install from: https://github.com/upstash/context7-mcp", + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"] + }, + "nuget": { + "description": "NuGet MCP server for querying package versions and vulnerability information during bug analysis.", + "notes": "Install from: https://github.com/github/github-mcp-server or equivalent NuGet MCP integration.", + "command": "npx", + "args": ["-y", "@microsoft/nuget-mcp"] + }, + "playwright": { + "description": "Playwright MCP server for browser-based testing and end-to-end validation during bug fixing.", + "notes": "Install from: https://github.com/microsoft/playwright-mcp — requires Node.js and Playwright browsers.", + "command": "npx", + "args": ["-y", "@playwright/mcp@latest"] + } + } +} diff --git a/plugins/enterprise-bug-fixing/plugin.json b/plugins/enterprise-bug-fixing/plugin.json index df49b04..6f19eb9 100644 --- a/plugins/enterprise-bug-fixing/plugin.json +++ b/plugins/enterprise-bug-fixing/plugin.json @@ -22,6 +22,9 @@ "validation" ], "categories": ["Specialized", "Workflow"], + "agents": "agents/", + "skills": "skills/", + "mcpServers": ".mcp.json", "contents": { "agents": ["agents/BugFixerAgent.agent.md"], "instructions": ["instructions/bug-fixing-workflow.md"] diff --git a/plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md b/plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md new file mode 100644 index 0000000..fa76149 --- /dev/null +++ b/plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md @@ -0,0 +1,58 @@ +--- +name: start-bug-fix +description: Kick off the full enterprise bug-fix workflow — retrieve a work item from Azure DevOps and begin the structured fix process +--- + +# Start Bug Fix Skill + +Launch the structured enterprise bug-fix workflow for an Azure DevOps work item. This skill delegates to the BugFixerAgent to drive the full process from work item retrieval through to a code-review-ready branch. + +## When to Use + +Invoke this skill when you: +- Have an Azure DevOps bug or PBI number and want to begin fixing it +- Need to start a test-first bug-fix workflow +- Want the full structured process (branch creation, test writing, fix, validation) + +## Usage + +Provide the Azure DevOps work item number when invoking: + +``` +/skills invoke start-bug-fix +``` + +You will be prompted for the work item number if not already provided. + +## What This Skill Does + +This skill activates the **BugFixerAgent** and begins the following workflow: + +``` +1. Retrieve work item from Azure DevOps +2. Analyze and understand root cause +3. Create feature branch (format: {initials}/pbi{number}) +4. Write tests that reproduce the bug (test-first) +5. Implement the minimal fix +6. Validate: run tests, build, check for regressions +7. Handle model/Coalesce changes if applicable +8. Pre-completion checklist +9. Mark as ready for code review +``` + +## Inputs Required + +- **Work item number** — e.g., `12345` or `PBI 12345` +- **Project** (optional) — defaults to `CMA` if not specified + +## Branch Naming Convention + +Feature branches are named: `{user_initials}/pbi{work_item_number}` + +Examples: `kb/pbi12345`, `jd/pbi67890` + +## Notes + +- Do not start this skill without a valid work item number — the agent will ask for one +- If you are already on a feature branch, the agent will ask whether to continue on it or create a new one +- Tests must fail before the fix and pass after — this is enforced by the workflow diff --git a/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md b/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md new file mode 100644 index 0000000..e9b0e43 --- /dev/null +++ b/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md @@ -0,0 +1,71 @@ +--- +name: write-bug-tests +description: Write xUnit tests that reproduce a specific bug before the fix is implemented (test-first approach) +--- + +# Write Bug Tests Skill + +Write failing xUnit tests that precisely reproduce a bug's behavior, following the test-first methodology. Tests should fail before the fix and pass after it. + +## When to Use + +Invoke this skill when you: +- Have identified the root cause of a bug and need to write tests before fixing it +- Want to ensure the fix doesn't regress later +- Need to document the expected behavior through tests + +## Inputs Required + +- Description of the bug (what happens vs. what should happen) +- The class/method where the bug occurs +- Any known reproduction steps + +## Test Structure + +Each bug-reproduction test must follow Arrange-Act-Assert: + +```csharp +[Fact] +public void ClassName_WhenBugCondition_ShouldExpectedBehavior() +{ + // Arrange — set up the bug-triggering scenario + var sut = new ServiceUnderTest(); + var input = CreateBugTriggeringInput(); + + // Act — perform the action that triggers the bug + var result = sut.MethodUnderTest(input); + + // Assert — verify the CORRECT (post-fix) behavior + Assert.Equal(expectedValue, result); +} +``` + +## Test Naming Convention + +Name tests to describe the business scenario, not the implementation: + +- ✅ `Order_WhenCancelledAfterShipment_ShouldNotRefundCustomer` +- ✅ `Invoice_WhenTaxRateIsZero_ShouldNotThrowException` +- ❌ `TestMethod1`, `FixBug123`, `CheckNull` + +## Steps + +1. **Identify the affected class and method** +2. **Locate or create the test file** — follow existing test project naming conventions +3. **Write a test that reproduces the bug** — it must fail with the current code +4. **Run the test to confirm it fails**: + ```bash + dotnet test --filter "FullyQualifiedName~TestClassName" + ``` +5. **Write additional tests** for: + - The happy path (normal behavior) + - Edge cases mentioned in the work item + - Related scenarios that could regress + +## Guidelines + +- Test business requirements, not implementation details +- Use realistic test data (not `"test"`, `0`, or `null` unless that's the bug trigger) +- Each test verifies exactly one business requirement +- Avoid complex test logic — if the test is hard to read, simplify it +- Do not use `Assert.True(result != null)` — use `Assert.NotNull(result)` diff --git a/plugins/testing-essentials/plugin.json b/plugins/testing-essentials/plugin.json index ba9bc9a..b9455ee 100644 --- a/plugins/testing-essentials/plugin.json +++ b/plugins/testing-essentials/plugin.json @@ -20,6 +20,7 @@ "mocking" ], "categories": ["Enterprise", "Testing"], + "skills": "skills/", "contents": { "instructions": [ "instructions/testing-best-practices.md", diff --git a/plugins/testing-essentials/skills/write-unit-tests/SKILL.md b/plugins/testing-essentials/skills/write-unit-tests/SKILL.md new file mode 100644 index 0000000..b0e181e --- /dev/null +++ b/plugins/testing-essentials/skills/write-unit-tests/SKILL.md @@ -0,0 +1,111 @@ +--- +name: write-unit-tests +description: Write xUnit unit tests for a C# class or method following Arrange-Act-Assert and enterprise testing patterns +--- + +# Write Unit Tests Skill + +Generate comprehensive xUnit unit tests for a specified C# class or method, covering the happy path, error conditions, boundary values, and edge cases. + +## When to Use + +Invoke this skill when you: +- Need to add tests to an existing untested class or method +- Are practicing TDD and want to write tests before implementation +- Want comprehensive coverage before a refactor +- Are reviewing a PR and need to add missing test cases + +## Required Information + +Provide: +1. **Class and method to test** — e.g., `OrderService.PlaceOrder` +2. **What it does** — brief description of the behavior +3. **Key scenarios** — happy path, failure cases, edge cases you want covered + +## Test File Structure + +```csharp +using FluentAssertions; +using Moq; +using Xunit; + +namespace MyApp.Tests.Services; + +public class OrderServiceTests +{ + // Shared mocks/fixtures + private readonly Mock _repositoryMock = new(); + private readonly Mock _emailMock = new(); + private OrderService CreateSut() => + new(_repositoryMock.Object, _emailMock.Object); + + [Fact] + public async Task PlaceOrder_WithValidInput_CreatesOrderAndSendsConfirmation() + { + // Arrange + var order = new Order { CustomerId = 1, Items = [new OrderItem { ProductId = 5, Qty = 2 }] }; + _repositoryMock.Setup(r => r.SaveAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(order with { OrderId = 42 }); + var sut = CreateSut(); + + // Act + var result = await sut.PlaceOrderAsync(order); + + // Assert + result.OrderId.Should().Be(42); + _emailMock.Verify(e => e.SendConfirmationAsync(order.CustomerId, 42, It.IsAny()), Times.Once); + } + + [Fact] + public async Task PlaceOrder_WithEmptyItems_ThrowsValidationException() + { + // Arrange + var order = new Order { CustomerId = 1, Items = [] }; + var sut = CreateSut(); + + // Act + var act = () => sut.PlaceOrderAsync(order); + + // Assert + await act.Should().ThrowAsync() + .WithMessage("*at least one item*"); + } +} +``` + +## Test Categories to Cover + +For each method, generate tests for: + +| Category | Description | +|----------|-------------| +| **Happy path** | Valid input, expected output | +| **Null / empty input** | `null`, empty string, empty collection | +| **Boundary values** | Min/max values, limits | +| **Invalid state** | Precondition failures | +| **Exception handling** | What throws and what is caught | +| **Dependency interactions** | Verify mocks called correctly | + +## Test Naming Convention + +``` +MethodName_WhenCondition_ExpectedOutcome +``` + +Examples: +- `PlaceOrder_WithValidInput_CreatesOrderAndSendsConfirmation` +- `GetUser_WhenUserNotFound_ReturnsNull` +- `ProcessPayment_WhenAmountExceedsLimit_ThrowsException` + +## Mocking Guidelines + +- Use `Moq` for interface mocks +- Prefer `Mock.Setup(...).ReturnsAsync(...)` over `.Returns(Task.FromResult(...))` +- Verify interactions with `.Verify(...)` only when the call itself is the behavior under test +- Use `It.IsAny()` for parameters you don't care about; use specific values when the value matters + +## Assertions + +- Use `FluentAssertions` (`.Should().Be(...)`, `.Should().Contain(...)`) for readable assertions +- One logical assertion per test — multiple `.Should()` calls on the same object are fine +- For exceptions: use `act.Should().ThrowAsync()` instead of `Assert.ThrowsAsync` diff --git a/plugins/vuetify-components/plugin.json b/plugins/vuetify-components/plugin.json index db5bf08..2e4ce63 100644 --- a/plugins/vuetify-components/plugin.json +++ b/plugins/vuetify-components/plugin.json @@ -23,6 +23,7 @@ "composition-api" ], "categories": ["Framework", "Frontend", "UI/UX", "Accessibility"], + "skills": "skills/", "contents": { "instructions": [ "instructions/vuetify-components.md", diff --git a/plugins/vuetify-components/skills/add-form/SKILL.md b/plugins/vuetify-components/skills/add-form/SKILL.md new file mode 100644 index 0000000..b5e06e1 --- /dev/null +++ b/plugins/vuetify-components/skills/add-form/SKILL.md @@ -0,0 +1,113 @@ +--- +name: add-form +description: Add a Vuetify form with validation to a Vue 3 component using VeeValidate or Vuetify's built-in validation +--- + +# Add Form Skill + +Add a validated Vuetify form to an existing or new Vue 3 component, including field definitions, validation rules, submission handling, and error display. + +## When to Use + +Invoke this skill when you need to: +- Add a create/edit form for a domain entity +- Add a search or filter form +- Add a settings or preferences form with validation +- Convert an unvalidated form to one with proper error handling + +## Required Information + +Provide: +1. **Fields** — names, types (`text`, `number`, `date`, `select`, `checkbox`), and validation rules +2. **Submit action** — what happens on successful submission (API call, event emit, navigation) +3. **Validation approach** — Vuetify built-in rules or VeeValidate + +## Vuetify Built-In Validation Pattern + +```vue + + + +``` + +## Validation Rules Reference + +| Rule | Pattern | +|------|---------| +| Required | `v => !!v \|\| 'Required'` | +| Min length | `v => v.length >= n \|\| 'Min n chars'` | +| Max length | `v => v.length <= n \|\| 'Max n chars'` | +| Email | `v => /.+@.+\..+/.test(v) \|\| 'Invalid email'` | +| Numeric range | `v => (v >= min && v <= max) \|\| 'Out of range'` | + +## UX Guidelines + +- Show validation errors only after the user has interacted with a field (`validate-on="blur"`) +- Disable the submit button only while submitting (`loading` prop), not while the form is invalid +- Display a top-level error alert for server-side errors +- Reset the form on cancel with `form.value?.reset()` +- Use `v-btn type="submit"` to enable native form submission (Enter key support) diff --git a/plugins/vuetify-components/skills/scaffold-component/SKILL.md b/plugins/vuetify-components/skills/scaffold-component/SKILL.md new file mode 100644 index 0000000..20ff43b --- /dev/null +++ b/plugins/vuetify-components/skills/scaffold-component/SKILL.md @@ -0,0 +1,90 @@ +--- +name: scaffold-component +description: Scaffold a new Vuetify Vue 3 component using the Composition API with proper structure, props, emits, and accessibility +--- + +# Scaffold Component Skill + +Generate a well-structured Vuetify Vue 3 single-file component (SFC) using the Composition API, following accessibility and UX best practices. + +## When to Use + +Invoke this skill when you need to: +- Create a new reusable UI component +- Add a page-level component that wraps Vuetify layout components +- Build a data display component (table, card, list) +- Create a modal or dialog component + +## Required Information + +Before scaffolding, provide: +1. **Component name** — PascalCase (e.g., `UserCard`, `InvoiceTable`, `ConfirmDialog`) +2. **Component purpose** — what data it displays or action it performs +3. **Props** — inputs from parent (names, types, whether required) +4. **Emits** — events the component raises to parent (e.g., `update:modelValue`, `confirm`) + +## SFC Structure + +```vue + + + +``` + +## Accessibility Requirements + +- Always use semantic Vuetify components (`v-btn` over `div` for buttons) +- Provide `aria-label` on icon-only buttons: + ```html + + ``` +- Use `v-tooltip` to add tooltips for icon actions +- Ensure keyboard navigation works (Vuetify handles most of this automatically) +- Color alone must not convey meaning — pair with text or icon + +## File Placement + +Place the component in the appropriate directory: +- Reusable components → `src/components/` +- Page-level components → `src/views/` +- Domain-specific components → `src/components/{domain}/` + +## Notes + +- Use ` -``` - -**Responsive Breakpoints**: -``` -xs: 0px (extra small) -sm: 600px (small) -md: 960px (medium) -lg: 1264px (large) -xl: 1904px (extra large) -``` - -**VCol Props**: -- `cols`: Default columns (1-12) at xs breakpoint -- `sm`, `md`, `lg`, `xl`: Columns at specific breakpoints -- `offset-*`: Offset columns at each breakpoint -- `order-*`: Reorder columns with flexbox - -### VSheet - -Flexible container for grouping content with consistent elevation and styling. - -```vue - - - - - rounded - color="primary" - class="pa-4 ma-2" -/> -``` - -**Usage Guidelines**: -- Use `VSheet` as a flexible container when `VCard` is overkill -- Elevation (shadow) for depth and visual hierarchy -- Combine with Vuetify spacing utilities (pa-*, ma-*, py-*, px-*) - -### VNavigationDrawer - -Persistent or temporary navigation sidebar. - -```vue - - - -``` - -**Props**: -- `v-model`: Control open/closed state -- `rail`: Collapse to icon-only mode -- `permanent`: Always visible (on large screens) -- `app`: Take full height including AppBar -- `width`: Custom drawer width (default 256px) - -### VAppBar - -Top application bar with title, actions, and navigation. - -```vue - - - -``` - -**Props**: -- `app`: Fix to top of screen -- `color`: Background color -- `dark`/`light`: Text color scheme -- `flat`: Remove elevation shadow -- `border`: Add bottom border instead of shadow - ---- - -## Data Display Components - -### VDataTable - -Powerful table component with sorting, filtering, and pagination. - -```vue - - - -``` - -**Key Features**: -- Two-way binding with `v-model:page` and `v-model:items-per-page` -- Search filtering across all columns -- Sortable columns (customize per column) -- Custom item rendering with scoped slots -- Loading state with spinner overlay - -### VList - -Flexible list component with items, groups, and avatars. - -```vue - - - -``` - -### VCard - -Container for content with header, text, and actions. - -```vue - -``` - -**Card Structure**: -- `VCardTitle`: Card heading -- `VCardSubtitle`: Optional subtitle -- `VCardText`: Main content area -- `VCardActions`: Footer with buttons -- Combine with `VImg`, `VDivider` for complex layouts - -### VChip - -Small, compact component for tags, categories, or selections. - -```vue - - - -``` - ---- - -## Form Components - -### VTextField - -Single-line text input with validation and icons. - -```vue - - - -``` - -**Props**: -- `type`: 'text', 'email', 'password', 'number', 'search', 'url', 'tel' -- `label`: Field label (floats on focus) -- `placeholder`: Input placeholder text -- `prepend-icon`/`append-icon`: Icons before/after input -- `clearable`: Show clear button when value exists -- `rules`: Array of validation functions -- `error-messages`: Display validation errors -- `hint`: Helper text below field -- `persistent-hint`: Always show hint (not just on focus) -- `readonly`: Prevent user input -- `disabled`: Disable field completely -- `variant`: 'outlined', 'filled', 'underlined', 'plain' -- `dense`: Smaller height -- `rounded`: Rounded corners - -### VSelect - -Dropdown selection with multiple choices. - -```vue - - - -``` - -**Props**: -- `multiple`: Allow multiple selections -- `chips`: Display selections as chips -- `search`: Enable search/filter -- `item-title`: Property name for display text -- `item-value`: Property name for actual value -- `clearable`: Show clear button -- `disabled`: Disable field - -### VCheckbox - -Checkbox for boolean input. - -```vue - - - -``` - -### VRadio & VRadioGroup - -Radio buttons for single selection from multiple options. - -```vue - - - -``` - -### VSwitch - -Toggle switch for boolean values. - -```vue - - - -``` - ---- - -## Dialog & Menu Patterns - -### VDialog - -Modal dialog for forms, confirmations, or detailed content. - -```vue - - - -``` - -**Props**: -- `max-width`: Maximum width (e.g., '500', '600', 'lg') -- `width`: Explicit width -- `fullscreen`: Full screen dialog -- `scrollable`: Scrollable content area -- `persistent`: Clicking outside doesn't close -- `transition`: Animation type - -### VMenu - -Context menu or dropdown menu. - -```vue - - - -``` - ---- - -## Typography & Icons - -### Text Hierarchy - -Use text classes for consistent typography. - -```vue - -``` - -### Icons with VIcon - -Material Design Icons integration. - -```vue - - - - - - -``` - ---- - -## Theming & Customization - -### Vuetify Theme Setup - -```typescript -// vuetify.ts -import { createVuetify } from 'vuetify' -import * as components from 'vuetify/components' -import * as directives from 'vuetify/directives' -import { aliases, mdi } from 'vuetify/iconsets/mdi-svg' -import '@mdi/js' - -export default createVuetify({ - components, - directives, - icons: { - defaultSet: 'mdi', - aliases, - sets: { mdi }, - }, - theme: { - defaultTheme: 'light', - themes: { - light: { - colors: { - primary: '#1976D2', - secondary: '#424242', - success: '#4CAF50', - warning: '#FFC107', - error: '#F44336', - info: '#2196F3', - }, - }, - dark: { - colors: { - primary: '#BB86FC', - secondary: '#03DAC6', - success: '#66BB6A', - warning: '#FFA726', - error: '#EF5350', - info: '#42A5F5', - }, - }, - }, - }, -}) -``` - -### Custom Color Palette - -```vue - -``` - -### Responsive Breakpoints - -```typescript -// Access breakpoints in components -import { useDisplay } from 'vuetify' - -const { xs, sm, md, lg, xl, mdAndUp, smAndUp } = useDisplay() - -// In template -v-if="mdAndUp" // Show on md and larger -v-if="smAndDown" // Show on sm and smaller -``` - ---- - -## Component Composition - -### Composite Components - -Create reusable component combinations. - -```vue - - - - - - - -``` - -### Wrapper Components - -Wrap Vuetify components with custom styling and behavior. - -```vue - - - - - - - -``` - ---- - -## Props & Slots - -### Working with Props - -```vue - - - -``` - -### Named Slots - -Most Vuetify components support multiple slots for customization. - -```vue - -``` - ---- - -## Advanced Patterns - -### Infinite Scroll with VList - -```vue - - - -``` - -### Expandable Rows in DataTable - -```vue - -``` - -### Modal with Scrollable Content - -```vue - -``` - ---- - -## Key Takeaways - -1. **Use responsive props** (cols, sm, md, lg) for mobile-first design -2. **Leverage slots** for customization without overriding components -3. **Combine validation** with clear error messages -4. **Use theming** for consistent visual design -5. **Extract composables** for reusable logic -6. **Test accessibility** from the start (next guide covers this in depth) -7. **Follow Material Design** principles for consistency -8. **Consider performance** with virtual scrolling and lazy loading - -**Next:** Explore [Vue 3 Composition API patterns](vue3-composition.md) for modern, maintainable components. diff --git a/plugins/vuetify-components/plugin.json b/plugins/vuetify-components/plugin.json index 2e4ce63..62a85f0 100644 --- a/plugins/vuetify-components/plugin.json +++ b/plugins/vuetify-components/plugin.json @@ -22,13 +22,11 @@ "responsive-design", "composition-api" ], - "categories": ["Framework", "Frontend", "UI/UX", "Accessibility"], - "skills": "skills/", - "contents": { - "instructions": [ - "instructions/vuetify-components.md", - "instructions/vue3-composition.md", - "instructions/accessibility-ux.md" - ] - } + "categories": [ + "Framework", + "Frontend", + "UI/UX", + "Accessibility" + ], + "skills": "skills/" } diff --git a/plugins/vuetify-components/instructions/accessibility-ux.md b/plugins/vuetify-components/skills/add-accessibility/SKILL.md similarity index 97% rename from plugins/vuetify-components/instructions/accessibility-ux.md rename to plugins/vuetify-components/skills/add-accessibility/SKILL.md index 3364cff..8cac523 100644 --- a/plugins/vuetify-components/instructions/accessibility-ux.md +++ b/plugins/vuetify-components/skills/add-accessibility/SKILL.md @@ -1,3 +1,20 @@ +--- +name: add-accessibility +description: Add WCAG-compliant accessibility and UX improvements to Vuetify components +--- + +# Add Accessibility Skill + +Audit and improve Vuetify Vue 3 components for WCAG compliance, keyboard navigation, ARIA labeling, color contrast, and overall UX quality. + +## When to Use + +Invoke this skill when you: +- Need to audit a component for accessibility issues +- Are adding ARIA labels, roles, or keyboard navigation support +- Want to ensure color contrast and visual accessibility standards +- Need to improve UX consistency and Vuetify component usage + # Accessibility & UX Best Practices Build inclusive, professional user interfaces that work for everyone. Master WCAG accessibility standards, semantic HTML, keyboard navigation, and accessibility testing. diff --git a/plugins/vuetify-components/skills/scaffold-component/SKILL.md b/plugins/vuetify-components/skills/scaffold-component/SKILL.md index 20ff43b..bd3c084 100644 --- a/plugins/vuetify-components/skills/scaffold-component/SKILL.md +++ b/plugins/vuetify-components/skills/scaffold-component/SKILL.md @@ -88,3 +88,1550 @@ Place the component in the appropriate directory: - Use ` +``` + +**Responsive Breakpoints**: +``` +xs: 0px (extra small) +sm: 600px (small) +md: 960px (medium) +lg: 1264px (large) +xl: 1904px (extra large) +``` + +**VCol Props**: +- `cols`: Default columns (1-12) at xs breakpoint +- `sm`, `md`, `lg`, `xl`: Columns at specific breakpoints +- `offset-*`: Offset columns at each breakpoint +- `order-*`: Reorder columns with flexbox + +### VSheet + +Flexible container for grouping content with consistent elevation and styling. + +```vue + + + + + rounded + color="primary" + class="pa-4 ma-2" +/> +``` + +**Usage Guidelines**: +- Use `VSheet` as a flexible container when `VCard` is overkill +- Elevation (shadow) for depth and visual hierarchy +- Combine with Vuetify spacing utilities (pa-*, ma-*, py-*, px-*) + +### VNavigationDrawer + +Persistent or temporary navigation sidebar. + +```vue + + + +``` + +**Props**: +- `v-model`: Control open/closed state +- `rail`: Collapse to icon-only mode +- `permanent`: Always visible (on large screens) +- `app`: Take full height including AppBar +- `width`: Custom drawer width (default 256px) + +### VAppBar + +Top application bar with title, actions, and navigation. + +```vue + + + +``` + +**Props**: +- `app`: Fix to top of screen +- `color`: Background color +- `dark`/`light`: Text color scheme +- `flat`: Remove elevation shadow +- `border`: Add bottom border instead of shadow + +--- + +## Data Display Components + +### VDataTable + +Powerful table component with sorting, filtering, and pagination. + +```vue + + + +``` + +**Key Features**: +- Two-way binding with `v-model:page` and `v-model:items-per-page` +- Search filtering across all columns +- Sortable columns (customize per column) +- Custom item rendering with scoped slots +- Loading state with spinner overlay + +### VList + +Flexible list component with items, groups, and avatars. + +```vue + + + +``` + +### VCard + +Container for content with header, text, and actions. + +```vue + +``` + +**Card Structure**: +- `VCardTitle`: Card heading +- `VCardSubtitle`: Optional subtitle +- `VCardText`: Main content area +- `VCardActions`: Footer with buttons +- Combine with `VImg`, `VDivider` for complex layouts + +### VChip + +Small, compact component for tags, categories, or selections. + +```vue + + + +``` + +--- + +## Form Components + +### VTextField + +Single-line text input with validation and icons. + +```vue + + + +``` + +**Props**: +- `type`: 'text', 'email', 'password', 'number', 'search', 'url', 'tel' +- `label`: Field label (floats on focus) +- `placeholder`: Input placeholder text +- `prepend-icon`/`append-icon`: Icons before/after input +- `clearable`: Show clear button when value exists +- `rules`: Array of validation functions +- `error-messages`: Display validation errors +- `hint`: Helper text below field +- `persistent-hint`: Always show hint (not just on focus) +- `readonly`: Prevent user input +- `disabled`: Disable field completely +- `variant`: 'outlined', 'filled', 'underlined', 'plain' +- `dense`: Smaller height +- `rounded`: Rounded corners + +### VSelect + +Dropdown selection with multiple choices. + +```vue + + + +``` + +**Props**: +- `multiple`: Allow multiple selections +- `chips`: Display selections as chips +- `search`: Enable search/filter +- `item-title`: Property name for display text +- `item-value`: Property name for actual value +- `clearable`: Show clear button +- `disabled`: Disable field + +### VCheckbox + +Checkbox for boolean input. + +```vue + + + +``` + +### VRadio & VRadioGroup + +Radio buttons for single selection from multiple options. + +```vue + + + +``` + +### VSwitch + +Toggle switch for boolean values. + +```vue + + + +``` + +--- + +## Dialog & Menu Patterns + +### VDialog + +Modal dialog for forms, confirmations, or detailed content. + +```vue + + + +``` + +**Props**: +- `max-width`: Maximum width (e.g., '500', '600', 'lg') +- `width`: Explicit width +- `fullscreen`: Full screen dialog +- `scrollable`: Scrollable content area +- `persistent`: Clicking outside doesn't close +- `transition`: Animation type + +### VMenu + +Context menu or dropdown menu. + +```vue + + + +``` + +--- + +## Typography & Icons + +### Text Hierarchy + +Use text classes for consistent typography. + +```vue + +``` + +### Icons with VIcon + +Material Design Icons integration. + +```vue + + + + + + +``` + +--- + +## Theming & Customization + +### Vuetify Theme Setup + +```typescript +// vuetify.ts +import { createVuetify } from 'vuetify' +import * as components from 'vuetify/components' +import * as directives from 'vuetify/directives' +import { aliases, mdi } from 'vuetify/iconsets/mdi-svg' +import '@mdi/js' + +export default createVuetify({ + components, + directives, + icons: { + defaultSet: 'mdi', + aliases, + sets: { mdi }, + }, + theme: { + defaultTheme: 'light', + themes: { + light: { + colors: { + primary: '#1976D2', + secondary: '#424242', + success: '#4CAF50', + warning: '#FFC107', + error: '#F44336', + info: '#2196F3', + }, + }, + dark: { + colors: { + primary: '#BB86FC', + secondary: '#03DAC6', + success: '#66BB6A', + warning: '#FFA726', + error: '#EF5350', + info: '#42A5F5', + }, + }, + }, + }, +}) +``` + +### Custom Color Palette + +```vue + +``` + +### Responsive Breakpoints + +```typescript +// Access breakpoints in components +import { useDisplay } from 'vuetify' + +const { xs, sm, md, lg, xl, mdAndUp, smAndUp } = useDisplay() + +// In template +v-if="mdAndUp" // Show on md and larger +v-if="smAndDown" // Show on sm and smaller +``` + +--- + +## Component Composition + +### Composite Components + +Create reusable component combinations. + +```vue + + + + + + + +``` + +### Wrapper Components + +Wrap Vuetify components with custom styling and behavior. + +```vue + + + + + + + +``` + +--- + +## Props & Slots + +### Working with Props + +```vue + + + +``` + +### Named Slots + +Most Vuetify components support multiple slots for customization. + +```vue + +``` + +--- + +## Advanced Patterns + +### Infinite Scroll with VList + +```vue + + + +``` + +### Expandable Rows in DataTable + +```vue + +``` + +### Modal with Scrollable Content + +```vue + +``` + +--- + +## Key Takeaways + +1. **Use responsive props** (cols, sm, md, lg) for mobile-first design +2. **Leverage slots** for customization without overriding components +3. **Combine validation** with clear error messages +4. **Use theming** for consistent visual design +5. **Extract composables** for reusable logic +6. **Test accessibility** from the start (next guide covers this in depth) +7. **Follow Material Design** principles for consistency +8. **Consider performance** with virtual scrolling and lazy loading + +**Next:** Explore [Vue 3 Composition API patterns](vue3-composition.md) for modern, maintainable components. diff --git a/plugins/vuetify-components/instructions/vue3-composition.md b/plugins/vuetify-components/skills/use-composition-api/SKILL.md similarity index 97% rename from plugins/vuetify-components/instructions/vue3-composition.md rename to plugins/vuetify-components/skills/use-composition-api/SKILL.md index 9ce4e34..f2141cd 100644 --- a/plugins/vuetify-components/instructions/vue3-composition.md +++ b/plugins/vuetify-components/skills/use-composition-api/SKILL.md @@ -1,3 +1,20 @@ +--- +name: use-composition-api +description: Build Vue 3 components using the Composition API with TypeScript and Vuetify +--- + +# Use Composition API Skill + +Build Vue 3 single-file components using the Composition API with TypeScript, covering reactive state, composables, lifecycle hooks, and performance optimization. + +## When to Use + +Invoke this skill when you: +- Are building a new Vue 3 component and want to use the Composition API correctly +- Need to refactor an Options API component to Composition API +- Want guidance on reactive state, composables, or lifecycle patterns +- Are implementing custom composables for shared logic + # Vue 3 Composition API Guide Master modern Vue 3 patterns with the Composition API. Learn reactive programming, composables, and performance optimization for professional, maintainable applications.