Files
fete/specs/012-link-preview/tasks.md
nitrix 751201617d
All checks were successful
CI / backend-test (push) Successful in 1m9s
CI / frontend-test (push) Successful in 23s
CI / frontend-e2e (push) Successful in 1m12s
CI / build-and-publish (push) Has been skipped
Add Open Graph and Twitter Card meta-tags for link previews
Replace PathResourceResolver SPA fallback with SpaController that
injects OG/Twitter meta-tags into cached index.html template.
Event pages get event-specific tags (title, date, location),
all other pages get generic fete branding. Includes og-image.png
brand asset and forward-headers-strategy for proxy support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:25:39 +01:00

10 KiB
Raw Permalink Blame History

Tasks: Link Preview (Open Graph Meta-Tags)

Input: Design documents from /specs/012-link-preview/ Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/

Tests: Included — constitution mandates TDD (Red → Green → Refactor).

Organization: Tasks grouped by user story for independent implementation and testing.

Format: [ID] [P?] [Story] Description

  • [P]: Can run in parallel (different files, no dependencies)
  • [Story]: Which user story this task belongs to (e.g., US1, US2, US3)
  • Include exact file paths in descriptions

Phase 1: Setup

Purpose: Prepare frontend template and static assets for meta-tag injection

  • T001 Add <!-- OG_META_TAGS --> placeholder comment in <head> of frontend/index.html
  • T002 [P] Create og-image.png brand image (1200x630) in frontend/public/og-image.png
  • T003 [P] Add server.forward-headers-strategy=framework to backend/src/main/resources/application.properties

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Core infrastructure for HTML meta-tag injection that ALL user stories depend on

⚠️ CRITICAL: No user story work can begin until this phase is complete

  • T004 Write unit tests for MetaTagRenderer (HTML escaping, meta-tag HTML output) in backend/src/test/java/de/fete/adapter/in/web/MetaTagRendererTest.java — tests MUST fail (Red)
  • T005 Implement MetaTagRenderer utility that renders meta-tag key-value pairs into HTML <meta> strings with proper HTML escaping in backend/src/main/java/de/fete/adapter/in/web/MetaTagRenderer.java
  • T006 Write integration tests for SpaController base functionality (serves index.html, replaces placeholder) in backend/src/test/java/de/fete/adapter/in/web/SpaControllerTest.java — tests MUST fail (Red)
  • T007 Implement SpaController that caches index.html template at startup and replaces <!-- OG_META_TAGS --> placeholder before serving in backend/src/main/java/de/fete/adapter/in/web/SpaController.java
  • T008 Remove PathResourceResolver SPA fallback from backend/src/main/java/de/fete/config/WebConfig.java (replaced by SpaController)

Checkpoint: SPA still works (index.html served for all non-API/non-static routes), but now through SpaController with placeholder replacement ready


Phase 3: User Story 1 — Event Link Preview in Messenger (Priority: P1) 🎯 MVP

Goal: Shared event links display rich preview cards with event title, date, location, and description in messengers

Independent Test: Share an event URL — messenger shows event title and formatted description with date/location

Tests for User Story 1 ⚠️

NOTE: Write these tests FIRST, ensure they FAIL before implementation

  • T009 [P] [US1] Unit tests for OpenGraphService.buildEventMeta() — full event data, no location, no description, long title truncation, special characters in backend/src/test/java/de/fete/application/OpenGraphServiceTest.java
  • T010 [P] [US1] Integration tests for SpaController event routes — GET /events/{token} returns HTML with event-specific OG meta-tags, event not found falls back to generic in backend/src/test/java/de/fete/adapter/in/web/SpaControllerTest.java

Implementation for User Story 1

  • T011 [US1] Implement OpenGraphService.buildEventMeta() — fetch event by token, compose og:title (truncated 70 chars), og:description (date + location + description, max 200 chars), og:url, og:type, og:site_name, og:image in backend/src/main/java/de/fete/application/service/OpenGraphService.java
  • T012 [US1] Wire SpaController to call OpenGraphService for /events/{token} routes, inject event-specific meta-tags via MetaTagRenderer in backend/src/main/java/de/fete/adapter/in/web/SpaController.java
  • T013 [US1] E2E test — deferred (requires running backend; covered by integration tests)

Checkpoint: Event links show rich OG preview cards in messengers. MVP complete.


Phase 4: User Story 2 — Fallback Preview for Generic Pages (Priority: P2)

Goal: Non-event pages (homepage, event list, create) show a meaningful generic fete preview when shared

Independent Test: Share the homepage URL — messenger shows "fete" as title and generic app description

Tests for User Story 2 ⚠️

NOTE: Write these tests FIRST, ensure they FAIL before implementation

  • T014 [P] [US2] Unit tests for OpenGraphService.buildGenericMeta() — verify generic title "fete", generic description, correct URL, image URL in backend/src/test/java/de/fete/application/service/OpenGraphServiceTest.java
  • T015 [P] [US2] Integration tests for SpaController generic routes — GET /, GET /create return HTML with generic OG meta-tags in backend/src/test/java/de/fete/adapter/in/web/SpaControllerTest.java

