Imported from harsul/hs-template (
AGENTS.md). Install upstream withnpx skills add harsul/hs-template. Copyright stays with the author.
AGENTS.md — Codebase Guide for AI Agents
This file helps AI coding assistants navigate and understand the HsTemplate project.
Deep-Dive Reference Files
For detailed architecture information, see these companion files in .devin/context/:
| File | Contents |
|---|---|
| API_REFERENCE.md | All 54+ endpoint signatures, request/response contracts, validation rules, rate limiting |
| BACKEND_ARCHITECTURE.md | Program.cs startup pipeline, DbContext entities, services, scoring, Aspire host, CI/CD |
| FRONTEND_ARCHITECTURE.md | Provider hierarchy, routing, auth, hooks, API services, query keys, theme, components |
| TEST_INFRASTRUCTURE.md | TestWebApplicationFactory, test helpers, test patterns, 250 test inventory |
Project Overview
HsTemplate is a full-stack quiz management application with:
- Backend: ASP.NET Core 10 Minimal APIs with PostgreSQL
- Frontend: React 19 + TypeScript + Material UI 7
- Orchestration: .NET Aspire (manages all infrastructure locally)
- Auth: Keycloak (JWT Bearer tokens)
- Cache: Redis (output caching)
Quick Commands
# Run the full stack (starts all services via Aspire)
dotnet run --project src/HsTemplate.AppHost
# Backend tests
dotnet test tests/HsTemplate.Server.xUnit # unit tests
dotnet test tests/HsTemplate.Server.xIntegration # integration tests
dotnet test # all tests
# Frontend commands (run from src/frontend/)
npm install # install dependencies
npm run dev # dev server
npm run build # production build (tsc + vite)
npm run lint # ESLint
npx tsc --noEmit # type check only
npm test # unit tests (vitest)
npm run test:e2e # E2E tests (playwright)
# Regenerate OpenAPI types after backend changes
npm run generate:api:refresh
Repository Layout
HsTemplate/
├── src/
│ ├── HsTemplate.AppHost/ # .NET Aspire host (orchestrates everything)
│ │ ├── AppHost.cs # Service wiring: Redis, PostgreSQL, Keycloak, Server, Frontend
│ │ └── KeycloakRealm.json # Keycloak realm configuration
│ │
│ ├── HsTemplate.Server/ # Backend API
│ │ ├── Program.cs # App startup, middleware, service registration
│ │ ├── GlobalExceptionHandler.cs # Global error handling
│ │ ├── Data/
│ │ │ ├── AppDbContext.cs # EF Core context (soft deletes, query filters, seeding)
│ │ │ └── Migrations/ # EF Core database migrations
│ │ ├── Models/ # Entity classes
│ │ │ ├── Quiz.cs # Core entity + enums (QuizStatus, QuestionType, Difficulty)
│ │ │ ├── Question.cs # Quiz question
│ │ │ ├── AnswerOption.cs # Answer choice for a question
│ │ │ ├── Category.cs # Quiz category
│ │ │ ├── QuestionBankItem.cs # Reusable question bank entry
│ │ │ ├── QuizTemplate.cs # Quiz template
│ │ │ └── QuizParticipant.cs # Participant tracking
│ │ ├── Endpoints/ # Minimal API endpoint groups
│ │ │ ├── Quizzes/ # CRUD, status transitions, soft delete, duplication
│ │ │ ├── Categories/ # Category management
│ │ │ ├── QuestionBank/ # Question bank CRUD
│ │ │ ├── Templates/ # Template management + create-from-template
│ │ │ ├── Participants/ # Quiz participation tracking
│ │ │ ├── ImportExport/ # JSON import/export
│ │ │ └── Helpers/ # Shared endpoint helpers
│ │ └── Services/
│ │ ├── IUserProvider.cs # User abstraction interface
│ │ └── UserProvider.cs # Extracts user info from JWT claims
│ │
│ ├── HsTemplate.ServiceDefaults/ # Shared Aspire service configuration
│ │
│ └── frontend/ # React SPA
│ ├── src/
│ │ ├── App.tsx # Route definitions (react-router-dom)
│ │ ├── main.tsx # App bootstrap with providers
│ │ ├── theme.ts # Material UI theme (light/dark)
│ │ │
│ │ ├── api/ # API client layer
│ │ │ ├── client.ts # Base fetch wrapper with auth token injection
│ │ │ ├── schema.d.ts # Auto-generated OpenAPI types
│ │ │ ├── quizService.ts # Quiz API calls
│ │ │ ├── categoryService.ts
│ │ │ ├── questionBankService.ts
│ │ │ ├── templateService.ts
│ │ │ ├── participantService.ts
│ │ │ └── importExportService.ts
│ │ │
│ │ ├── components/
│ │ │ ├── auth/ProtectedRoute.tsx # Auth guard
│ │ │ ├── layout/ # Header, Sidebar, MainLayout
│ │ │ └── shared/ # Reusable components (see below)
│ │ │
│ │ ├── hooks/
│ │ │ ├── useAuth.ts # Authentication hook (Keycloak)
│ │ │ ├── useApiQuery.ts # Data fetching with loading/error states
│ │ │ ├── usePreferences.ts # User preferences (theme, sidebar)
│ │ │ ├── useToast.ts # Toast notifications
│ │ │ └── useUndoRedo.ts # Undo/redo state management
│ │ │
│ │ ├── pages/ # Route-level components
│ │ │ ├── QuizzesPage.tsx # Quiz list with filters/sort
│ │ │ ├── QuizDetailPage/ # Quiz detail (Overview + Data tabs)
│ │ │ ├── CategoriesPage.tsx
│ │ │ ├── QuestionBankPage.tsx
│ │ │ ├── TemplatesPage.tsx
│ │ │ ├── TrashPage.tsx # Soft-deleted quizzes
│ │ │ ├── LiveTestPage.tsx # Live quiz testing
│ │ │ └── TakeQuizPage.tsx # Public quiz-taking
│ │ │
│ │ ├── store/ # React Context providers
│ │ │ ├── auth.tsx # AuthProvider (Keycloak)
│ │ │ ├── preferences.tsx # PreferencesProvider (theme, layout)
│ │ │ └── toast.tsx # ToastProvider (notifications)
│ │ │
│ │ └── __tests__/ # Unit tests (mirrors src/ structure)
│ │
│ └── e2e/ # Playwright E2E tests
│
└── tests/
├── HsTemplate.Server.xUnit/ # Backend unit tests (xUnit 3)
└── HsTemplate.Server.xIntegration/ # Backend integration tests
├── Infrastructure/
│ └── TestWebApplicationFactory.cs # In-memory DB test setup
└── Tests/ # Endpoint integration tests
Key Shared Components (frontend)
Located in src/frontend/src/components/shared/:
| Component | Purpose |
|---|---|
FilterBar |
Reusable filter/sort/search bar (used by all list pages) |
PageHeader |
Page title with action buttons |
EmptyState |
Empty state illustrations with CTA |
ConfirmDialog |
Confirmation modal |
SearchInput |
Debounced search field |
QuizStatusChip |
Status badge (Draft/Live/Closed) |
ElevatedCard |
Styled card with hover effect |
QuestionFormFields |
Question editor (shared constants: QUESTION_TYPE_LABELS, DIFFICULTY_COLORS) |
ImportFromBankDialog |
Import questions from bank |
QuizPreviewDialog |
Quiz preview modal |
KeywordInput |
Tag/keyword input field |
MarkdownField |
Markdown editor with preview |
DesignTab |
Quiz design/styling editor |
GlobalSearch |
Header search bar with Ctrl+K, grouped results dropdown, recent searches |
Architecture Patterns
Backend
- Minimal APIs — no controllers; endpoints organized by feature in
Endpoints/directory - Contracts pattern — request/response DTOs defined as records in
*Contracts.csfiles - Soft deletes —
DeletedAtfield with EF Core global query filters - Aspire integration — service discovery, health checks, OpenTelemetry
- JWT auth — Keycloak issues tokens; backend validates via
AddKeycloakJwtBearer()
Frontend
- Service layer — all API calls go through
api/*Service.ts, usingclient.tsas base - OpenAPI types —
schema.d.tsis auto-generated from backend OpenAPI spec - Context providers — Auth, Preferences, Toast wrapped in
main.tsx - Custom hooks —
useApiQueryfor data fetching,useAuthfor auth state - Material UI 7 — all styling via MUI components and
sxprop
Database
- PostgreSQL with EF Core 10
- Array columns for keywords/tags (PostgreSQL native arrays)
- JSONB for participant answers
- Enum mappings for QuizStatus, QuestionType, Difficulty
Important Enums (Backend)
QuizStatus: Draft, Live, Closed
QuestionType: MultipleChoice, TrueFalse, ShortAnswer, MultiSelect
Difficulty: Easy, Medium, Hard
QuizStyle: Classic, Modern, Minimal, Colorful
ParticipantStatus: InProgress, Completed, Abandoned
API Endpoint Groups
| Prefix | File | Purpose |
|---|---|---|
/api/quizzes |
QuizEndpoints.cs |
Full quiz CRUD, status transitions, soft delete, duplication |
/api/categories |
CategoryEndpoints.cs |
Category management |
/api/question-bank |
QuestionBankEndpoints.cs |
Question bank CRUD |
/api/templates |
TemplateEndpoints.cs |
Template CRUD, create quiz from template |
/api/quizzes/{id}/participants |
ParticipantEndpoints.cs |
Participant tracking and scoring |
/api/import-export |
ImportExportEndpoints.cs |
JSON import/export |
/api/search |
SearchEndpoints.cs |
Global search across all entities |
Adding a New Feature — Checklist
Backend
- Add/update model in
Models/ - Add migration:
dotnet ef migrations add <Name> --project src/HsTemplate.Server - Create
Endpoints/{Feature}/{Feature}Endpoints.csand{Feature}Contracts.cs - Register endpoints in
Program.cs - Write integration tests in
tests/HsTemplate.Server.xIntegration/Tests/
Frontend
- Add API service in
src/api/{feature}Service.ts - Regenerate types:
npm run generate:api:refresh - Create page component in
src/pages/ - Add route in
App.tsx - Write tests in
src/__tests__/
CI/CD
GitHub Actions workflow (.github/workflows/ci.yml) runs on push to main/develop and on PRs:
- Backend job: restore, build, unit tests, integration tests (skipped if no backend changes)
- Frontend job: install, lint, type-check, unit tests, build (skipped if no frontend changes)
- Path detection via
dorny/paths-filter
