From 173208c62a30a39a00ab6e202b02eba8cff55cfe Mon Sep 17 00:00:00 2001 From: Collin Barrett <6483057+collinbarrett@users.noreply.github.com> Date: Mon, 28 Jul 2025 20:05:22 -0500 Subject: [PATCH] feat: generate copilot instructions --- .github/copilot-instructions.md | 150 ++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..794a46211 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,150 @@ +# FilterLists AI Coding Instructions + +## Architecture Overview + +FilterLists is a dual-stack application that serves as a comprehensive directory of filter and host lists for blocking advertisements, trackers, and malware: + +- **Backend**: .NET 9 Aspire application with clean architecture (Application/Infrastructure/API layers) +- **Frontend**: React + TypeScript SPA with Ant Design UI components +- **Database**: SQL Server with Entity Framework Core for data persistence +- **Deployment**: Containerized API on Azure, Static Web App frontend + +## Project Structure + +``` +services/ # .NET backend solution +├── FilterLists.AppHost/ # .NET Aspire orchestrator (main entry point) +├── Directory/ # Core domain logic +│ ├── FilterLists.Directory.Api/ # Minimal API endpoints +│ ├── FilterLists.Directory.Application/ # Query handlers (no MediatR) +│ ├── FilterLists.Directory.Infrastructure/ # EF Core, DbContext +│ └── data/ # JSON seed data files +web/ # React frontend +infra/cloudflare-workers/ # CDN edge workers +``` + +## Key Patterns & Conventions + +### Data-Driven Architecture + +- **Seed Data**: All domain data lives in JSON files under `services/Directory/data/` +- **Migrations**: EF Core migrations are auto-generated from JSON changes via `lint.sh` +- **Read-Only DbContext**: `QueryDbContext` throws on save operations - data changes only via migrations + +### Query Pattern (No CQRS/MediatR) + +```csharp +public static class GetLists +{ + public class Query(QueryDbContext ctx) + { + public async Task> ExecuteAsync(CancellationToken ct) => + await ctx.FilterLists.Select(f => new Response(...)).ToListAsync(ct); + } + public sealed record Response(...); +} +``` + +### Entity Configuration Pattern + +```csharp +internal sealed class FilterListTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) => + builder.HasDataJsonFile(); // Loads from JSON +} +``` + +## Development Workflows + +### Local Development + +```bash +# Start with .NET Aspire (includes SQL Server container) +cd services/FilterLists.AppHost +dotnet run + +# Frontend development server +cd web +npm start +``` + +### Data Changes + +1. Edit JSON files in `services/Directory/data/` +2. Run `./lint.sh` to sort/format JSON consistently +3. Generate migration: `dotnet ef migrations add -p FilterLists.Directory.Infrastructure.Migrations -s FilterLists.Directory.Api` +4. Migration auto-applies on startup via `MigrationService` + +### Adding EF Migrations + +Always run from `services/Directory/` with these specific parameters: + +```bash +dotnet ef migrations add -p FilterLists.Directory.Infrastructure.Migrations -s FilterLists.Directory.Api +``` + +## Domain Model Key Relationships + +- **FilterList**: Core entity with many-to-many relationships via junction tables +- **Maintainer**: People/orgs who maintain filter lists +- **License**: Legal permissions for filter list usage +- **Syntax**: Technical format (Adblock Plus, hosts file, etc.) +- **Language**: Target languages for localized lists +- **Tag**: Categorization (ads, trackers, malware, etc.) + +Complex relationships: Fork (upstream/downstream), Merge (includes/included), Dependent (dependencies). + +## API Conventions + +### Minimal API Endpoints + +- Endpoints defined in `FilterLists.Directory.Api/Endpoints.cs` +- Output caching with 1-day expiration for all GET endpoints +- OpenAPI documentation with detailed examples +- CORS enabled for web frontend consumption + +### Response Patterns + +All endpoints return strongly-typed records with XML documentation examples: + +```csharp +/// The identifier. +public sealed record Response(int Id, string Name, ...); +``` + +## Build & Deployment + +### GitHub Actions + +- **Directory API**: Builds Docker image, deploys to Azure Container Registry +- **Web Frontend**: Builds static assets, deploys to Azure Static Web Apps +- **Path-based triggers**: Only builds when relevant files change + +### Docker Configuration + +API containerized with multi-stage build. Database runs in Docker volume with persistent storage (configure password via user secrets). + +## React Frontend Specifics + +### Tech Stack + +- React 19 + TypeScript +- Ant Design 4.x components +- React Router 5.x (class-based routing) +- Custom proxy configuration for API calls + +### Component Patterns + +- Functional components with hooks +- Props interfaces defined inline or in `interfaces/` folder +- Ant Design `Table` component for main list display +- Tag clouds for maintainers, languages, syntaxes + +## Critical Notes + +- **No MediatR**: Use direct query pattern instead +- **JSON-first**: All data changes start with JSON edits, not EF model changes +- **Read-only runtime**: Database modifications only via migrations +- **Aspire orchestration**: Always start development via `FilterLists.AppHost` +- **Unique naming**: All FilterList names must be unique and in title case