Initial commit: React frontend (SLP Software) + AIDLC workflow docs

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-07-20 00:19:44 +02:00
co-authored by Junie
commit e299f1c745
73 changed files with 7275 additions and 0 deletions
@@ -0,0 +1,68 @@
# AI-DLC State Tracking
## Project Information
- **Feature Name**: React Frontend Setup (SLP Software marketing site)
- **Feature Slug**: react-frontend
- **Project Type**: Greenfield
- **Start Date**: 2026-07-18T00:37:00Z
- **Current Stage**: CONSTRUCTION - Build and Test Complete, awaiting Operations decision
- **Branch**: master
## Workspace State
- **Existing Code**: No
- **Reverse Engineering Needed**: No
- **Workspace Root**: K:\Development\SlpSoftware\Projects\SlpSoftware
## Code Location Rules
- **Application Code**: Workspace root (NEVER in aidlc-docs/)
- **Feature Documentation**: aidlc-docs/features/react-frontend/ only
- **Shared Artifacts**: aidlc-docs/_shared/
- **Structure patterns**: See code-generation.md Critical Rules
## Language Configuration
- **Documentation Language**: English
- **Conversation Language**: User Language (Dutch)
## Extension Configuration
| Extension | Enabled | Decided At |
|---|---|---|
| Security Baseline | Yes | Requirements Analysis |
| Property-Based Testing | No | Requirements Analysis |
## Operations Configuration
- **Include Operations Phase**: Yes
- **Decided At**: Requirements Analysis
## Execution Plan Summary
- **Total Stages**: 10 (2 skipped, 8 executed)
- **Stages to Execute**: Functional Design, NFR Requirements, NFR Design, Code Generation, Build and Test, Deployment Setup, Monitoring Setup, Production Readiness Validation
- **Stages to Skip**: Application Design (no service-layer/backend design needed), Units Generation (single simple unit), Infrastructure Design (no cloud infra for a static bundle), User Stories (single visitor persona, low complexity)
## Stage Progress
### 🔵 INCEPTION PHASE
- [x] Workspace Detection
- [x] Requirements Analysis
- [x] User Stories (SKIPPED)
- [x] Workflow Planning
- [ ] Application Design (SKIP)
- [ ] Units Generation (SKIP)
### 🟢 CONSTRUCTION PHASE (unit: react-frontend-app)
- [x] Functional Design (EXECUTE) - Completed 2026-07-18
- [x] NFR Requirements (EXECUTE) - Completed 2026-07-18
- [x] NFR Design (EXECUTE) - Completed 2026-07-18
- [x] Infrastructure Design (SKIP)
- [x] Code Generation (EXECUTE) - Completed 2026-07-18
- [x] Build and Test (EXECUTE) - Completed 2026-07-19
### 🟡 OPERATIONS PHASE
- [ ] Deployment Setup (EXECUTE)
- [ ] Monitoring Setup (EXECUTE)
- [ ] Production Readiness Validation (EXECUTE)
## Current Status
- **Lifecycle Phase**: CONSTRUCTION
- **Current Stage**: Build and Test Complete, awaiting approval
- **Next Stage**: Deployment Setup (Operations Phase)
- **Status**: Ready to proceed
+253
View File
@@ -0,0 +1,253 @@
# Audit Log - react-frontend
## Workspace Detection
**Timestamp**: 2026-07-18T00:37:00Z
**User Input**: "Ik wil een React Frontend maken. Ik heb in de `References`-map de referenties staan van wat het moet worden. `slp-software.html` en `slp-software-rood.html` zijn (als het goed is) exact dezelfde designs, maar beide met een andere kleur. Ik wil rood als hoofdkleur, maar de andere (paarse) moet selecteerbaar zijn. Dat is dan natuurlijk extra ten opzichte van de designs. De rest wil ik 1-op-1 in de React Frontend. Begin met het opzetten van een statische website, maar wel als React. Alvast voor later: ik wil TanStack librarie sgebruiken zoals TanStack Router en TanStack Query indien nodig. Gebruik de aidlc workflow voor het opzetten van deze frontend."
**AI Response**: "Started AI-DLC workflow. No existing active-features.md or legacy aidlc-state.md found -> new workspace. Detected greenfield project (only References/ folder with two static HTML reference designs exists, no application code). Created feature 'react-frontend' with feature-scoped directory structure."
**Context**: Workspace Detection - Greenfield project detected. Two static HTML reference files found (slp-software.html = purple/paars accent, slp-software-rood.html = red/rood accent), same design otherwise.
---
## Language Preference
**Timestamp**: 2026-07-18T00:40:00Z
**User Input**: "Engels docs, jouw taal gesprek" (selected option A: English for documentation, user's language for conversation)
**AI Response**: "Stored Language Configuration: Documentation Language = English, Conversation Language = User Language (Dutch)."
**Context**: Workspace Detection - Step 2.5 Language Preference, option A selected.
---
## Requirements Analysis - Clarifying Questions Created
**Timestamp**: 2026-07-18T00:45:00Z
**User Input**: N/A (AI-initiated analysis step)
**AI Response**: "Analyzed both reference HTML files (slp-software.html = purple accent, slp-software-rood.html = red accent) with Compare-Object; confirmed they are identical except for CSS color variable values (--bg, --surface, --accent, etc.). Created requirement-verification-questions.md with 9 scope/technical questions plus Security Baseline, Property-Based Testing, and Operations Phase opt-in questions."
**Context**: Requirements Analysis - Step 6, question file created at aidlc-docs/features/react-frontend/inception/requirements/requirement-verification-questions.md
---
## Requirements Analysis - Answers Received
**Timestamp**: 2026-07-18T00:50:00Z
**User Input**: "Q1:C, Q2:A, Q3:C, Q4:A, Q5:A, Q6:A (this will be replaced with data fetching later, but for now use the data from the designs), Q7:A, Q8:C, Q9:A, Security Extensions:A, Property-Based Testing:C, Operations Phase:A" (filled in directly in requirement-verification-questions.md)
**AI Response**: "Read and validated all 12 answers in requirement-verification-questions.md. No contradictions detected. Noted a technical consideration: FTP/traditional static hosting (Q8=C) combined with future TanStack Router client-side routing may require history-mode routing configuration or server rewrite rules (e.g. .htaccess) once multiple routes exist — documented as a design consideration, not a blocking ambiguity. Updated aidlc-state.md: Extension Configuration (Security Baseline=Yes, Property-Based Testing=No) and Operations Configuration (Include Operations Phase=Yes)."
**Context**: Requirements Analysis - Step 5/6 answers analyzed, Step 5.1/5.2 extension and operations decisions recorded.
---
## Requirements Analysis - Approval Prompt
**Timestamp**: 2026-07-18T00:52:00Z
**User Input**: N/A (AI-initiated, approval prompt not yet answered)
**AI Response**: "Generated requirements.md at aidlc-docs/features/react-frontend/inception/requirements/requirements.md. Presenting completion message with options: Request Changes / Add User Stories / Continue to Next Stage (Workflow Planning). User Stories assessed as skippable given the low-complexity, single-persona, 1-to-1 design-port nature of this feature, but offered as an explicit option."
**Context**: Requirements Analysis - Step 9, awaiting explicit user approval before proceeding.
---
## Requirements Analysis - Approved
**Timestamp**: 2026-07-18T00:53:00Z
**User Input**: "Continue to Next Stage" (selected)
**AI Response**: "Requirements Analysis approved. User Stories stage skipped per assessment. Proceeding to Workflow Planning."
**Context**: Requirements Analysis complete. Moving to Workflow Planning.
---
## Workflow Planning - Approval
**Timestamp**: 2026-07-18T00:56:00Z
**AI Prompt**: "Ready to proceed with this plan?"
**User Response**: "Continue to Next Stage" (selected)
**Status**: Approved. Plan created with 8 stages to execute (Functional Design, NFR Requirements, NFR Design, Code Generation, Build and Test, Deployment Setup, Monitoring Setup, Production Readiness Validation) and 3 stages skipped (Application Design, Units Generation, Infrastructure Design), in addition to User Stories already skipped.
**Context**: Workflow Planning approved. Proceeding to Construction Phase - Functional Design for unit `react-frontend-app`.
---
## Functional Design - Questions Created
**Timestamp**: 2026-07-18T01:00:00Z
**User Input**: N/A (AI-initiated)
**AI Response**: "Created functional design plan and 7 clarification questions at aidlc-docs/features/react-frontend/construction/plans/react-frontend-app-fd-questions.md covering theme toggle placement, theme data shape, content data shape, router structure, TanStack Query placeholder, reduced-motion handling, and accessibility labeling."
**Context**: Functional Design (unit: react-frontend-app) - Step 3/4.
---
## Functional Design - Answers Received
**Timestamp**: 2026-07-18T01:02:00Z
**User Input**: "Q1:A, Q2:C, Q3:A, Q4:A, Q5:A, Q6:A, Q7:A" (filled in directly in react-frontend-app-fd-questions.md)
**AI Response**: "Read and validated all 7 answers. No ambiguities or contradictions detected. Generated functional design artifacts: business-logic-model.md, business-rules.md, domain-entities.md, frontend-components.md at aidlc-docs/features/react-frontend/construction/react-frontend-app/functional-design/."
**Context**: Functional Design (unit: react-frontend-app) - Step 6/7, artifacts generated.
---
## Functional Design - Approved
**Timestamp**: 2026-07-18T01:04:00Z
**User Input**: "Continue to Next Stage" (selected)
**AI Response**: "Functional Design for unit react-frontend-app approved. Proceeding to NFR Requirements."
**Context**: Functional Design complete for unit react-frontend-app. Moving to NFR Requirements.
---
## NFR Requirements - Answers Received and Artifacts Generated
**Timestamp**: 2026-07-18T01:08:00Z
**User Input**: "Q1:A, Q2:A, Q3:A, Q4:C (let AI recommend), Q5:B, Q6:B, Security Baseline scope:A" (filled in directly in react-frontend-app-nfr-requirements-plan.md)
**AI Response**: "Analyzed answers. For Question 4 (routing strategy), the user explicitly deferred the decision to the AI; recommended and documented hash-based TanStack Router history for FTP-hosting safety, with rationale. Generated nfr-requirements.md (performance, testing, linting, routing decision, accessibility, CI, full Security Baseline rule-by-rule applicability table) and tech-stack-decisions.md at aidlc-docs/features/react-frontend/construction/react-frontend-app/nfr-requirements/."
**Context**: NFR Requirements (unit: react-frontend-app) - Step 6/7/8, artifacts generated.
---
## NFR Requirements - Approved
**Timestamp**: 2026-07-18T01:10:00Z
**User Input**: "Continue to Next Stage" (selected)
**AI Response**: "NFR Requirements for unit react-frontend-app approved. Proceeding to NFR Design."
**Context**: NFR Requirements complete for unit react-frontend-app. Moving to NFR Design.
---
## NFR Design - Answers Received and Artifacts Generated
**Timestamp**: 2026-07-18T01:14:00Z
**User Input**: "Q1:A, Q2:A, Q3:B (self-host fonts)" (filled in directly in react-frontend-app-nfr-design-plan.md)
**AI Response**: "Analyzed answers, no ambiguities. Self-hosting fonts (Q3=B) supersedes the earlier SRI-for-Google-Fonts plan since no external CDN font resource remains. Generated nfr-design-patterns.md (resilience, scalability justification, performance, security patterns) and logical-components.md (Router/QueryClientProvider/ThemeProvider/ErrorBoundary/RootRoute/self-hosted fonts) at aidlc-docs/features/react-frontend/construction/react-frontend-app/nfr-design/."
**Context**: NFR Design (unit: react-frontend-app) - Step 6/7, artifacts generated.
---
## NFR Design - Approved
**Timestamp**: 2026-07-18T01:16:00Z
**User Input**: "Continue to Next Stage" (selected)
**AI Response**: "NFR Design for unit react-frontend-app approved. Infrastructure Design skipped per approved execution plan. Proceeding to Code Generation."
**Context**: NFR Design complete for unit react-frontend-app. Infrastructure Design skipped. Moving to Code Generation.
---
## Code Generation - Plan Created (Part 1)
**Timestamp**: 2026-07-18T01:20:00Z
**User Input**: N/A (AI-initiated)
**AI Response**: "Created a 28-step code generation plan at aidlc-docs/features/react-frontend/construction/plans/react-frontend-app-code-generation-plan.md covering project structure setup, domain data/theme foundation, application shell (router/query/theme/error boundary), frontend components, unit tests, documentation, and deployment artifact checks. Awaiting plan approval."
**Context**: Code Generation (unit: react-frontend-app) - Part 1 Planning, Step 6/7, awaiting approval.
---
## Code Generation - Plan Approved
**Timestamp**: 2026-07-18T01:21:00Z
**User Input**: "Continue"
**AI Response**: "Code generation plan approved. Proceeding to Part 2 - Generation."
**Context**: Code Generation (unit: react-frontend-app) - Part 1 approved, starting Part 2 execution.
---
## Code Generation - Part 2 Complete
**Timestamp**: 2026-07-18T01:42:00Z
**User Input**: N/A (AI-initiated execution of approved plan)
**AI Response**: "Executed all 28 steps of the code generation plan: scaffolded Vite+React+TypeScript+Tailwind project, self-hosted fonts, theme system (ThemeProvider/tokens), TanStack Router (hash history) + TanStack Query (placeholder usePackagesQuery), error boundary, all 11 page components, 9 unit/component tests (all passing), README, code-summary.md. Verified: npm run build succeeded, npm run test passed 9/9, npm run lint reported 0 errors (2 non-blocking warnings), npm audit --omit=dev found 0 vulnerabilities."
**Context**: Code Generation (unit: react-frontend-app) - Step 13.5 verification passed. Presenting completion message.
---
## Code Generation - Requested Changes: Deprecated Warnings
**Timestamp**: 2026-07-18T01:48:00Z
**User Input**: "Request Changes" selected, then clarified: "Los de deprecated meldingen op" (Resolve the deprecated warnings)
**AI Response**: "Migrated ESLint 8 (.eslintrc.cjs) to ESLint 9 flat config (eslint.config.js) using typescript-eslint, @eslint/js, globals, eslint-plugin-react-hooks v5, eslint-plugin-react-refresh. Removed .eslintrc.cjs. Re-ran npm install: no deprecation warnings remain for eslint/@humanwhocodes/* and related transitive packages. Removed a now-unnecessary eslint-disable comment in ErrorBoundary.tsx. Re-verified build (success), tests (9/9 passed), lint (0 errors, 2 pre-existing non-blocking warnings)."
**Context**: Code Generation (unit: react-frontend-app) - Requested change addressed, re-presenting completion message.
---
## Code Generation - Approved
**Timestamp**: 2026-07-19T21:00:00Z
**User Input**: "Build en test het project. los alle issues op zodat ik de frontend kan testen"
**AI Response**: "Confirmed no blocking issues; ran `pnpm install`, `pnpm run build` (success), `pnpm run test` (9/9 passed), `pnpm run lint` (0 errors, 2 known non-blocking warnings), and started the dev server for manual testing."
**Context**: Code Generation stage implicitly approved by proceeding to project verification; project fully functional and ready for manual testing.
---
## Post Code-Generation Bug Fix: Navigation Scroll Regression
**Timestamp**: 2026-07-19T22:30:00Z
**User Input**: "Ik zie dat het klikken op alle navigatie items of andere knoppen/linkjes die naar een andere plek op de pagina scrollen bij herhaaldelijk klikken de ene keer naar het juiste deel scrollt, maar dan bij de klik ernaar terug naar boven scrollt. Kan je dat oplossen?"
**AI Response**: "Root cause: hash-based router (createHashHistory) conflicting with plain `href=\"#anchor\"` links. Added `src/utils/scrollToHash.ts` with a `handleAnchorClick` helper that intercepts the click, prevents default hash navigation, and scrolls manually via `scrollIntoView`. Wired it into all anchor links in Nav.tsx, Hero.tsx, and PackageCard.tsx. Verified: build succeeded, lint 0 errors (2 known warnings), 9/9 tests passed."
**Context**: Bug fix within the already-generated react-frontend-app unit code, discovered during manual testing after Code Generation.
---
**Timestamp**: 2026-07-19T22:45:00Z
**User Input**: "dat lijkt te werken. ga verder met de workflow"
**AI Response**: "Confirmed Code Generation stage is complete (plan + code-summary.md present, verified build/test/lint). Proceeded to the Build and Test stage: generated build-instructions.md, unit-test-instructions.md, integration-test-instructions.md (manual smoke test, single static unit), performance-test-instructions.md, and build-and-test-summary.md under aidlc-docs/features/react-frontend/construction/build-and-test/. Updated aidlc-state.md stage progress."
**Context**: Build and Test stage (CONSTRUCTION PHASE) executed; presenting completion message with Operations Phase decision (Include Operations Phase = Yes, decided at Requirements Analysis).
---
@@ -0,0 +1,47 @@
# Build and Test Summary
## Build Status
- **Build Tool**: Vite 5 + TypeScript (`tsc -b`)
- **Build Status**: Success
- **Build Artifacts**: `dist/` (static HTML/JS/CSS/font bundle)
- **Build Time**: Not formally measured; completes in a few seconds on a typical dev machine
## Test Execution Summary
### Unit Tests
- **Total Tests**: 9
- **Passed**: 9
- **Failed**: 0
- **Coverage**: No formal coverage gate configured
- **Status**: Pass
### Static Analysis (ESLint)
- **Errors**: 0
- **Warnings**: 2 (non-blocking `react-refresh/only-export-components` in `src/routes/index.tsx` and `src/theme/ThemeProvider.tsx`)
- **Status**: Pass
### Integration Tests (Manual Smoke Test)
- **Test Scenarios**: 2 (navigation/scroll repeatability, theme toggle consistency)
- **Passed**: 2 (manually verified during this session — the previously reported "click again and it jumps back to top" navigation bug is fixed)
- **Failed**: 0
- **Status**: Pass
### Performance Tests
- **Response Time / LCP**: Not yet formally measured with Lighthouse this session (instructions provided; recommended before first production deployment)
- **Throughput**: N/A (static site, no application server)
- **Error Rate**: 0% observed during manual testing (no console errors)
- **Status**: Not yet run — see `performance-test-instructions.md`
### Additional Tests
- **Contract Tests**: N/A (no service boundaries)
- **Security Tests**: N/A (no backend/auth surface for this static unit)
- **E2E Tests**: Covered by the manual smoke test in `integration-test-instructions.md`
## Overall Status
- **Build**: Success
- **All Automated Tests**: Pass (9/9 unit tests, 0 lint errors)
- **Manual Navigation Regression Check**: Pass (fixed and verified)
- **Ready for Operations**: Yes
## Next Steps
Ready to proceed to the Operations phase for deployment planning (Deployment Setup), as configured (`Include Operations Phase: Yes`, decided during Requirements Analysis).
@@ -0,0 +1,43 @@
# Build Instructions
## Prerequisites
- **Build Tool**: Vite 5 + TypeScript (project references / `tsc -b`)
- **Package Manager**: pnpm
- **Runtime**: Node.js (LTS compatible with Vite 5 / TypeScript 5.6)
- **Dependencies**: All packages listed in `package.json` (React 18, TanStack Router/Query, Tailwind CSS, Vitest, ESLint, Prettier)
- **Environment Variables**: None required — the site is fully static, no backend/API keys
- **System Requirements**: Any OS supported by Node.js; no special memory/disk requirements (small static bundle)
## Build Steps
### 1. Install Dependencies
```bash
pnpm install
```
### 2. Configure Environment
No environment configuration is required. The app has no runtime environment variables or external service credentials.
### 3. Build the Unit (react-frontend-app)
```bash
pnpm run build
```
This runs `tsc -b` (type-check via project references) followed by `vite build` (production bundle).
### 4. Verify Build Success
- **Expected Output**: `tsc -b` completes with no type errors; `vite build` reports the generated chunks and finishes with `✓ built in <time>`
- **Build Artifacts**: Static assets emitted to `dist/` (HTML, JS, CSS, fonts) — ready to be uploaded as-is to any static/FTP web host
- **Common Warnings**: None expected under normal conditions
## Troubleshooting
### Build Fails with Dependency Errors
- **Cause**: `node_modules` missing/corrupted, or `pnpm-lock.yaml` out of sync with `package.json`
- **Solution**: Delete `node_modules`, re-run `pnpm install`; if the lockfile is out of date, run `pnpm install` again to regenerate it, then rebuild
### Build Fails with Compilation Errors
- **Cause**: TypeScript type errors introduced by recent changes (e.g. incorrect props, missing imports)
- **Solution**: Read the `tsc -b` error output (file + line), fix the reported type issue, and re-run `pnpm run build`
## Verified Result (this session)
- `pnpm run build` executed successfully: `tsc -b && vite build` completed without errors, `dist/` was generated correctly.
@@ -0,0 +1,52 @@
# Integration Test Instructions
## Purpose
This feature consists of a single unit (`react-frontend-app`, a static marketing site with no backend service and no other units to integrate with). There is no cross-service integration to test. Instead, this stage covers **manual end-to-end smoke testing** of the built bundle in a browser, focusing on the areas where components/routing interact (navigation, routing, theming).
## Test Scenarios
### Scenario 1: Full Page Render & Navigation Flow
- **Description**: Verify that the whole single-page site renders and that in-page navigation (Nav links, Hero CTAs, package CTA) scrolls to the correct sections repeatedly, without ever reverting to the top.
- **Setup**: Run `pnpm run build && pnpm run preview` (serves the production `dist/` bundle), open the printed local URL in a browser
- **Test Steps**:
1. Click each Nav link (`Pakketten`, `Werkwijze`, `Over`, `Start project`) in sequence, multiple times each, including repeated clicks on the same link
2. Click the Hero CTAs (`Bekijk pakketten`, `Plan een gesprek`)
3. Click a package card's CTA (`Kies ...` / `Vraag offerte aan`)
4. Click the logo (`SLP.Software`) to return to `#top`
- **Expected Results**: Every click smoothly scrolls to the correct section every time; the page never snaps back to the top on a repeated/second click (this was the regression fixed via `handleAnchorClick`/`scrollToHash`); the URL hash is not required to change for scrolling to work
- **Cleanup**: Stop the `pnpm run preview` process
### Scenario 2: Theme Toggle Integration
- **Description**: Verify the theme toggle correctly switches and persists across the whole page (all sections read from the same theme context)
- **Setup**: Same as Scenario 1
- **Test Steps**: Toggle the theme control in the Nav; observe all sections (Hero, Packages, Process, About, Contact)
- **Expected Results**: All sections switch theme consistently; no section is left in the previous theme
- **Cleanup**: None
## Setup Integration Test Environment
### 1. Build and Serve the Production Bundle
```bash
pnpm run build
pnpm run preview
```
### 2. Configure Service Endpoints
Not applicable — no external services or APIs are called by this unit.
## Run Integration Tests
### 1. Execute Manual Smoke Test Suite
Follow Scenario 1 and Scenario 2 above in a browser against the `pnpm run preview` URL.
### 2. Verify Behaviors
- **Test Scenarios**: Navigation/scroll repeatability (Scenario 1), theme consistency (Scenario 2)
- **Expected Results**: See per-scenario expectations above
- **Logs Location**: Browser DevTools console (should show no errors/warnings during navigation)
### 3. Cleanup
Stop the preview server (`Ctrl+C` or terminate the process).
## Status
- **Automated integration/contract tests**: N/A — single static unit, no service boundaries to test
- **Manual smoke test**: Recommended before each deployment; the navigation-scroll regression (Scenario 1) was manually verified as fixed during this session
@@ -0,0 +1,51 @@
# Performance Test Instructions
## Purpose
Validate that the static marketing site loads fast on a typical FTP/static web host, since page-load speed and SEO basics are explicit requirements (see `aidlc-docs/features/react-frontend/inception/requirements/`).
## Performance Requirements
- **Initial Load (Largest Contentful Paint)**: < 2.5s on a simulated "Fast 3G"/typical mobile connection
- **Bundle Size**: JS + CSS payload kept small (single-page static site, no heavy client-side data fetching)
- **Concurrent Users**: Not applicable — static assets served by the host/CDN, no application server to load-test
- **Error Rate**: 0% (no runtime errors in the browser console)
## Setup Performance Test Environment
### 1. Prepare Test Environment
```bash
pnpm run build
pnpm run preview
```
Serves the actual production bundle (`dist/`) locally, which is representative of what a static host would serve.
### 2. Configure Test Parameters
- **Tooling**: Browser DevTools "Lighthouse" panel (or `npx lighthouse <preview-url> --view`)
- **Throttling**: Simulated mobile / Fast 3G, as offered by Lighthouse's default mobile preset
## Run Performance Tests
### 1. Execute Load Test (Lighthouse)
```bash
npx lighthouse http://localhost:4173 --view
```
(Adjust the port to whatever `pnpm run preview` prints.)
### 2. Execute Stress Tests
Not applicable — there is no backend/API to stress-test; the site is purely static assets.
### 3. Analyze Performance Results
- **Response Time / LCP**: Read from the Lighthouse report; target < 2.5s
- **Bundle Size**: Inspect `dist/assets/*.js` and `*.css` sizes after `pnpm run build`
- **Error Rate**: Confirm no console errors during the Lighthouse run
- **Bottlenecks**: Typically font loading (`@fontsource/*`) or unused CSS; check the Lighthouse "Opportunities" section
- **Results Location**: Lighthouse HTML report opened via `--view`, or exported JSON if needed
## Performance Optimization
If performance doesn't meet requirements:
1. Identify bottlenecks from the Lighthouse report (e.g. render-blocking fonts, unused Tailwind classes)
2. Optimize (e.g. font-display swap, purge unused Tailwind utilities via the existing Tailwind config, code-split rarely used components)
3. Rerun `pnpm run build` + Lighthouse to validate improvements
## Status
- **Automated performance gate**: Not part of the current CI; this is a manual pre-deployment check
- **Recommendation**: Run this check once before the first production deployment (Deployment Setup stage) and after any significant asset/dependency change
@@ -0,0 +1,31 @@
# Unit Test Execution
## Run Unit Tests
### 1. Execute All Unit Tests
```bash
pnpm run test
```
Runs Vitest (`vitest run`) with `jsdom` + `@testing-library/react` for component-level tests.
### 2. Review Test Results
- **Expected**: 9 tests pass across 3 test files, 0 failures
- **Test Coverage**: No formal coverage threshold configured; tests cover key rendering/interaction behavior of `Hero`, `Nav`, and the anchor-scroll utility
- **Test Report Location**: Console output from `vitest run` (no HTML report is generated by default)
### 3. Static Analysis (complementary check)
```bash
pnpm run lint
```
- **Expected**: 0 errors. 2 non-blocking warnings are known and accepted (`react-refresh/only-export-components` in `src/routes/index.tsx` and `src/theme/ThemeProvider.tsx`) — cosmetic Fast Refresh warnings, not correctness issues.
### 4. Fix Failing Tests
If tests fail:
1. Review the Vitest console output for the failing test file/assertion
2. Reproduce locally with `pnpm run test:watch` for fast iteration
3. Fix the component/utility code or update the test if the expected behavior changed intentionally
4. Rerun `pnpm run test` until all pass
## Verified Result (this session)
- `pnpm run test`: 3 test files, 9 tests, all passed.
- `pnpm run lint`: 0 errors, 2 known non-blocking warnings.
@@ -0,0 +1,57 @@
# Code Generation Plan — react-frontend-app
## Unit Context
- **Unit**: `react-frontend-app` (single unit, greenfield)
- **Workspace root**: `K:\Development\SlpSoftware\Projects\SlpSoftware` (from aidlc-state.md)
- **Project structure pattern**: Greenfield single unit → `src/`, `tests/`, config files at workspace root
- **Requirements source**: `aidlc-docs/features/react-frontend/inception/requirements/requirements.md`
- **Design sources**: Functional Design, NFR Requirements, NFR Design artifacts under `aidlc-docs/features/react-frontend/construction/react-frontend-app/`
- **Stories**: N/A (User Stories stage was skipped for this feature)
- **Dependencies**: None (first and only unit)
## Steps
### Project Structure Setup
- [x] Step 1: Scaffold Vite + React + TypeScript project files at workspace root (`package.json`, `vite.config.ts`, `tsconfig.json`, `tsconfig.node.json`, `index.html`, `.gitignore`)
- [x] Step 2: Configure Tailwind CSS with red/purple theme variants (`tailwind.config.ts`, `postcss.config.js`, `src/index.css`) per NFR Requirements/Design decisions
- [x] Step 3: Configure ESLint + Prettier (`.eslintrc.cjs` or `eslint.config.js`, `.prettierrc`)
- [x] Step 4: Configure Vitest + React Testing Library (`vitest.config.ts` or Vite test config, `src/test/setup.ts`)
### Domain Data & Theme Foundation
- [x] Step 5: Create typed content data module `src/data/content.ts` (NavLink, HeroContent, PackageCard, ProcessStep, AboutContent, ContactInfo) with the reference designs' Dutch copy ported 1-to-1 (FR-1, domain-entities.md)
- [x] Step 6: Create theme tokens module `src/theme/tokens.ts` (red default + purple alternate, per domain-entities.md `ThemeTokens`)
- [x] Step 7: Self-host fonts (Sora, Instrument Sans, JetBrains Mono) via `@fontsource` packages, imported in the app entry point (NFR Design font-loading decision)
### Application Shell (Router, Query, Theme, Error Handling)
- [x] Step 8: Create `ThemeProvider` (`src/theme/ThemeProvider.tsx`) implementing BR-1/BR-2/BR-3 (default red, persistence, fallback on invalid stored value)
- [x] Step 9: Create `ErrorBoundary` (`src/components/ErrorBoundary.tsx`) with on-brand fallback message (NFR Design resilience pattern)
- [x] Step 10: Set up TanStack Router with hash history (`src/router.tsx`, `src/routes/__root.tsx`, `src/routes/index.tsx`) composing ErrorBoundary → ThemeProvider → QueryClientProvider → RootLayout → routed content
- [x] Step 11: Set up TanStack Query (`src/queryClient.ts`) and the placeholder `usePackagesQuery` hook (`src/hooks/usePackagesQuery.ts`) with `staleTime: Infinity`
- [x] Step 12: Wire the application entry point (`src/main.tsx`) to mount the router
### Frontend Components Generation
- [x] Step 13: Create `RootLayout` (`src/components/RootLayout.tsx`)
- [x] Step 14: Create `Nav` + `ThemeToggle` (`src/components/Nav.tsx`, `src/components/ThemeToggle.tsx`) with Dutch `aria-label`/`aria-pressed`
- [x] Step 15: Create `Hero` (`src/components/Hero.tsx`) including the animated code line respecting `prefers-reduced-motion`
- [x] Step 16: Create `PackagesSection` + `PackageCard` (`src/components/PackagesSection.tsx`, `src/components/PackageCard.tsx`) consuming `usePackagesQuery`
- [x] Step 17: Create `ProcessSection` + `ProcessStep` (`src/components/ProcessSection.tsx`, `src/components/ProcessStep.tsx`)
- [x] Step 18: Create `AboutSection` (`src/components/AboutSection.tsx`)
- [x] Step 19: Create `ContactSection` (`src/components/ContactSection.tsx`)
- [x] Step 20: Create `Footer` (`src/components/Footer.tsx`)
- [x] Step 21: Assemble `src/routes/index.tsx` to render Hero, PackagesSection, ProcessSection, AboutSection, ContactSection in order
### Frontend Components Unit Testing
- [x] Step 22: Write unit tests for theme logic (`src/theme/__tests__/ThemeProvider.test.tsx`) covering BR-1, BR-2, BR-3
- [x] Step 23: Write component tests for `Nav`/`ThemeToggle` (`src/components/__tests__/Nav.test.tsx`)
- [x] Step 24: Write component tests for `PackagesSection`/`PackageCard` (`src/components/__tests__/PackagesSection.test.tsx`)
### Documentation Generation
- [x] Step 25: Create `README.md` at workspace root with setup/run/build/test instructions
- [x] Step 26: Create code summary documentation at `aidlc-docs/features/react-frontend/construction/react-frontend-app/code/code-summary.md`
### Deployment Artifacts
- [x] Step 27: Add `npm audit`-friendly `package-lock.json` (generated automatically on install) and confirm `.gitignore` excludes `node_modules`/`dist` — verified: `package-lock.json` present, `npm audit --omit=dev` reports 0 vulnerabilities
- [x] Step 28: Verify `vite.config.ts` base path is compatible with hash-based routing on a static/FTP host (no special `base` needed since hash routing carries the route state client-side) — confirmed via successful `npm run build`
## Story Traceability
No user stories exist for this feature (stage skipped). Traceability is instead to `requirements.md` (FR-1 through FR-5, NFR-1 through NFR-5) and to the approved Functional Design / NFR Requirements / NFR Design artifacts, referenced inline per step above.
@@ -0,0 +1,68 @@
# Functional Design Clarification Questions — react-frontend-app
Please answer each question by filling in the letter choice after the `[Answer]:` tag.
## Question 1: Theme toggle placement and style
Where and how should the visible theme switcher (red/purple) be placed in the UI?
A) A small icon/swatch button in the nav bar (next to the "Start project" CTA), showing the current theme and toggling on click
B) A labeled two-option switch (e.g. "Rood" / "Paars" segmented control) in the nav bar
C) A floating control (e.g. fixed corner button) separate from the nav bar
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 2: Theme data shape
How should the two theme palettes be modeled in code?
A) A single TypeScript object/record per theme (e.g. `{ red: {...tokens}, purple: {...tokens} }`) mapped to CSS custom properties at runtime via a `data-theme` attribute on `<html>`/`<body>`
B) Two separate static CSS files (one per theme) that get swapped via a `<link>` tag toggle
C) Tailwind config with two named theme variants selected via a class on the root element (e.g. `theme-red`, `theme-purple`)
X) Other (please describe after [Answer]: tag below)
[Answer]: C
## Question 3: Package/content data shape
How should the static package/pricing/content data (nav links, hero copy, package cards, steps, etc.) be structured in code for this iteration?
A) One central static data module (e.g. `content.ts`) exporting typed constants/arrays consumed directly by components — easiest to later swap for a TanStack Query hook with the same shape
B) Hardcoded directly inside each component (no separate data module)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 4: TanStack Router route structure for this iteration
Given there is effectively one page right now, how should the initial route structure look?
A) A root route (`__root.tsx`) rendering the shared layout (nav, theme provider, footer) with a single index route (`/`) rendering the full page content — ready to add sibling routes later
B) A single flat route with no nested layout route yet (add the root/layout split only when a second route is introduced)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 5: TanStack Query placeholder usage
Since there's no backend yet, how should the "prepared for TanStack Query" requirement (FR-5) be reflected in this functional design?
A) Define one placeholder query hook (e.g. `usePackagesQuery`) that currently resolves the static data through `queryFn` (wrapped in a Promise) so the calling component already consumes it via `useQuery`, making a future real API swap a one-line change
B) Only add the `QueryClientProvider` at the app root for now, without creating any actual query hook yet — components keep reading static data directly until a real API exists
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 6: Reduced-motion handling for the theme switch itself
The reference design already respects `prefers-reduced-motion` for the caret blink. Should the theme-switch transition (background/color change) also respect this preference?
A) Yes — make the theme color transition instant (no fade) when `prefers-reduced-motion: reduce` is set, consistent with the existing caret handling
B) No special handling needed for the theme transition — only the existing caret animation needs to respect it
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 7: Accessibility labeling for the theme switcher
What accessible name/label should the new theme switcher control have?
A) `aria-label="Wissel kleurthema"` (Dutch, matching the rest of the site's language) with `aria-pressed`/`aria-checked` reflecting current state
B) `aria-label="Toggle color theme"` (English)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
@@ -0,0 +1,18 @@
# Functional Design Plan — react-frontend-app
## Unit Context
- **Unit**: `react-frontend-app` (single unit — Units Generation was skipped per the approved execution plan; this is the only unit of work for this feature)
- **Source**: `aidlc-docs/features/react-frontend/inception/requirements/requirements.md`
## Steps
- [x] Define the theme/color-token domain model (red default palette, purple alternate palette, shared token shape)
- [x] Define the static content domain model (nav links, hero copy, package/pricing cards, process steps, about/tech-stack content, contact info) sourced 1-to-1 from the reference designs
- [x] Define business rules for theme selection and persistence (default theme, switching behavior, persistence/fallback rules)
- [x] Define the frontend component hierarchy (Nav, Hero, PackagesSection/PackageCard, ProcessSection/Step, AboutSection, ContactSection, Footer, ThemeProvider/ThemeToggle)
- [x] Define props/state for each component and the user interaction flows (theme toggle click, anchor navigation, hover/focus states, mailto CTA)
- [x] Define the TanStack Router route structure (root layout route + index route housing the whole page for this iteration)
- [x] Define the TanStack Query integration point (provider placement + a placeholder query hook shape for future package/content data, backed by static data for now)
- [x] Generate context-appropriate clarification questions and store in a dedicated question file
- [x] Generate functional design artifacts: business-logic-model.md, business-rules.md, domain-entities.md, frontend-components.md
- [x] Present completion message and await approval
@@ -0,0 +1,49 @@
# NFR Design Plan — react-frontend-app
## Steps
- [x] Define resilience pattern (error boundary fallback behavior)
- [x] Define scalability pattern (justify minimal need given static single-page scope)
- [x] Define performance pattern (TanStack Query caching config, font-loading strategy)
- [x] Define security pattern (SRI application, CSP scope given deferred HTTP headers)
- [x] Define logical components (theme store, content store, query client, router instance)
- [x] Generate nfr-design-patterns.md and logical-components.md
## Category Applicability Justification
- **Resilience Patterns**: Applicable at a minimal level — a top-level React error boundary is the only meaningful resilience concern for a static, no-backend frontend (per SECURITY-15 from NFR Requirements).
- **Scalability Patterns**: Not meaningfully applicable — this is a static single-page site with no server-side scaling concerns; the only "scaling" consideration is adding more routes/queries later, already covered by the Functional Design's extensible route/query structure.
- **Performance Patterns**: Applicable — caching behavior of the placeholder TanStack Query hook and web font loading strategy are worth deciding now.
- **Security Patterns**: Applicable at the scope already defined in NFR Requirements (SECURITY-10/13/15 addressed now; SECURITY-04/14 deferred) — this stage just needs to decide the concrete implementation pattern.
- **Logical Components**: Applicable — need to name the concrete provider/store components (ThemeProvider, QueryClientProvider, Router instance) that implement the functional design.
## Clarification Questions
Please answer each question by filling in the letter choice after the `[Answer]:` tag.
### Question 1: Error boundary fallback behavior
When an unexpected rendering error occurs, what should the top-level error boundary show?
A) A minimal, on-brand fallback message (styled with the current theme) with no technical details, e.g. "Er ging iets mis. Probeer de pagina te vernieuwen."
B) A plain, unstyled fallback message (not necessarily following the current theme)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
### Question 2: TanStack Query caching for the placeholder hook
Since `usePackagesQuery` currently wraps static data (no real network call), how should its caching be configured?
A) Use TanStack Query defaults (`staleTime: 0`, refetch on window focus) — harmless for static data since the `queryFn` always returns the same static array anyway
B) Set a long `staleTime` (e.g. `Infinity`) now, anticipating that once real data-fetching is wired in later, the content won't need to refetch constantly
X) Other (please describe after [Answer]: tag below)
[Answer]: A
### Question 3: Web font loading strategy
The reference design loads Google Fonts (Sora, Instrument Sans, JetBrains Mono) via `<link>` tags. How should this be handled in the React app?
A) Keep loading via Google Fonts CDN `<link>` tags in `index.html`, adding SRI hashes where Google Fonts' CSS response allows it (per SECURITY-13 decision)
B) Self-host the font files as static assets bundled with the app (avoids depending on an external CDN and SRI complications, at the cost of larger initial bundle/setup effort)
X) Other (please describe after [Answer]: tag below)
[Answer]: B
@@ -0,0 +1,88 @@
# NFR Requirements Plan — react-frontend-app
## Steps
- [x] Assess Security Baseline rule applicability for a static, no-backend React frontend
- [x] Determine performance expectations (Lighthouse-style targets, bundle size sensitivity)
- [x] Determine testing/tooling expectations (test runner, linting, formatting)
- [x] Determine routing fallback strategy for the FTP/static hosting target (NFR-4 follow-up) — AI recommendation: hash-based routing (see nfr-requirements.md)
- [x] Determine accessibility target level
- [x] Determine CI expectations for this iteration
- [x] Generate nfr-requirements.md and tech-stack-decisions.md
## Clarification Questions
Please answer each question by filling in the letter choice after the `[Answer]:` tag.
### Question 1: Performance target
Is there a specific performance target for this static marketing site (e.g. Lighthouse score, load time)?
A) No hard numeric target — just keep the bundle reasonably small and avoid obvious performance mistakes (code-splitting not required yet for a single page)
B) Target a Lighthouse Performance score of 90+ on the built production bundle
C) No performance requirements at all for this iteration
X) Other (please describe after [Answer]: tag below)
[Answer]: A
### Question 2: Testing tooling
Which testing setup should be used for this iteration (component/unit tests)?
A) Vitest + React Testing Library (natural fit with Vite)
B) Jest + React Testing Library
C) No automated tests for this iteration — only manual verification and a successful build
X) Other (please describe after [Answer]: tag below)
[Answer]: A
### Question 3: Linting / formatting
Should linting and formatting be configured as part of this setup?
A) Yes — ESLint (with React/TypeScript rules) + Prettier, configured and passing on the initial codebase
B) Only ESLint, no Prettier
C) Not needed for this iteration
X) Other (please describe after [Answer]: tag below)
[Answer]: A
### Question 4: Routing fallback strategy for FTP hosting (NFR-4 follow-up)
Since the target deployment is a plain FTP/static web host and TanStack Router is being set up now, which routing mode should be used to avoid future deep-link/404 problems on that kind of host?
A) Use TanStack Router's `hashHistory` (URLs like `/#/pakketten`) — works on any static host without server configuration, at the cost of slightly less clean URLs
B) Use browser `history` mode now and defer the FTP rewrite-rule (`.htaccess`) problem to Deployment Setup in the Operations phase, since there's only one route today
C) Not sure — let the AI recommend based on best practice for this hosting target
X) Other (please describe after [Answer]: tag below)
[Answer]: C
### Question 5: Accessibility target
What accessibility (a11y) target should this frontend meet?
A) WCAG 2.1 AA as a target (semantic HTML, sufficient color contrast for both themes, keyboard-operable theme toggle, aria labels per functional design)
B) No formal target — best-effort only, matching whatever the reference HTML already provides
X) Other (please describe after [Answer]: tag below)
[Answer]: B
### Question 6: CI for this iteration
Should a CI pipeline (e.g. GitHub Actions) running build/lint/test be set up as part of this iteration?
A) Yes — set up a basic CI workflow that runs install, lint, test, and build on every push
B) Not yet — CI can be addressed later, possibly during the Operations phase (Deployment Setup)
X) Other (please describe after [Answer]: tag below)
[Answer]: B
### Question: Security Baseline Rule Applicability
Given this is a static, no-backend marketing frontend (per requirements.md), most backend-oriented Security Baseline rules (SECURITY-01, 02, 05, 06, 07, 08, 11, 12, 13, 14, 15) will be marked **N/A**. The following rules ARE potentially applicable and need a decision on scope:
- SECURITY-04 (HTTP security headers) — depends on hosting; may need to be deferred to Deployment Setup if the FTP host doesn't support custom headers easily
- SECURITY-09 (hardening/misconfiguration) — mainly "no sample/demo pages", generic error handling for a client-side app
- SECURITY-10 (software supply chain) — dependency lock file + vulnerability scanning, applicable to any npm project
- SECURITY-13 (integrity) — Subresource Integrity (SRI) for the Google Fonts CDN `<link>` tags
How should these be handled for this iteration?
A) Address SECURITY-10 (lock file + `npm audit`/dependency scanning) and SECURITY-13 (SRI where feasible) now during Code Generation; defer SECURITY-04 (HTTP headers) to Deployment Setup since it depends on the final hosting choice; mark SECURITY-09 items as addressed via a standard production build (no demo pages, generic error boundary)
B) Defer ALL of these to the Operations phase (Deployment Setup / Production Readiness) — do not address any Security Baseline rule during Code Generation
X) Other (please describe after [Answer]: tag below)
[Answer]: A
@@ -0,0 +1,47 @@
# Code Summary — react-frontend-app
## Application Code (Workspace Root)
### Project Configuration
- `package.json`, `vite.config.ts`, `tsconfig.json`, `tsconfig.node.json`, `index.html`, `.gitignore`
- `tailwind.config.ts`, `postcss.config.js` — Tailwind theme mapped to CSS custom properties
- `eslint.config.js` (ESLint 9 flat config), `.prettierrc`
- `README.md` — setup/run/build/test instructions
### Domain Data & Theme
- `src/data/content.ts` — typed static content (NavLink, HeroContent, PackageCardData, ProcessStepData, AboutContent, ContactInfo), copied 1-to-1 from the reference designs
- `src/theme/tokens.ts` — theme value model (`red`/`purple`), storage key, validation/fallback (BR-1/BR-3)
- `src/theme/ThemeProvider.tsx` — theme context, localStorage persistence (BR-2), applies `theme-red`/`theme-purple` class to `<html>`
- `src/index.css` — theme token CSS variables (`.theme-red`, `.theme-purple`), global styles, caret animation, reduced-motion handling
- `src/fonts.ts` — self-hosted font imports (`@fontsource/sora`, `@fontsource/instrument-sans`, `@fontsource/jetbrains-mono`)
### Application Shell
- `src/queryClient.ts` — shared `QueryClient` (`staleTime: Infinity`)
- `src/hooks/usePackagesQuery.ts` — placeholder query hook wrapping static package data
- `src/components/ErrorBoundary.tsx` — top-level on-brand error boundary
- `src/routes/__root.tsx` — root route composing ErrorBoundary → ThemeProvider → QueryClientProvider → RootLayout
- `src/routes/index.tsx` — index route assembling the page sections
- `src/router.tsx` — router instance with hash-based history
- `src/main.tsx` — application entry point
### Components
- `src/components/RootLayout.tsx`, `Nav.tsx`, `ThemeToggle.tsx`, `Hero.tsx`, `PackagesSection.tsx`, `PackageCard.tsx`, `ProcessSection.tsx`, `ProcessStep.tsx`, `AboutSection.tsx`, `ContactSection.tsx`, `Footer.tsx`
### Tests
- `src/theme/__tests__/ThemeProvider.test.tsx` — 4 tests covering BR-1, BR-2, BR-3
- `src/components/__tests__/Nav.test.tsx` — 3 tests (nav links, accessible toggle label, toggle interaction)
- `src/components/__tests__/PackagesSection.test.tsx` — 2 tests (package rendering, featured badge)
- `src/test/setup.ts` — Testing Library / jest-dom setup for Vitest
## Verification (Step 13.5)
- **Build**: ✅ Success (`npm run build``tsc -b && vite build`)
- **Unit Tests**: ✅ 9 passed, 0 failed (`npm run test` — Vitest)
- **Lint**: ✅ 0 errors (2 non-blocking `react-refresh/only-export-components` warnings on files that intentionally export a hook alongside a component)
### Post-Review Fix: Deprecated Package Warnings
After initial review, the user requested that the `npm install` deprecation warnings (`eslint@8.57.1`, `@humanwhocodes/config-array`, `@humanwhocodes/object-schema`, and related transitive packages) be resolved. Resolved by migrating from ESLint 8 (`.eslintrc.cjs`) to **ESLint 9 flat config** (`eslint.config.js`), using `typescript-eslint`, `@eslint/js`, `globals`, and `eslint-plugin-react-hooks` v5. Re-verified: build, tests (9/9), and lint (0 errors) all still pass after the migration, and `npm install` no longer reports deprecation warnings for these packages.
## Traceability
- Requirements: FR-1 (content parity), FR-2 (componentization), FR-3 (theme switching), FR-4 (preserved micro-interactions), FR-5 (TanStack Router/Query scaffolding), NFR-1 through NFR-5
- Functional Design business rules BR-1 through BR-6 implemented as described above
- NFR Design patterns (error boundary, query caching, self-hosted fonts, hash routing) implemented as described above
@@ -0,0 +1,65 @@
# Business Logic Model — react-frontend-app
## Overview
This unit's business logic is small and UI-centric: rendering static marketing content and managing the theme (red default / purple alternate) selection and persistence. There is no backend business logic in this iteration.
## Process Flow: Page Load and Theme Resolution
```mermaid
graph TD
start_load["Visitor loads the site"]
read_storage["Read stored theme preference from localStorage"]
check_stored["Stored preference found?"]
use_stored["Use stored theme (red or purple)"]
use_default["Use default theme: red"]
apply_theme["Apply theme class/attribute to document root"]
load_content["Load static content module (nav, hero, packages, steps, about, contact)"]
init_query["Initialize QueryClientProvider and packages placeholder query"]
render_page["Render page sections via TanStack Router index route"]
start_load --> read_storage
read_storage --> check_stored
check_stored -->|"Yes"| use_stored
check_stored -->|"No"| use_default
use_stored --> apply_theme
use_default --> apply_theme
apply_theme --> load_content
load_content --> init_query
init_query --> render_page
classDef process fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
classDef decision fill:#fbd38d,stroke:#92400e,stroke-width:1px,color:#000;
classDef terminal fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000;
class start_load,render_page terminal;
class read_storage,use_stored,use_default,apply_theme,load_content,init_query process;
class check_stored decision;
```
Text alternative: On load, the app reads a stored theme preference; if found it is used, otherwise red is used as default; the theme is applied to the document, static content is loaded, the query provider is initialized, then the page renders.
## Process Flow: Theme Switch Interaction
```mermaid
graph TD
click_toggle["Visitor clicks the theme toggle button in the nav"]
determine_next["Determine next theme (red to purple, or purple to red)"]
update_state["Update in-memory theme state (ThemeProvider context)"]
persist_storage["Persist chosen theme to localStorage"]
reapply_theme["Re-apply theme class/attribute to document root"]
update_toggle["Update toggle button visual state and aria-pressed"]
click_toggle --> determine_next
determine_next --> update_state
update_state --> persist_storage
persist_storage --> reapply_theme
reapply_theme --> update_toggle
classDef process fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
classDef terminal fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000;
class click_toggle terminal;
class determine_next,update_state,persist_storage,reapply_theme,update_toggle process;
```
Text alternative: Clicking the toggle determines the other theme, updates in-memory state, persists it to localStorage, reapplies the theme to the document, and updates the toggle button's visual/accessible state.
@@ -0,0 +1,42 @@
# Business Rules — react-frontend-app
## BR-1: Default Theme Rule
The site MUST use the **red** theme when no stored theme preference exists (first visit, cleared storage, or unsupported storage).
## BR-2: Theme Persistence Rule
Whenever the visitor switches themes, the chosen theme MUST be written to `localStorage` immediately, so a page reload or new visit resolves to the same theme (BR-1 only applies when nothing is stored).
## BR-3: Valid Theme Values Rule
Only two theme values are valid: `red` and `purple`. If a stored value is anything else (corrupted/unexpected), the app MUST fall back to the default theme (`red`) rather than error.
## BR-4: Content Fidelity Rule
All rendered marketing copy, prices (€300 / €750 / "Op maat"), and the contact e-mail (`info@slpsoftware.nl`) MUST match the reference HTML designs exactly for this iteration (per requirements FR-1); no content may be altered, abbreviated, or replaced with placeholder text.
## BR-5: Reduced Motion Rule
When the visitor's OS/browser signals `prefers-reduced-motion: reduce`, both the hero caret blink animation AND the theme-switch color transition MUST be instant / non-animated.
## BR-6: Single Route Rule (current iteration)
For this iteration, all page sections (nav, hero, packages, process, about, contact, footer) are rendered under a single index route (`/`). No section requires its own route yet.
## Decision Flow: Theme Resolution on Load
```mermaid
graph TD
load_pref{"Stored theme value exists?"}
valid_check{"Stored value is 'red' or 'purple'?"}
use_stored_value["Use stored value as active theme"]
fallback_default["Fall back to default theme: red"]
load_pref -->|"No"| fallback_default
load_pref -->|"Yes"| valid_check
valid_check -->|"Yes"| use_stored_value
valid_check -->|"No (corrupted/unexpected)"| fallback_default
classDef decision fill:#fbd38d,stroke:#92400e,stroke-width:1px,color:#000;
classDef outcome fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
class load_pref,valid_check decision;
class use_stored_value,fallback_default outcome;
```
Text alternative: If no stored theme exists, or the stored value is not "red"/"purple", the app falls back to red; otherwise the valid stored value is used.
@@ -0,0 +1,97 @@
# Domain Entities — react-frontend-app
## Overview
This unit has no persisted backend entities. The "domain" here is the static content model and the theme model that drive rendering.
## Entity Relationships
```mermaid
graph TD
theme_pref["ThemePreference"]
theme_tokens["ThemeTokens"]
site_content["SiteContent"]
nav_link["NavLink"]
hero_content["HeroContent"]
package_card["PackageCard"]
process_step["ProcessStep"]
about_content["AboutContent"]
contact_info["ContactInfo"]
theme_pref -->|"selects"| theme_tokens
site_content -->|"has many"| nav_link
site_content -->|"has one"| hero_content
site_content -->|"has many"| package_card
site_content -->|"has many"| process_step
site_content -->|"has one"| about_content
site_content -->|"has one"| contact_info
classDef entity fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000;
classDef value fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000;
class theme_pref,site_content entity;
class theme_tokens,nav_link,hero_content,package_card,process_step,about_content,contact_info value;
```
Text alternative: A ThemePreference selects a set of ThemeTokens; SiteContent aggregates NavLinks, one HeroContent, many PackageCards, many ProcessSteps, one AboutContent, and one ContactInfo (blue = stateful entity, orange = static value objects).
## Entity Definitions
### ThemePreference
| Field | Type | Required | Description |
|---|---|---|---|
| `value` | `'red' \| 'purple'` | Yes | Currently active theme; defaults to `'red'` per BR-1 |
| `source` | `'stored' \| 'default'` | Yes | Whether the value came from `localStorage` or the default fallback |
### ThemeTokens
| Field | Type | Required | Description |
|---|---|---|---|
| `bg`, `surface`, `surfaceAlt`, `line`, `text`, `muted` | `string` (hex) | Yes | Neutral palette tokens, taken 1-to-1 from the reference CSS variables |
| `accent`, `accentSoft`, `accentLine` | `string` (hex/rgba) | Yes | Accent palette tokens (red or purple variant), taken 1-to-1 from the reference CSS variables |
### NavLink
| Field | Type | Required | Description |
|---|---|---|---|
| `label` | `string` | Yes | Link text (e.g. "Pakketten") |
| `href` | `string` | Yes | Anchor target (e.g. "#pakketten") |
| `isCta` | `boolean` | No | Marks the "Start project" call-to-action link |
### HeroContent
| Field | Type | Required | Description |
|---|---|---|---|
| `eyebrow` | `string` | Yes | Small label above the heading |
| `heading` | `string` | Yes | Main H1 text |
| `lead` | `string` | Yes | Lead paragraph text |
| `codeLine` | `string` | Yes | The animated code-line snippet text |
### PackageCard
| Field | Type | Required | Description |
|---|---|---|---|
| `id` | `string` | Yes | e.g. `pakket_01` |
| `title` | `string` | Yes | e.g. "Landingspagina" |
| `description` | `string` | Yes | Short description |
| `price` | `string` | Yes | e.g. "€ 300" or "Op maat" |
| `priceNote` | `string` | Yes | e.g. "eenmalig, excl. btw" |
| `features` | `string[]` | Yes | Bullet list of included features |
| `ctaLabel` | `string` | Yes | Button text |
| `featured` | `boolean` | No | Marks the "Meest gekozen" (most chosen) card |
### ProcessStep
| Field | Type | Required | Description |
|---|---|---|---|
| `label` | `string` | Yes | e.g. "stap 01 — intake" |
| `title` | `string` | Yes | e.g. "Kennismaken" |
| `description` | `string` | Yes | Step description |
### AboutContent
| Field | Type | Required | Description |
|---|---|---|---|
| `paragraphs` | `string[]` | Yes | About-section body paragraphs |
| `techStack` | `{ label: string; value: string }[]` | Yes | Tech-stack list items (Front-end, Back-end, API's, Focus) |
### ContactInfo
| Field | Type | Required | Description |
|---|---|---|---|
| `heading` | `string` | Yes | Contact section heading |
| `description` | `string` | Yes | Contact section body text |
| `email` | `string` | Yes | `info@slpsoftware.nl` |
| `mailSubject` | `string` | Yes | Prefilled mailto subject |
@@ -0,0 +1,77 @@
# Frontend Components — react-frontend-app
## Component Hierarchy
```mermaid
graph TD
root_route["__root.tsx\n(Root Route: ThemeProvider + QueryClientProvider)"]
layout["RootLayout\n(Nav + Footer wrapper)"]
index_route["index.tsx\n(/ Index Route)"]
nav["Nav"]
theme_toggle["ThemeToggle"]
hero["Hero"]
packages_section["PackagesSection"]
package_card["PackageCard (x3)"]
process_section["ProcessSection"]
process_step["ProcessStep (x3)"]
about_section["AboutSection"]
contact_section["ContactSection"]
footer["Footer"]
root_route --> layout
layout --> nav
nav --> theme_toggle
layout --> index_route
index_route --> hero
index_route --> packages_section
packages_section --> package_card
index_route --> process_section
process_section --> process_step
index_route --> about_section
index_route --> contact_section
layout --> footer
classDef root_node fill:#4CAF50,stroke:#2e7d32,stroke-width:2px,color:#000;
classDef layout_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000;
classDef page_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000;
classDef guard_node fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000;
class root_route root_node;
class layout,index_route layout_node;
class nav,hero,packages_section,package_card,process_section,process_step,about_section,contact_section,footer page_node;
class theme_toggle guard_node;
```
Text alternative: The root route provides ThemeProvider and QueryClientProvider and renders a RootLayout (Nav with ThemeToggle, plus Footer) wrapping the index route, which renders Hero, PackagesSection (three PackageCard instances), ProcessSection (three ProcessStep instances), AboutSection, and ContactSection.
## Components: Props and State
| Component | Props | State | Notes |
|---|---|---|---|
| `RootRoute` (`__root.tsx`) | — | — | Hosts `ThemeProvider` and `QueryClientProvider`; renders `<Outlet />` |
| `ThemeProvider` | `children: ReactNode` | `theme: 'red' \| 'purple'` (from context) | Reads/writes `localStorage`; exposes `theme` and `toggleTheme()` via context; applies `theme-red`/`theme-purple` class to `<html>` |
| `RootLayout` | `children: ReactNode` | — | Renders `Nav`, `children` (routed content), `Footer` |
| `Nav` | `links: NavLink[]` | — | Renders logo, `nav-links`, `ThemeToggle`, CTA link |
| `ThemeToggle` | — | — | Reads `theme`/`toggleTheme` from `ThemeProvider` context; `aria-label="Wissel kleurthema"`, `aria-pressed` reflects whether purple is active |
| `Hero` | `content: HeroContent` | — | Renders eyebrow, heading, lead, animated code line (caret respects `prefers-reduced-motion`), two CTA buttons |
| `PackagesSection` | `packages: PackageCard[]` | — | Renders section head + grid of `PackageCard` |
| `PackageCard` | `pkg: PackageCard` | — | Renders one pricing card; `featured` prop styling for "Meest gekozen" |
| `ProcessSection` | `steps: ProcessStep[]` | — | Renders section head + grid of `ProcessStep` |
| `ProcessStep` | `step: ProcessStep` | — | Renders one process step (label, title, description) |
| `AboutSection` | `content: AboutContent` | — | Renders paragraphs + tech-stack panel |
| `ContactSection` | `content: ContactInfo` | — | Renders contact box with mailto CTA |
| `Footer` | — | — | Renders copyright + mono tagline |
## User Interaction Flows
- **Theme toggle click**: `ThemeToggle` → calls `toggleTheme()` from `ThemeProvider` context → context updates `theme` state → writes new value to `localStorage` (BR-2) → root element's theme class is updated → all themed elements re-render with new token values → transition is instant if `prefers-reduced-motion: reduce` (BR-5), otherwise a short color transition plays.
- **In-page anchor navigation**: Clicking a `Nav` link or hero CTA scrolls smoothly to the target section (`scroll-behavior: smooth`), respecting `prefers-reduced-motion` (falls back to instant jump).
- **Hover / focus-visible states**: Preserved 1-to-1 from the reference design on nav links, buttons, and cards (border/color changes on `:hover`/`:focus-visible`).
- **Mailto CTA**: Clicking the contact CTA or the inline mail link opens the visitor's mail client via a `mailto:` link with a prefilled subject.
## Form Validation Rules
None — this iteration has no forms; the only interactive control is the theme toggle and standard anchor/mailto links.
## API Integration Points (Forward-Looking)
- `usePackagesQuery` (TanStack Query hook, placeholder): `queryFn` currently resolves the static `PackageCard[]` data from the content module wrapped in `Promise.resolve(...)`, consumed via `useQuery` in `PackagesSection`. This keeps the component's data-access pattern identical to what it will be once a real backend endpoint exists — only the `queryFn` implementation will need to change in a future iteration (per FR-5).
- No other components call `useQuery` in this iteration; `Nav`, `Hero`, `ProcessSection`, `AboutSection`, and `ContactSection` read directly from the static content module for now.
@@ -0,0 +1,42 @@
# Logical Components — react-frontend-app
## Component/Provider Overview
```mermaid
graph TD
router["Router Instance\n(TanStack Router, hash history)"]
query_client["QueryClientProvider\n(staleTime: Infinity for placeholder queries)"]
theme_provider["ThemeProvider\n(theme state + localStorage persistence)"]
error_boundary["ErrorBoundary\n(on-brand fallback UI)"]
root_route["Root Route (__root.tsx)"]
fonts["Self-hosted Fonts\n(bundled static assets)"]
router --> root_route
root_route --> error_boundary
error_boundary --> theme_provider
theme_provider --> query_client
root_route -.->|"loads"| fonts
classDef infra fill:#9C27B0,stroke:#4a148c,stroke-width:1px,color:#000;
classDef guard fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000;
classDef layout fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000;
classDef asset fill:#4CAF50,stroke:#2e7d32,stroke-width:1px,color:#000;
class router,query_client infra;
class error_boundary guard;
class theme_provider,root_route layout;
class fonts asset;
```
Text alternative: The router hosts the root route, which is wrapped by an ErrorBoundary, which wraps ThemeProvider, which wraps QueryClientProvider; the root route also loads self-hosted font assets (purple = infra provider, orange = guard/boundary, blue = layout/route, green = static asset).
## Logical Component Definitions
| Component | Type | Responsibility |
|---|---|---|
| **Router Instance** | Infrastructure | Created via TanStack Router with `createHashHistory()`; defines the root route and index route tree. |
| **QueryClientProvider** | Infrastructure | Wraps the app with a single shared `QueryClient`; configures default `staleTime: Infinity` for this iteration's placeholder queries. |
| **ThemeProvider** | Layout/Context | Owns `theme` state (`'red' \| 'purple'`), reads/writes `localStorage`, applies the active theme class to the document root; exposes `theme` + `toggleTheme()` via React context (implements BR-1, BR-2, BR-3). |
| **ErrorBoundary** | Guard | Top-level React error boundary; renders the on-brand fallback UI on unexpected render errors (implements the Resilience Pattern). |
| **Root Route (`__root.tsx`)** | Layout/Route | Composes `ErrorBoundary``ThemeProvider``QueryClientProvider``RootLayout` (Nav/Footer) → routed content (`<Outlet />`). |
| **Self-hosted Fonts** | Static Asset | Sora, Instrument Sans, and JetBrains Mono font files bundled with the app and declared via local `@font-face`/`@fontsource` imports — no external CDN dependency. |
@@ -0,0 +1,26 @@
# NFR Design Patterns — react-frontend-app
## Resilience Pattern: Top-Level Error Boundary
A single React error boundary wraps the routed content inside the root route. On an unexpected rendering error it shows a minimal, on-brand fallback message styled with the currently active theme (e.g. "Er ging iets mis. Probeer de pagina te vernieuwen."), with no stack traces or technical details exposed (satisfies SECURITY-09 and SECURITY-15 from NFR Requirements).
## Scalability Pattern: Not Applicable (Justified)
This is a static single-page marketing site with no server-side component to scale. The only forward-looking "scalability" concern — adding more routes and swapping the placeholder query for a real API — is already accommodated structurally by the Functional Design's root/index route split and the `usePackagesQuery` hook shape, so no additional scalability pattern is introduced at this stage.
## Performance Patterns
### Query Caching
The `usePackagesQuery` placeholder hook is configured with `staleTime: Infinity` (and no automatic refetch-on-window-focus), since its `queryFn` currently always returns the same static array. This is a deliberate choice anticipating the future real-data swap, where refetch behavior can be tuned once real network latency/staleness exists.
### Font Loading
Fonts (Sora, Instrument Sans, JetBrains Mono) are **self-hosted** as static assets bundled with the app (via `@fontsource/*` packages or locally vendored font files + `@font-face` declarations), rather than loaded from the Google Fonts CDN.
- **Impact on Security Baseline SECURITY-13 (integrity)**: Self-hosting removes the need for Subresource Integrity (SRI) hashes on font `<link>` tags entirely, since no external CDN resource is loaded for fonts anymore. The NFR Requirements SECURITY-13 note ("SRI where feasible") is superseded by this decision — self-hosting is a stronger mitigation (no external dependency at all) than SRI on a CDN resource.
- **Trade-off accepted**: Slightly larger initial bundle/setup effort, in exchange for one fewer external dependency and a fully offline-buildable app.
## Security Patterns
- **Dependency/supply chain (SECURITY-10)**: `package-lock.json` committed; `npm audit` step documented in build instructions (implemented in Build and Test stage).
- **Integrity (SECURITY-13)**: Satisfied via the font self-hosting decision above (no external CDN assets requiring SRI remain in this iteration).
- **Hardening (SECURITY-09) & fail-safe defaults (SECURITY-15)**: Satisfied via the Resilience Pattern (error boundary) above and a standard production build with no demo/sample routes.
- **HTTP security headers (SECURITY-04)**: Remains deferred to Deployment Setup (Operations phase), unchanged from NFR Requirements — no hosting decision has been finalized yet.
## Logical Components
See `logical-components.md` for the concrete component/provider list implementing these patterns.
@@ -0,0 +1,53 @@
# NFR Requirements — react-frontend-app
## Performance
- **Target**: No hard numeric target. Keep the production bundle reasonably small; code-splitting is not required for this single-page iteration but the setup should not preclude it later (Vite handles this automatically as routes/queries grow).
## Testing
- **Test runner**: Vitest (pairs naturally with Vite)
- **Component testing**: React Testing Library
- **Scope for this iteration**: Component rendering tests for key components (`Nav`, `ThemeToggle`, `PackagesSection`, `PackageCard`) and a unit test for the theme resolution/persistence logic (BR-1, BR-2, BR-3).
## Linting & Formatting
- **ESLint** configured with React + TypeScript rules (e.g. `typescript-eslint`, `eslint-plugin-react-hooks`)
- **Prettier** for consistent formatting
- Both must pass cleanly on the initial generated codebase.
## Routing Strategy for Static/FTP Hosting (AI Recommendation)
The user deferred this decision to the AI (Question 4 = "Not sure — let the AI recommend").
**Decision: Use TanStack Router's hash-based history (`createHashHistory`) for this iteration.**
**Rationale**:
- The confirmed deployment target (requirements.md NFR-4) is a traditional web host via FTP/manual upload, where server-side rewrite rules (`.htaccess` or equivalent) are not guaranteed to be configurable or reliably supported.
- Hash-based routing (`/#/route`) works correctly on any static file host with zero server configuration, because the part after `#` is never sent to the server — the server only ever needs to serve `index.html`.
- The trade-off (slightly less clean URLs, e.g. `example.com/#/pakketten` instead of `example.com/pakketten`) is acceptable for a small marketing site and avoids a class of "404 on refresh/direct link" bugs that browser `history` mode would introduce on this hosting target.
- If hosting later moves to a platform with reliable rewrite support (e.g. Netlify/Vercel per requirements.md's alternative hosting note), this can be revisited and switched to `createBrowserHistory` — this is a router configuration change only, not a structural one, since TanStack Router's history mode is set in one place at the router's creation.
## Accessibility
- **Target**: Best-effort only, matching whatever the reference HTML already provides (no formal WCAG level mandated for this iteration). Note: the functional design already includes concrete accessibility details (Dutch `aria-label` and `aria-pressed` on the theme toggle) that will still be implemented, since they were explicit functional design decisions — this NFR decision only means no additional formal accessibility audit/target is required beyond that.
## CI/CD
- **This iteration**: No CI pipeline is set up yet. Deferred to the Operations phase (Deployment Setup), which will define the concrete build/deploy process for the FTP target.
## Security Baseline — Rule-by-Rule Applicability
| Rule | Applicability | Decision / Rationale |
|---|---|---|
| SECURITY-01 (encryption at rest/in transit) | N/A | No data store exists in this static frontend. |
| SECURITY-02 (access logging on intermediaries) | N/A | No load balancer/API gateway/CDN configured by this unit; would apply at hosting level if applicable, out of scope here. |
| SECURITY-03 (application-level logging) | N/A | No server-side application component; a client-side app has no backend logs to configure. |
| SECURITY-04 (HTTP security headers) | Deferred | Depends on the final hosting choice and whether the host supports custom headers — deferred to Deployment Setup (Operations phase). |
| SECURITY-05 (input validation on API params) | N/A | No API endpoints exist in this unit. |
| SECURITY-06 (least-privilege access policies) | N/A | No IAM/cloud roles involved. |
| SECURITY-07 (restrictive network configuration) | N/A | No network/firewall resources involved. |
| SECURITY-08 (application-level access control) | N/A | No authenticated resources or user accounts exist. |
| SECURITY-09 (hardening/misconfiguration) | Addressed now | Production build via Vite has no sample/demo pages; a top-level React error boundary will show a generic message instead of exposing stack traces. |
| SECURITY-10 (software supply chain) | Addressed now | `package-lock.json` committed; `npm audit` documented as part of build instructions; no unused dependencies added. |
| SECURITY-11 (secure design principles) | N/A | No security-critical logic (auth, payments) exists in this unit. |
| SECURITY-12 (authentication/credential mgmt) | N/A | No authentication exists in this unit. |
| SECURITY-13 (software/data integrity) | Addressed now (partial) | Subresource Integrity (SRI) hashes will be added to the Google Fonts `<link>` tags where the CDN provides stable, hashable assets; no other external CDN resources are used. |
| SECURITY-14 (alerting and monitoring) | Deferred | No backend/log service exists yet; revisit if/when Monitoring Setup (Operations phase) introduces any client-side error/analytics reporting. |
| SECURITY-15 (exception handling / fail-safe defaults) | Addressed now | A top-level React error boundary is added; the `usePackagesQuery` placeholder hook's promise-based `queryFn` will have explicit error handling wired through TanStack Query's error state. |
**Summary**: 10 of 15 Security Baseline rules are N/A for this static, no-backend frontend. 4 rules (SECURITY-09, SECURITY-10, SECURITY-13, SECURITY-15) are addressed during this iteration's Code Generation. 2 rules (SECURITY-04, SECURITY-14) are explicitly deferred to the Operations phase.
@@ -0,0 +1,15 @@
# Tech Stack Decisions — react-frontend-app
| Concern | Decision | Rationale |
|---|---|---|
| Build tool | Vite | Confirmed in requirements.md NFR-1; fast dev server, first-class TypeScript/React support, pairs naturally with Vitest. |
| Language | TypeScript | Confirmed in requirements.md NFR-1; type safety for the domain entities defined in functional design. |
| UI library | React 18+ | Confirmed in requirements.md NFR-1. |
| Styling | Tailwind CSS | Confirmed in requirements.md NFR-2. Theme variants implemented as Tailwind theme classes (`theme-red` / `theme-purple`) per Functional Design Question 2 answer. |
| Routing | TanStack Router, hash-based history (`createHashHistory`) | Confirmed in requirements.md FR-5; hash history chosen per this stage's routing-strategy decision (NFR Requirements Question 4) to be safe on a plain FTP static host without server rewrite rules. |
| Data fetching (forward-looking) | TanStack Query (`@tanstack/react-query`) | Confirmed in requirements.md FR-5; a `QueryClientProvider` is set up now, with one placeholder query hook (`usePackagesQuery`) as defined in Functional Design. |
| Testing | Vitest + React Testing Library | NFR Requirements Question 2 answer A. |
| Linting | ESLint (`typescript-eslint`, `eslint-plugin-react-hooks`) + Prettier | NFR Requirements Question 3 answer A. |
| Package manager | npm (with committed `package-lock.json`) | Default choice for a Vite-scaffolded project; supports SECURITY-10 (lock file requirement). |
| CI | None for this iteration | NFR Requirements Question 6 answer B — deferred to Operations phase. |
| Accessibility | Best-effort (no formal WCAG target this iteration) | NFR Requirements Question 5 answer B; explicit a11y attributes from Functional Design are still implemented. |
@@ -0,0 +1,131 @@
# Execution Plan — React Frontend (SLP Software Marketing Site)
## Detailed Analysis Summary
### Change Impact Assessment
- **User-facing changes**: Yes — the entire marketing site is user-facing; net-new capability is the red/purple theme switcher with persisted preference.
- **Structural changes**: Yes (greenfield) — establishing the whole application structure (Vite + React + TypeScript, Tailwind, TanStack Router, TanStack Query, theming).
- **Data model changes**: Minor — a small static data model for package/pricing content and a theme-token model; no backend data model yet.
- **API changes**: None — no backend/API exists yet; TanStack Query is scaffolded but not wired to a real endpoint.
- **NFR impact**: Yes — Security Baseline extension is enabled and must be assessed rule-by-rule for a static frontend; deployment target (FTP/static hosting) affects routing and build configuration.
### Risk Assessment
- **Risk Level**: Low — greenfield, single static page, no backend, well-defined reference design to copy from.
- **Rollback Complexity**: Easy — no production system yet; this is the initial build.
- **Testing Complexity**: Simple — mostly component rendering/visual + a small amount of interaction logic (theme toggle, persistence).
## Workflow Visualization
```mermaid
flowchart TD
Start(["User Request"])
subgraph INCEPTION["INCEPTION PHASE"]
WD["Workspace Detection<br/><b>COMPLETED</b>"]
RA["Requirements Analysis<br/><b>COMPLETED</b>"]
US["User Stories<br/><b>SKIPPED</b>"]
WP["Workflow Planning<br/><b>IN PROGRESS</b>"]
AD["Application Design<br/><b>SKIP</b>"]
UG["Units Generation<br/><b>SKIP</b>"]
end
subgraph CONSTRUCTION["CONSTRUCTION PHASE"]
FD["Functional Design<br/><b>EXECUTE</b>"]
NFRA["NFR Requirements<br/><b>EXECUTE</b>"]
NFRD["NFR Design<br/><b>EXECUTE</b>"]
ID["Infrastructure Design<br/><b>SKIP</b>"]
CG["Code Generation<br/><b>EXECUTE</b>"]
BT["Build and Test<br/><b>EXECUTE</b>"]
end
subgraph OPERATIONS["OPERATIONS PHASE"]
DS["Deployment Setup<br/><b>EXECUTE</b>"]
MS["Monitoring Setup<br/><b>EXECUTE</b>"]
PRV["Production Readiness Validation<br/><b>EXECUTE</b>"]
end
Start --> WD
WD --> RA
RA --> US
US --> WP
WP --> AD
AD --> UG
UG --> FD
FD --> NFRA
NFRA --> NFRD
NFRD --> ID
ID --> CG
CG --> BT
BT --> DS
DS --> MS
MS --> PRV
PRV --> End(["Complete"])
style WD fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style RA fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style US fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
style WP fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style AD fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
style UG fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
style FD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
style NFRA fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
style NFRD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
style ID fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
style CG fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style BT fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style DS fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
style MS fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
style PRV fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
style Start fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000
style End fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000
style INCEPTION fill:#BBDEFB
style CONSTRUCTION fill:#C8E6C9
style OPERATIONS fill:#FFF59D
linkStyle default stroke:#333,stroke-width:2px
```
Text alternative: Workspace Detection, Requirements Analysis and Workflow Planning are completed (green). User Stories is skipped (gray, dashed). Application Design and Units Generation are skipped (gray, dashed) in Inception. In Construction, Functional Design, NFR Requirements and NFR Design are set to execute (orange, dashed border denotes conditional-but-selected), Infrastructure Design is skipped (gray), while Code Generation and Build and Test always execute (green). In Operations, Deployment Setup and Monitoring Setup execute (orange) and Production Readiness Validation always executes (green) as the final wrap-up stage.
## Phases to Execute
### 🔵 INCEPTION PHASE
- [x] Workspace Detection (COMPLETED)
- [x] Requirements Analysis (COMPLETED)
- [x] User Stories (SKIPPED — single visitor persona, low complexity, no acceptance-criteria ambiguity beyond what requirements.md already captures)
- [x] Execution Plan (IN PROGRESS)
- [ ] Application Design - SKIP
- **Rationale**: No backend services or service-layer design needed. Component decomposition (Nav, Hero, PackageCard, ThemeProvider, etc.) is already outlined in requirements.md and will be finalized during Functional Design.
- [ ] Units Generation - SKIP
- **Rationale**: Single, straightforward unit of work (one React frontend application) — no decomposition into multiple units needed.
### 🟢 CONSTRUCTION PHASE (single unit: `react-frontend-app`)
- [ ] Functional Design - EXECUTE
- **Rationale**: New data models needed — theme/color-token model and static package/pricing content model — plus the component tree and route structure need to be defined before code generation.
- [ ] NFR Requirements - EXECUTE
- **Rationale**: Security Baseline extension is enabled and must be assessed rule-by-rule for applicability to a static, no-backend frontend (e.g. HTTP security headers, dependency/supply-chain scanning, Subresource Integrity for Google Fonts CDN links). Browser-support and deployment-target NFRs from requirements.md also need to be carried into concrete design decisions.
- [ ] NFR Design - EXECUTE
- **Rationale**: NFR Requirements is executing, so applicable NFR patterns (security headers config, lockfile/scanning setup) need to be incorporated into the design.
- [ ] Infrastructure Design - SKIP
- **Rationale**: No cloud infrastructure to design at this stage — the site is a static bundle. Concrete hosting/deployment mechanics (FTP upload, routing fallback strategy) are handled by Deployment Setup in the Operations phase.
- [ ] Code Generation - EXECUTE (ALWAYS)
- **Rationale**: Implementation planning and code generation needed to produce the actual React application.
- [ ] Build and Test - EXECUTE (ALWAYS)
- **Rationale**: Build, test, and verification needed across the (single) unit.
### 🟡 OPERATIONS PHASE
- [ ] Deployment Setup - EXECUTE
- **Rationale**: `Operations Configuration = Yes` (decided in Requirements Analysis). Deployment method (FTP/traditional web host, per NFR-4) needs concrete setup: build/export steps and upload process.
- [ ] Monitoring Setup - EXECUTE
- **Rationale**: `Operations Configuration = Yes`. Even for a static site, basic uptime/availability monitoring or analytics may be relevant — the stage will ask the user what's actually needed.
- [ ] Production Readiness Validation - EXECUTE (ALWAYS once Operations phase is reached)
- **Rationale**: Final wrap-up checklist for the feature.
## Estimated Timeline
- **Total Stages**: 10 (2 skipped, 8 executed) across Inception (remaining), Construction, and Operations
- **Estimated Duration**: Single focused session — small, well-scoped greenfield frontend
## Success Criteria
- **Primary Goal**: A working, statically-buildable React application that reproduces the reference marketing page 1-to-1, with a red-default/purple-selectable theme switcher, scaffolded with TanStack Router and TanStack Query for future growth.
- **Key Deliverables**: React + TypeScript + Vite + Tailwind project; theme system with persistence; ported page content/components; TanStack Router route shell; TanStack Query provider shell; build/test instructions; deployment instructions for FTP/static hosting; production readiness checklist.
- **Quality Gates**: Successful production build; passing component/unit tests; applicable Security Baseline rules satisfied (or explicitly marked N/A with rationale).
@@ -0,0 +1,117 @@
# Requirements Clarification Questions — React Frontend
Please answer each question by filling in the letter choice after the `[Answer]:` tag.
## Question 1: Scope of this first iteration
The request says "start with setting up a static website, but as React". What should be included in this first delivery?
A) Only the landing page content that is already in the reference designs (nav, hero, pakketten, werkwijze, over, contact, footer), rebuilt 1-on-1 as React components
B) The reference page content, plus routing scaffolding (TanStack Router) even though there is only one route today
C) The reference page content, plus a full project skeleton including TanStack Router AND TanStack Query wired up (even though there is no data-fetching need yet)
X) Other (please describe after [Answer]: tag below)
[Answer]: C
## Question 2: Tooling / build setup
Which React tooling stack should be used to set up the project?
A) Vite + React + TypeScript (fast dev server, widely used with TanStack)
B) Vite + React (JavaScript, no TypeScript)
C) Next.js (React framework with built-in routing — note: overlaps with TanStack Router, so would need a decision on which router to use)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 3: Styling approach
The reference designs use hand-written CSS with CSS custom properties (`:root { --bg; --accent; ... }`) for theming. How should styling be implemented in React?
A) Keep plain CSS (CSS Modules or global CSS) using the same CSS custom properties, so the color palette stays swappable exactly like the reference
B) Move to CSS-in-JS (e.g. styled-components / vanilla-extract)
C) Move to a utility CSS framework (e.g. Tailwind CSS), re-implementing the visuals with utility classes
X) Other (please describe after [Answer]: tag below)
[Answer]: C
## Question 4: Color theme switching mechanism
You want red as the default/primary theme, with the purple theme selectable as an addition to the reference designs. How should the user select the theme?
A) A visible UI toggle/switcher on the site (e.g. in the nav) that lets visitors switch between "Rood" and "Paars" at runtime
B) Only a developer-facing mechanism for now (e.g. a config value or environment variable) — no visible UI control yet, visible switcher can be a later iteration
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 5: Theme persistence
If a visible theme switcher is added (Question 4 = A), should the chosen theme be remembered between visits?
A) Yes — persist the choice in the browser (e.g. localStorage) so it's remembered on return visits
B) No — theme resets to red (default) on every page load/visit
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 6: Content fidelity vs. placeholders
The reference designs contain real Dutch marketing copy (package prices, e-mail address `info@slpsoftware.nl`, etc.). Should this content be copied 1-on-1?
A) Yes — copy all text, prices, and contact details 1-on-1 exactly as in the reference HTML
B) Copy the structure/layout 1-on-1, but replace specific business content (prices, e-mail) with placeholders to be finalized later
X) Other (please describe after [Answer]: tag below)
[Answer]: A, this will be replaced with data fetching later, but for now use the data from the designs
## Question 7: Interactivity already present in the reference
The reference HTML has a couple of small interactive/dynamic bits (a blinking caret animation in the hero code line, `:hover`/`:focus-visible` states, smooth scroll anchor links). Should these be preserved as-is?
A) Yes — preserve all existing visual micro-interactions exactly (blinking caret, hover states, smooth scroll)
B) Preserve hover/focus states, but drop the blinking caret animation
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question 8: Target deployment / hosting
Is there a specific hosting target already in mind for this static React site (relevant later for build output configuration)?
A) Not decided yet — keep the build generic (static output, deployable anywhere)
B) Static hosting / CDN (e.g. Netlify, Vercel, Cloudflare Pages, GitHub Pages)
C) Traditional web host via FTP/manual upload (as hinted by the `demo-setup` / on-premises style deployment)
X) Other (please describe after [Answer]: tag below)
[Answer]: C
## Question 9: Browser/device support baseline
What is the minimum browser/device support baseline for this site?
A) Modern evergreen browsers only (latest Chrome, Firefox, Edge, Safari) — matches the reference's use of modern CSS (backdrop-filter, clamp, etc.)
B) Broader legacy support required (older browsers, e.g. older Safari/IE-adjacent) with graceful degradation
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question: Security Extensions
Should security extension rules be enforced for this project?
A) Yes — enforce all SECURITY rules as blocking constraints (recommended for production-grade applications)
B) No — skip all SECURITY rules (suitable for PoCs, prototypes, and experimental projects, or for a marketing-only static site with no backend/user data)
X) Other (please describe after [Answer]: tag below)
[Answer]: A
## Question: Property-Based Testing Extension
Should property-based testing (PBT) rules be enforced for this project?
A) Yes — enforce all PBT rules as blocking constraints
B) Partial — enforce PBT rules only for pure functions and serialization round-trips
C) No — skip all PBT rules (suitable for this kind of largely static, UI-only marketing site with no significant business logic)
X) Other (please describe after [Answer]: tag below)
[Answer]: C
## Question: Operations Phase
Should this feature go through the Operations phase after Construction (setting up deployment and monitoring)?
A) Yes — run the Operations phase after Construction (deployment + monitoring setup)
B) No — stop after Build and Test (deployment/monitoring are out of scope for this feature)
C) Not sure yet — ask me again after the Construction phase
X) Other (please describe after [Answer]: tag below)
[Answer]: A
@@ -0,0 +1,100 @@
# Requirements — React Frontend (SLP Software Marketing Site)
## Intent Analysis Summary
- **User Request**: Build a React frontend for SLP Software. Two static HTML reference designs exist in `References/` (`slp-software.html` = purple accent, `slp-software-rood.html` = red accent) that are the same design with only a different accent color. Red must become the primary/default theme; the purple theme must remain selectable (this selectability is new, not present in the original static designs). All other content/layout must be ported 1-to-1 into React. Start with a static site, but built as React. For later use: TanStack Router and TanStack Query should be used where needed. The AI-DLC workflow must be used to set this up.
- **Request Type**: New Project (Greenfield)
- **Scope Estimate**: Single Component — one marketing/landing page rebuilt as a React application, plus supporting theming infrastructure
- **Complexity Estimate**: Simple to Moderate — the visual/content scope is a single static page, but a full modern tooling skeleton (Vite, TypeScript, TanStack Router, TanStack Query, Tailwind CSS, theming) is being set up for future growth
- **Requirements Depth**: Standard
## Reference Design Analysis
Both reference files were compared byte-for-byte (`Compare-Object`). They are **identical in structure, markup, and copy**; the only differences are CSS custom property values used for theming:
| Variable | Purple (`slp-software.html`) | Red (`slp-software-rood.html`) |
|---|---|---|
| `--bg` | `#0E1220` | `#140C0E` |
| `--surface` | `#151A2C` | `#1F1315` |
| `--surface-2` | `#1B2138` | `#291719` |
| `--line` | `#262E4A` | `#402226` |
| `--text` | `#E9EBF5` | `#F5EAEB` |
| `--muted` | `#98A0BA` | `#B69C9F` |
| `--accent` | `#8B7CFF` | `#E04848` |
| `--accent-soft` | `rgba(139,124,255,.14)` | `rgba(224,72,72,.16)` |
| `--accent-line` | `rgba(139,124,255,.35)` | `rgba(224,72,72,.40)` |
| Hero radial gradients, badge/button text color, `#pakketten` gradient | purple-tinted values | red-tinted values |
Page structure (both files, identical):
1. **Nav** — logo ("SLP.Software"), links (Pakketten / Werkwijze / Over), CTA ("Start project")
2. **Hero** — eyebrow label, H1, lead paragraph, animated code line with blinking caret, two CTA buttons
3. **Pakketten (Packages)** — 3 pricing cards (Landingspagina €300, Website €750 — featured, Maatwerk — quote-based)
4. **Werkwijze (Process)** — 3-step process (intake, bouwen, live)
5. **Over (About)** — company description + tech stack panel
6. **Contact** — contact box with mailto CTA
7. **Footer** — copyright + mono tagline
## Functional Requirements
### FR-1: Page Content Parity
The React application MUST reproduce all sections, copy, structure, and visual layout of the reference designs 1-to-1: Nav, Hero, Pakketten, Werkwijze, Over, Contact, Footer. All Dutch marketing copy, package prices (€300 / €750 / "Op maat"), and the contact e-mail address (`info@slpsoftware.nl`) are copied exactly as-is from the reference HTML for this iteration; this content is expected to be replaced by dynamically fetched data in a future iteration (see FR-5).
### FR-2: Componentization
The page MUST be decomposed into reusable React components (e.g. `Nav`, `Hero`, `PackagesSection`, `PackageCard`, `ProcessSection`, `AboutSection`, `ContactSection`, `Footer`) rather than a single monolithic page component.
### FR-3: Theme Switching
- The site MUST default to the **red** theme on first load.
- The **purple** theme MUST remain selectable by the visitor via a visible UI control (e.g. a toggle/switcher in the nav).
- The chosen theme MUST be persisted in the browser (`localStorage` or equivalent) so it is remembered on return visits; if no stored preference exists, red is used.
- Theme values MUST be implemented so that both palettes (and any future palette) can be added without duplicating component markup — i.e. only the color tokens change, not the structure.
### FR-4: Preserved Micro-Interactions
All existing micro-interactions from the reference designs MUST be preserved: the blinking caret animation in the hero code line, `:hover` / `:focus-visible` states on links, cards and buttons, and smooth-scroll behavior for in-page anchor navigation (respecting `prefers-reduced-motion`).
### FR-5: Forward-Looking Data Layer (Preparation Only)
- TanStack Router MUST be set up and wired into the application shell, even though the initial scope has effectively a single route (`/`). Route structure should be organized so that adding routes later is straightforward.
- TanStack Query MUST be installed and configured (e.g. `QueryClientProvider` at the app root) as part of this iteration's skeleton, in preparation for a future iteration where package/content data is fetched from a backend instead of being hardcoded. No actual network data-fetching is required yet — static data (matching FR-1) is used as the source for now, structured so it can be swapped for a TanStack Query hook later with minimal changes.
## Non-Functional Requirements
### NFR-1: Tooling & Language
- Build tool: **Vite**
- Language: **TypeScript**
- UI library: **React**
### NFR-2: Styling
- **Tailwind CSS** is used as the utility CSS framework to re-implement the reference visuals.
- The color palette (red default / purple alternate) MUST be modeled as design tokens (e.g. CSS custom properties consumed via Tailwind theme config, or a Tailwind theme extension keyed by a `data-theme` attribute/class) so that switching a single token set changes the whole site's palette, mirroring how the reference designs use `:root` CSS variables.
### NFR-3: Browser Support
Modern evergreen browsers only (latest Chrome, Firefox, Edge, Safari). No legacy/IE-adjacent support required. This matches the reference design's use of modern CSS features (`backdrop-filter`, `clamp()`, CSS custom properties).
### NFR-4: Deployment Target
The build output MUST remain a plain static bundle (HTML/CSS/JS, no Node.js server required at runtime) so it can be deployed to a traditional web host via FTP/manual upload. This has a design implication for TanStack Router: once more than one route exists, either hash-based routing or host-level rewrite rules (e.g. `.htaccess`) will be needed for direct-link/deep-link support on a plain static FTP host — to be finalized during Application Design / Infrastructure Design when routing needs are concrete.
### NFR-5: Operations Phase
This feature WILL go through the Operations phase after Construction (deployment setup + monitoring setup + production readiness validation).
## Extension Configuration
| Extension | Enabled | Notes |
|---|---|---|
| **Security Baseline** | Yes | Enforced as blocking constraints. Most backend-oriented rules (auth, API validation, network config, encryption at rest, etc.) are expected to be **N/A** for this static, no-backend marketing site — applicability will be re-assessed rule-by-rule at each stage (e.g. HTTP security headers via hosting/CDN config, dependency lock file & vulnerability scanning, Subresource Integrity for the Google Fonts CDN links). |
| **Property-Based Testing** | No | Skipped — this is a largely static, UI-only marketing site with no significant business logic. |
## Out of Scope (for this iteration)
- Real backend/API integration for package/content data (prepared for via TanStack Query, but not implemented)
- Multiple routes/pages beyond the single landing page
- CMS or admin interface for editing content
- Analytics/tracking integration
- Automated deployment pipeline details (handled in the Operations phase)
## Open Design Considerations (to resolve later, not blocking)
- Exact mechanism for FTP-safe client-side routing once multiple routes exist (hash routing vs. `.htaccess` rewrites) — Application Design / Infrastructure Design.
- Exact shape of the future data-fetching layer (API contract) that TanStack Query will eventually call — deferred until a backend exists.
## Summary
This is a greenfield React frontend for SLP Software's marketing site. The visual and content scope is a straightforward 1-to-1 port of an existing static HTML/CSS design (available in two color variants). The key net-new requirement beyond the reference designs is a red-default / purple-selectable theme switcher with persisted preference. The project is set up with Vite + React + TypeScript + Tailwind CSS, and is scaffolded from day one with TanStack Router and TanStack Query to support future growth, even though the current scope has a single route and static data. Security Baseline is enforced; Property-Based Testing is skipped; the Operations phase will run after Construction.
@@ -0,0 +1,77 @@
# Deployment Setup Questions
Context: tijdens NFR Design is al besloten dat de site gebouwd wordt met hash-based routing zodat het werkt op een traditionele FTP/statische webhost zonder server-side rewrite-regels (zie `src/router.tsx`). De build levert een statische bundel op in `dist/` (HTML/JS/CSS/fonts).
Beantwoord elke vraag door de letter van je keuze na de `[Answer]:` tag in te vullen.
## Question 1: Include Deployment Setup?
Wil je dat deployment voor deze feature wordt opgezet als onderdeel van deze workflow?
A) Ja — help me met het opzetten van deployment
B) Nee — deployment wordt elders geregeld of is niet nodig voor deze feature
C) Niet zeker — stel een aanpak voor op basis van het project en ik beslis dan
X) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 2: Deployment Method
Hoe moet deze feature gedeployed worden?
A) CI/CD pipeline (bijv. GitHub Actions, GitLab CI, Azure DevOps, Jenkins)
B) Cloud platform deployment (bijv. AWS, Azure, GCP — managed service of Infrastructure as Code)
C) On-premises / zelf gehoste server
D) Handmatig / lokale deployment (bijv. build een artefact en upload het via FTP/SFTP naar een webhost)
E) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 3: Omgevingen
Voor welke omgeving(en) moeten deployment-instructies gemaakt worden?
A) Alleen productie (single environment)
B) Staging en productie
C) Development, staging en productie
D) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 4: Automatiseringsniveau
Welk automatiseringsniveau wil je?
A) Volledig geautomatiseerde pipeline die draait bij elke push/merge naar master
B) Gedeeltelijk geautomatiseerd (bijv. build lokaal, upload automatisch via een script)
C) Volledig handmatige, gedocumenteerde stappen (bijv. build lokaal, zelf uploaden via FTP-client)
D) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 5: Rollback-strategie
Hoe moet een mislukte deployment teruggedraaid kunnen worden?
A) Vorige `dist/`-build opnieuw uploaden (bewaar altijd de laatste werkende build als backup)
B) Versiebeheer via tags/releases in git, opnieuw builden vanaf een eerdere tag
C) Geen expliciete rollback nodig (statische site, snel opnieuw te builden en uploaden)
D) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 6: Doelhost en overdrachtsmethode (alleen relevant bij handmatige/lokale deployment)
Welke webhost/host wordt gebruikt en hoe komt het build-artefact daar terecht?
A) Traditionele hostingprovider via FTP
B) Traditionele hostingprovider via SFTP
C) Upload via het controlepaneel van de hostingprovider (bijv. cPanel file manager)
D) Nog niet bekend — stel een generieke FTP/SFTP-aanpak voor die ik later kan invullen
E) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]:
## Question 7: Opslag van inloggegevens (alleen relevant bij handmatige/lokale deployment)
Waar worden de inloggegevens voor de FTP/SFTP-overdracht bewaard? (Nooit credentials hardcoden in gegenereerde instructies.)
A) In een lokale password manager / FTP-client configuratie (bijv. FileZilla site manager), niet in de repo
B) In environment variables op de machine die deployed (bijv. voor een toekomstig deploy-script)
C) Nog niet bepaald — vermeld dit als open actiepunt in de instructies
D) Anders (beschrijf na de [Answer]: tag hieronder)
[Answer]: