# Data Model: Link Preview (Open Graph Meta-Tags)

**Feature**: 012-link-preview | **Date**: 2026-03-09

## Overview

This feature does NOT introduce new database entities. It reads existing event data and projects it into HTML meta-tags. The "model" here is the meta-tag value object used during HTML generation.

## Meta-Tag Value Objects

### OpenGraphMeta

Represents the set of Open Graph meta-tags to inject into the HTML response.

| Field | Type | Source | Rules |
|---|---|---|---|
| `title` | String | Event title or "fete" | Max 70 chars, truncated with "..." |
| `description` | String | Composed from event fields or generic text | Max 200 chars |
| `url` | String | Canonical URL from request | Absolute URL |
| `type` | String | Always "website" | Constant |
| `siteName` | String | Always "fete" | Constant |
| `image` | String | Static brand image URL | Absolute URL to `/og-image.png` |

### TwitterCardMeta

| Field | Type | Source | Rules |
|---|---|---|---|
| `card` | String | Always "summary" | Constant |
| `title` | String | Same as OG title | Max 70 chars |
| `description` | String | Same as OG description | Max 200 chars |

## Data Flow

```
Request for /events/{token}
    │
    ▼
LinkPreviewController
    │
    ├── Resolve event token → Event domain object (existing EventRepository)
    │
    ├── Build OpenGraphMeta from Event fields:
    │     title     ← event.title (truncated)
    │     description ← formatDescription(event.dateTime, event.timezone, event.location, event.description)
    │     url       ← request base URL + /events/{token}
    │     image     ← request base URL + /og-image.png
    │
    ├── Build TwitterCardMeta (mirrors OG values)
    │
    ├── Inject meta-tags into cached index.html template
    │
    └── Return modified HTML

Request for / or /create (non-event pages)
    │
    ▼
LinkPreviewController
    │
    ├── Build generic OpenGraphMeta:
    │     title       ← "fete"
    │     description ← "Privacy-focused event planning. Create and share events without accounts."
    │     url         ← request URL
    │     image       ← request base URL + /og-image.png
    │
    ├── Build generic TwitterCardMeta
    │
    ├── Inject meta-tags into cached index.html template
    │
    └── Return modified HTML
```

## Existing Entities Used (Read-Only)

### Event (from `de.fete.domain.model.Event`)

| Field | Used For |
|---|---|
| `title` | `og:title`, `twitter:title` |
| `description` | Part of `og:description`, `twitter:description` |
| `dateTime` | Part of `og:description` (formatted) |
| `timezone` | Date formatting context |
| `location` | Part of `og:description` |
| `eventToken` | URL construction |