Implementation for User Story 2

  • T016 [US2] Implement OpenGraphService.buildGenericMeta() — title "fete", description "Privacy-focused event planning. Create and share events without accounts.", type "website", site_name "fete" in backend/src/main/java/de/fete/application/service/OpenGraphService.java
  • T017 [US2] Wire SpaController to call OpenGraphService.buildGenericMeta() for all non-event HTML routes in backend/src/main/java/de/fete/adapter/in/web/SpaController.java
  • T018 [US2] E2E test — deferred (requires running backend; covered by integration tests)

Checkpoint: All shared fete links (event-specific and generic) show rich preview cards


Phase 5: User Story 3 — Twitter/X Card Support (Priority: P3)

Goal: Links shared on Twitter/X also display rich preview cards via Twitter Card meta-tags

Independent Test: Verify HTML source contains twitter:card, twitter:title, twitter:description meta-tags

Tests for User Story 3 ⚠️

NOTE: Write these tests FIRST, ensure they FAIL before implementation

  • T019 [P] [US3] Unit tests for Twitter Card meta-tag generation — verify twitter:card = "summary", twitter:title, twitter:description match OG values in backend/src/test/java/de/fete/application/service/OpenGraphServiceTest.java
  • T020 [P] [US3] Integration tests for SpaController — event and generic routes include Twitter Card meta-tags in backend/src/test/java/de/fete/adapter/in/web/SpaControllerTest.java

Implementation for User Story 3

  • T021 [US3] Extend OpenGraphService to include Twitter Card meta-tags (twitter:card, twitter:title, twitter:description) alongside OG tags in backend/src/main/java/de/fete/application/service/OpenGraphService.java
  • T022 [US3] Extend MetaTagRenderer to render <meta name="twitter:*"> tags (using name attribute instead of property) in backend/src/main/java/de/fete/adapter/in/web/MetaTagRenderer.java
  • T023 [US3] E2E test — fetch event page and homepage, verify Twitter Card meta-tags present alongside OG tags in frontend/e2e/link-preview.spec.ts

Checkpoint: All three user stories complete — OG tags, generic fallback, and Twitter Cards all working


Phase 6: Polish & Cross-Cutting Concerns

Purpose: Edge cases, hardening, and final verification

  • T024 [P] Verify HTML escaping for special characters (quotes, ampersands, angle brackets) in meta-tag values across all routes — edge-case tests in MetaTagRendererTest.java
  • T025 [P] Verify SpaController does not intercept static asset requests — SpaController only handles explicit routes, not wildcard
  • T026 Run full backend test suite (cd backend && ./mvnw verify) and fix any regressions — 97 tests, 0 bugs
  • T027 Run full frontend test suite (cd frontend && npm run test:unit) — 133 tests passed

Dependencies & Execution Order

Phase Dependencies

  • Setup (Phase 1): No dependencies — can start immediately
  • Foundational (Phase 2): Depends on T001 (placeholder in index.html) — BLOCKS all user stories
  • US1 (Phase 3): Depends on Foundational phase completion
  • US2 (Phase 4): Depends on Foundational phase completion — can run in parallel with US1
  • US3 (Phase 5): Depends on US1 or US2 (extends their meta-tag output)
  • Polish (Phase 6): Depends on all user stories being complete

User Story Dependencies

  • User Story 1 (P1): Can start after Foundational (Phase 2) — no dependencies on other stories
  • User Story 2 (P2): Can start after Foundational (Phase 2) — independent from US1
  • User Story 3 (P3): Depends on US1 or US2 — extends existing OG meta-tag output with Twitter tags

Within Each User Story

  • Tests MUST be written and FAIL before implementation (TDD Red phase)
  • Service layer before controller wiring
  • Unit tests before integration tests before E2E tests
  • Story complete before moving to next priority

Parallel Opportunities

  • T001, T002, T003 can all run in parallel (Setup phase)
  • T004 and T006 can run in parallel (Foundational tests — different files)
  • T009, T010 can run in parallel (US1 tests — different files)
  • T014, T015 can run in parallel (US2 tests — different files)
  • T019, T020 can run in parallel (US3 tests — different files)
  • US1 and US2 can be worked on in parallel after Foundational phase

Parallel Example: User Story 1

# Launch US1 tests in parallel (Red phase):
Task: "Unit tests for OpenGraphService.buildEventMeta() in OpenGraphServiceTest.java"
Task: "Integration tests for SpaController event routes in SpaControllerTest.java"

# Then implement sequentially:
Task: "Implement OpenGraphService.buildEventMeta()"
Task: "Wire SpaController for /events/{token} routes"
Task: "E2E test for event page meta-tags"

Implementation Strategy

MVP First (User Story 1 Only)

  1. Complete Phase 1: Setup (T001T003)
  2. Complete Phase 2: Foundational (T004T008)
  3. Complete Phase 3: User Story 1 (T009T013)
  4. STOP and VALIDATE: Share an event link in a messenger, verify preview card
  5. Deploy/demo if ready

Incremental Delivery

  1. Setup + Foundational → SpaController serving index.html with placeholder replacement
  2. Add US1 → Event links show rich previews → Deploy (MVP!)
  3. Add US2 → Generic pages also show previews → Deploy
  4. Add US3 → Twitter/X cards work too → Deploy
  5. Polish → Edge cases hardened → Final release

Notes

  • [P] tasks = different files, no dependencies
  • [Story] label maps task to specific user story for traceability
  • Each user story is independently completable and testable
  • TDD enforced: write tests first, verify they fail, then implement
  • Commit after each task or logical group
  • Stop at any checkpoint to validate story independently