The native datetime-local picker on iOS Safari has an intrinsic min-width
that exceeds the form container, and its webkit pseudo-elements don't
inherit the glass text color, making the selected value invisible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LightningCSS (Vite 8) was stripping the unprefixed backdrop-filter when
it saw the manual -webkit- prefix, breaking blur effects in Firefox and
on production. Let LightningCSS handle prefixing automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures deterministic CSS output across build environments (local vs
Docker/Alpine) by pinning browser targets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aligns the Docker build environment with the local development setup
which already uses Node 25.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Organizers can now cancel events directly from the event list via the
existing PATCH /events/{eventToken} API. The confirmation dialog shows
role-differentiated messaging: "Cancel event?" with a severity warning
for organizers vs. "Remove event?" for attendees. Responses 204, 409,
and 404 all result in successful removal from the local list.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move back navigation (chevron + "fete" brand) from per-view
definitions into a shared BackLink component rendered in App.vue.
Shown on all pages except home. Hero overlay gets pointer-events:
none so the link stays clickable on the event detail page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace harsh "permanently cancelled" language with friendlier
"The organizer will no longer see you as attending" and rename
buttons from "Cancel attendance" to "Cancel RSVP".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add client-side watch/bookmark functionality: users can save events to
localStorage without RSVPing via a bookmark button next to the "I'm attending"
CTA. Watched events appear in the event list with a "Watching" label.
Bookmark is only visible for visitors (not attendees or organizers).
Includes spec, plan, research, tasks, unit tests, and E2E tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert Event and Rsvp from mutable POJOs to Java records
- Move all 8 exception classes to application.service.exception sub-package
- Add ArchUnit rule enforcing domain models must be records
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add PATCH /events/{eventToken} endpoint for organizers to cancel events,
cancellation banner for visitors, and RSVP rejection on cancelled events.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aligns the path parameter naming with the value object convention
used throughout the codebase (eventToken, rsvpToken, organizerToken).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows guests to cancel their RSVP via a DELETE endpoint using their
guestToken. Frontend shows cancel button in RsvpBar and clears local
storage on success. Includes unit tests, integration tests, and E2E spec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a Spring @Scheduled job (daily at 03:00) that deletes all events
whose expiry_date is before CURRENT_DATE using a native SQL DELETE.
RSVPs are cascade-deleted via the existing FK constraint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The expiry date is no longer user-facing: it is removed from the API
(request and response) and the frontend. The backend now automatically
calculates it as the event date plus 7 days. The expired banner and
RSVP-bar filtering by expired status are also removed from the UI,
since expiry is purely an internal data-retention mechanism.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Wrap the "I'm attending" button with animated glow-border and
glass-inner styling. Update test selectors for new structure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use .glass class on form fields and buttons on gradient backgrounds.
Buttons get gradient glow border via background-clip trick. Solid
white fallback preserved for BottomSheet context.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Centralize all hardcoded rgba color values into CSS custom properties
and extract glass/glow styles into reusable utility classes (.glass,
.glass-inner, .glow-border, .glow-border--animated) in main.css.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace solid orange FAB with glassmorphism inner and a conic
gradient border (pink-purple-indigo) with subtle glow halo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hard-edged color overlay with CSS mask-image fade-out and
increase hero height to 420px for a seamless blend into the aurora
mesh background.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use layered radial gradients on a dark base (#1B1730) with
backdrop blur for an organic, aurora-like background effect
that better complements the glassmorphism event cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace solid white event cards with glass-effect cards featuring
backdrop blur, semi-transparent gradient backgrounds, and light
borders that blend with the Electric Dusk gradient background.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New GET /events/{token}/attendees endpoint returns attendee names when
a valid organizer token is provided (403 otherwise). The frontend
conditionally renders the list below the attendee count for organizers,
silently degrading for visitors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Group events into five temporal sections with section headers, date subheaders,
and context-aware time display (clock time for upcoming, relative for past).
Includes new useEventGrouping composable, SectionHeader and DateSubheader
components, full unit and E2E test coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace card-based event detail view with full-screen gradient layout.
Add hero image with gradient overlay, icon-based meta rows, and
"About" section. Content renders directly on the gradient background
with white text for an app-native feel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enable users to see all their saved events on the home screen, sorted
by date with upcoming events first. Key capabilities:
- EventCard with title, relative time display, and organizer/attendee
role badge
- Sortable EventList with past-event visual distinction (faded style)
- Empty state when no events are stored
- Swipe-to-delete gesture with confirmation dialog
- Floating action button for quick event creation
- Rename router param :token → :eventToken across all views
- useRelativeTime composable (Intl.RelativeTimeFormat)
- useEventStorage: add validation, removeEvent(), reactive versioning
- Full E2E and unit test coverage for all new components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move feature summaries for 18 unimplemented specs into
.specify/memory/ideen.md before deleting the full spec files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Gitea runner cannot reach gitea.com (IPv6 timeout), so switch to
the akkuman/gitea-release-action mirror hosted on GitHub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generate changelog from commits between tags and create a Gitea release
using the official gitea-release-action after publishing container images.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds ExpiryDateBeforeEventException (400) when expiryDate <= eventDate,
asserts DB row count unchanged after every rejection in integration tests,
and replaces all hardcoded dates in EventServiceTest with TODAY-relative
expressions derived from the fixed Clock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds expiry check to RsvpService using an injected Clock for testability,
handles EventExpiredException in GlobalExceptionHandler as 409 Conflict,
and adds unit + integration tests using relative dates from a fixed clock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces BottomSheet and RsvpBar components, integrates the RSVP
submission flow into EventDetailView, extends useEventStorage with
saveRsvp/getRsvp, and adds unit tests plus an E2E spec for the RSVP
workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents future regressions where controllers bypass the application layer
and access repositories directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The EventController was directly accessing RsvpRepository (an outbound port)
to count attendees, bypassing the application layer. Introduce a dedicated
inbound port and implement it in RsvpService. Remove the now-unused Clock
dependency from RsvpService.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce typed token value objects (EventToken, OrganizerToken,
RsvpToken) and refactor all existing Event code to use them.
Add POST /events/{token}/rsvps endpoint that persists an RSVP and
returns an rsvpToken. Populate attendeeCount in GET /events/{token}
from a real count query instead of hardcoded 0.
Includes: OpenAPI spec, Liquibase migration (rsvps table with
ON DELETE CASCADE), domain model, hexagonal ports/adapters,
service layer, and full test coverage (unit + integration).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spec, research decisions, implementation plan, data model,
API contract, and task breakdown for the RSVP feature.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Encodes the workflow for creating PRs, monitoring CI status via
Actions API (cross-referencing head SHA), and merging when green.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The hook used --noEmit which is less strict than CI's --build,
causing type errors to slip through.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add missing timezone field to CreateEventResponse mock
- Fix createTestRouter signature to accept optional token parameter
- Add non-null assertion for dateField element access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New view fetches event via openapi-fetch, formats date/time with
Intl.DateTimeFormat. Skeleton shimmer during loading (CSS-only).
Create form now sends auto-detected timezone.
Unit tests for all five view states, E2E tests with MSW mocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Domain: add timezone field to Event and CreateEventCommand.
Ports: new GetEventUseCase inbound port.
Service: implement getByEventToken, validate IANA timezone on create.
Controller: map to GetEventResponse, compute expired flag via Clock.
Persistence: timezone column in JPA entity and mapping.
Tests: integration tests use DTOs + ObjectMapper instead of inline JSON,
GET tests seed DB directly via JpaRepository for isolation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenAPI: new GetEventResponse schema, timezone on Create request/response.
Liquibase: add timezone VARCHAR(64) NOT NULL DEFAULT 'UTC' column.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spec, research, data model, API contract, implementation plan, and
task breakdown for the public event detail page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Node 25 localStorage warning from MSW broke vue-tsc type-check
because the override signature was incompatible with the Signals type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Human-readable reference for the clarify → plan → tasks → analyze → implement
loop and the file structure it produces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move cross-cutting docs (personas, design system, implementation phases,
Ideen.md) to .specify/memory/
- Move cross-cutting research and plans to .specify/memory/research/ and
.specify/memory/plans/
- Extract 5 setup tasks from spec/setup-tasks.md into individual
specs/001-005/spec.md files with spec-kit template format
- Extract 20 user stories from spec/userstories.md into individual
specs/006-026/spec.md files with spec-kit template format
- Relocate feature-specific research and plan docs into specs/[feature]/
- Add spec-kit constitution, templates, scripts, and slash commands
- Slim down CLAUDE.md to Claude-Code-specific config, delegate principles
to .specify/memory/constitution.md
- Update ralph.sh with stream-json output and per-iteration logging
- Delete old spec/ and docs/agents/ directories
- Gitignore Ralph iteration JSONL logs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Runs Playwright E2E tests with Chromium after checkout.
Uploads HTML report as artifact on failure.
build-and-publish now requires all three test jobs.
Research reports on datetime handling, RFC 9457, font selection.
Implementation plans for US-1 create event and post-review fixes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Post-creation confirmation page showing shareable event URL with
copy-to-clipboard and fallback feedback on failure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Form with client-side validation, server error handling, aria-invalid/
aria-describedby for a11y, localStorage persistence via useEventStorage
composable. Routes for /create and /events/:token.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EventController for POST /events, GlobalExceptionHandler mapping
validation and business exceptions to problem+json responses.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
JPA entity, repository, persistence adapter for events. Liquibase
changelog creates the events table with BIGSERIAL ID and UUID tokens.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Event entity, CreateEventCommand, ports (CreateEventUseCase,
EventRepository), and EventService with Clock injection for
deterministic testing. Expiry date must be in the future.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define CreateEventRequest, CreateEventResponse, ProblemDetail, and
ValidationProblemDetail schemas. RFC 9457 problem details for errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip default Vue components (HelloWorld, TheWelcome, icons, AboutView),
base.css, and placeholder assets. Add Sora font (self-hosted WOFF2),
Electric Dusk color palette, and design system spec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostToolUse hook triggers on openapi/*.yaml edits and runs
redocly lint with the recommended ruleset (security-defined
disabled since endpoints are intentionally public).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Honeypot spam protection is overengineered for this project's scope.
Removed the acceptance criteria from both stories and added addenda
documenting the decision. Updated implementation order and review
findings accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The OpenAPI spec is the single source of truth for the REST API
contract. Endpoints and schemas must be defined in the spec before
writing implementation code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rework the implementation roadmap from parallelizable phases to a strict
sequential order optimized for earliest usable increments. Key changes:
- All 20 user stories in a single sequential queue (no parallelization)
- Progress tracker at the top for status tracking
- US-17 (dark mode) moved from Phase 5 to Increment 4 (before US-15)
- US-14 (PWA) moved to last position
- Deferred AC activation schedule added
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up development infrastructure for TDD: JPA + Liquibase for
database migrations, Testcontainers for integration tests against
real PostgreSQL, profile-based configuration (prod/local), and
README deployment documentation with docker-compose example.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Project-specific skill that validates version, checks for clean
working tree and pushed commits, then creates and pushes a SemVer
tag to trigger the CI/CD pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All manual verification passed:
- Branch push: tests only, no image build
- Non-SemVer tag: tests only, no image build
- SemVer tag (0.0.1): all jobs green, 4 tags in Gitea registry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The act_runner does not have Buildah installed. Docker is available
via socket forwarding, so use docker build/tag/push instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single workflow with three jobs:
- backend-test: JDK 25, ./mvnw -B verify (Checkstyle, JUnit, ArchUnit, SpotBugs)
- frontend-test: Node 24, lint, type generation, type-check, unit tests, production build
- build-and-publish: Buildah image build + push with rolling SemVer tags (only on vX.Y.Z tags)
Includes research report and implementation plan.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace server.servlet.context-path=/api with addPathPrefix so API
endpoints stay under /api while static resources and SPA routes are
served at /. Spring Boot falls back to index.html for unknown paths
(SPA forwarding). Multi-stage Dockerfile builds frontend (Node 24)
and backend (Temurin 25) into a single 250MB JRE-alpine image with
Docker-native HEALTHCHECK.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
T-2 was "Dockerfile + configuration" but database connectivity
cannot be meaningfully verified without JPA and migrations (T-4).
Split: T-2 focuses on the multi-stage Dockerfile, T-4 absorbs
DATABASE_URL config, env vars, and docker-compose documentation.
Updated dependency graph and Mermaid diagram accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check off all T-1 acceptance criteria (retroactively) and the health-check
criterion of T-2. Add methodology rule to CLAUDE.md requiring acceptance
criteria to be checked off when tasks or stories are completed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: openapi-generator-maven-plugin generates Spring interfaces and DTOs
from the spec. Frontend: openapi-typescript + openapi-fetch provide type-safe
API access. Both sides get compile-time contract enforcement from a single
api.yaml file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Research API-first approach with Spring Boot (openapi-generator-maven-plugin)
and Vue 3 frontend (openapi-typescript + openapi-fetch). Add T-5 setup task
for scaffolding the tooling. Update T-4 to depend on T-5 (removes redundant
API client AC), update implementation phases table and mermaid dependency graph.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove aspirational self-hosting section (docker-compose, config table,
image storage) — will be written when features are actually implemented
- Fix build commands: mvn → ./mvnw, npm test → npm run test:unit
- Remove nonexistent Dockerfile from project structure tree
- Remove Testcontainers from prerequisites (not yet a dependency)
- Add README documentation ACs to US-13 (MAX_ACTIVE_EVENTS) and US-16
(UNSPLASH_API_KEY + volume mount)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the hand-rolled HealthController and use spring-boot-starter-actuator
instead. Only the health endpoint is exposed, with no detail leakage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostToolUse hooks run after every file edit:
- Backend: ./mvnw compile (Checkstyle Google Style + javac)
- Frontend: vue-tsc --noEmit + oxlint + ESLint
Stop hook runs test suites when source files changed, blocks the
agent on failure and re-engages it to fix the issue. Output is
filtered to [ERROR] lines only for context efficiency.
Static analysis: Checkstyle (validate phase), SpotBugs (verify phase),
ArchUnit (9 hexagonal architecture rules as JUnit tests).
Fail-fast: Surefire skipAfterFailureCount=1, Vitest bail=1.
Test log noise suppressed via logback-test.xml (WARN level),
redirectTestOutputToFile, and trimStackTrace.
Existing Java sources reformatted to Google Style (2-space indent,
import order, Javadoc on public types).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: Spring Boot 3.5.11 on Java 25, Maven with wrapper, hexagonal
architecture package layout (domain/application/adapter/config), health
endpoint with integration test. Originally planned for Spring Boot 4.0
but pivoted due to massive package reorganization in 4.0 (see addenda
in research and plan docs).
Frontend: Vue 3 scaffolded via create-vue with TypeScript, Vue Router,
Vitest, ESLint, Prettier. Pivoted from Svelte due to ecosystem maturity
concerns (broken router ecosystem for Svelte 5).
Also: extended .gitignore for Java/Maven and Node/Vue artifacts, updated
CLAUDE.md with tech stack, build commands, agent documentation sections,
and document integrity rule.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>