# Fan Passport Content Authoring Guidelines These guidelines explain how to create and maintain content for **Fan Passport: The World Cup Journey**. They are intended for producers, editors, designers, and engineers adding teams, matches, stadiums, quizzes, predictions, sticker albums, memories, achievements, and challenges. ## Principles 1. **Make the fan feel present** - Every object should help fans remember what they watched, predicted, collected, learned, or felt. - Prefer concrete tournament language: “Check in to both semi-finals” is better than “Complete 2 events.” 2. **Design for daily return** - Include a mix of quick daily actions, streaks, live match hooks, and long-form collection goals. - Daily content should be achievable in under one minute unless clearly labeled as a bigger challenge. 3. **Use dynamic tournament logic** - The 2026 tournament evolves as teams qualify, groups are drawn, fixtures are finalized, and knockout paths emerge. - Use dynamic scopes such as `matches_for_team`, `qualified_teams`, `host_country_stadiums`, and `tournament_stadiums` when the target may change. 4. **Avoid spoilers** - Do not reveal outcomes in titles, descriptions, stickers, trivia explanations, or memory prompts before the relevant result is final. - Mark spoiler-sensitive content with a risk flag and an unlock condition. 5. **Keep content portable** - This foundation should later evolve into Premier League Passport, Champions League Passport, and a wider football fan rewards ecosystem. - Avoid encoding World Cup-only assumptions into generic concepts such as sticker packs, memories, achievements, and prediction scoring. ## Repository map Primary seed files: - `data/seeds/tournament.json` - `data/seeds/stadiums.json` - `data/seeds/teams.json` - `data/seeds/groups.json` - `data/seeds/matches.json` - `data/seeds/stickers.json` - `data/seeds/memories.json` - `data/seeds/quizzes.json` - `data/seeds/predictions.json` - `data/seeds/achievements.json` - `data/seeds/challenges.json` Supporting validation and documentation: - `src/schema.ts` - `src/validate.ts` - `schemas/challenge-catalog.schema.json` - `docs/validation-rules.md` - `docs/live-tournament-data-plan.md` - `docs/content-authoring-guidelines.md` ## ID conventions Use the existing convention of each seed file. For new content in this milestone: | Entity | Recommended format | Example | |---|---|---| | Challenge | `chal_` + snake case | `chal_prediction_giant_killing` | | Challenge set | `set_` + snake case | `set_stadium_collectors` | | Badge reward | `badge_` + snake case | `badge_all_stadiums_collected` | | Prediction template | `pred_template_` + snake case | `pred_template_exact_score` | | Sticker set | kebab-case ending in year | `team-crests-2026` | | Group | lowercase group letter slug | `group-a` | | Team | lowercase team slug | `england` | | Stadium | lowercase venue slug | `metlife-stadium` | Rules: - Do not rename published IDs. - Do not recycle deleted IDs. - Keep IDs stable across localization. - Use display fields for user-facing names; IDs are not copy. ## Authoring workflow 1. **Draft** - Write the content in the correct seed file. - Add source notes for facts, rankings, capacities, historical trivia, and award logic. - Use dynamic scopes for unknown or future tournament state. 2. **Self-review** - Confirm all required fields are present. - Check copy length for mobile display. - Check if the item has spoiler risk. - Confirm reward values match difficulty. 3. **Validation** - Parse JSON. - Run schema validation. - Run cross-reference validation. - Review warnings for placeholders or dynamic scopes. 4. **Editorial review** - Confirm tone, inclusivity, localizability, and accuracy. - Confirm that fan memory prompts are safe and privacy-aware. - Confirm that quiz explanations are clear and sourced. 5. **Live-data review** - If content depends on official results, rankings, standings, or awards, mark the correct `riskFlags`. - Confirm settlement logic can be replayed without duplicate rewards. 6. **Publish** - Bump content version where appropriate. - Record the change in release notes. - Deploy behind a feature flag if the content is phase-dependent. ## Copy style ### Voice Use a warm, energetic, football-native voice: - “Watch Every England Match” - “Predict a Giant Killing” - “Final Day Passport” - “Penalty Shootout Nerves” Avoid: - Corporate language: “Engage with event inventory” - Excessive slang that will age poorly - Insults or negative framing toward teams, countries, players, or fans - Claims that imply official endorsement unless licensing is in place ### Titles - Aim for 2-6 words. - Use title case for English titles. - Include the content hook: team, stadium, group, prediction, sticker, or memory. - Avoid dates in titles unless the date is the point of the content. ### Descriptions - One sentence is usually best. - Start with a verb when possible: “Collect,” “Check in,” “Predict,” “Save,” “Answer.” - Explain the objective, not the implementation. - Avoid hidden criteria in description copy. If the user must do it, say it. ### Examples Good: > Correctly predict an upset where a lower-ranked team beats a much higher-ranked opponent. Weak: > Make a special prediction and get it right. Good: > Collect every Group A team crest and check in to at least two Group A matches. Weak: > Finish Group A. ## Challenge authoring Challenge records live in `data/seeds/challenges.json`. ### Required design fields Every challenge needs: - Stable `id` - `setId` - User-facing `title` - User-facing `description` - `category` - `difficulty` - `repeatability` - Tournament `phase` - One or more technical `rules` - `rewards` - `contentRefs` - Search/filter `tags` - `riskFlags` ### Difficulty guidance | Difficulty | Use for | Typical reward | |---|---|---| | `starter` | First-session/tutorial actions | 100-150 XP | | `easy` | One simple action | 150-300 XP | | `medium` | Several actions or modest skill | 300-600 XP | | `hard` | Multi-day, multi-match, or difficult skill | 700-1000 XP | | `elite` | Completionist or rare outcome | 1200+ XP | ### Repeatability - `once`: Can be completed once for the tournament. - `daily`: Resets each day and should have daily timing. - `weekly`: Resets weekly or per content window. - `seasonal`: Can recur in later competitions using the same pattern. - `unlimited`: Use sparingly and only with anti-farming protection. ### Rule patterns #### Event count Use for simple events. ```json { "type": "event_count", "event": "quiz_answered", "target": { "count": 1 }, "distinctBy": "quizId" } ``` #### Dynamic collection Use when the target is not fixed until live data updates. ```json { "type": "dynamic_collection", "event": "match_check_in", "target": { "mode": "all_available", "entity": "matches_for_team" }, "scope": { "teamId": "england" }, "distinctBy": "matchId" } ``` #### Prediction outcome Use for settled predictions. ```json { "type": "prediction_outcome", "event": "prediction_settled", "predictionTemplateId": "pred_template_giant_killing", "target": { "count": 1, "outcome": "correct" }, "scope": { "minimumRankGap": 20, "winnerMustBeLowerRanked": true }, "distinctBy": "matchId" } ``` #### Composite challenge Use multiple rules when the player must do several things. All rules in the array are treated as required unless the rule explicitly declares an alternative group. ```json [ { "type": "event_count", "event": "match_check_in", "target": { "count": 2 }, "scope": { "stage": "semi_final" }, "distinctBy": "matchId" }, { "type": "quiz_score", "event": "quiz_answered", "target": { "minimumCorrect": 1 }, "scope": { "category": "semi_final", "mustBeCorrect": true }, "distinctBy": "quizQuestionId" } ] ``` ### Dynamic targets Use dynamic targets for: - Every match a team plays - Every qualified team - Every group member before draw finalization - Every stadium in the tournament - Every knockout match in a stage - Every sticker in a live-generated set - Award predictions that settle after the tournament Recommended dynamic target fields: - `target.mode`: usually `all_available` - `target.entity`: e.g. `matches_for_team`, `qualified_teams`, `tournament_stadiums` - `scope`: filters such as team, group, host country, stage, sticker set, category - `distinctBy`: the unique key used for progress ### Risk flags Use risk flags honestly. They are operational hints for QA and live-data jobs. | Flag | Meaning | |---|---| | `requires_live_result` | Needs official match/tournament result settlement | | `requires_official_feed` | Depends on official fixtures, standings, bracket, or stadium data | | `requires_manual_review` | Needs moderation, legal, editorial, or safety review | | `anti_spoiler` | Could reveal a result if shown too early | | `geo_sensitive` | Uses user location or venue presence | | `provider_dependent` | Relies on third-party odds, rankings, stats, or prediction provider behavior | ## Quiz authoring ### Good trivia questions - Are unambiguous. - Have one correct answer. - Include an explanation. - Are tagged by difficulty and category. - Can be localized without losing the answer. - Avoid spoilers unless gated. ### Bad trivia questions - “Who is the best player?” - “Which team shocked everyone yesterday?” before the user has seen yesterday’s result. - Questions with multiple correct answers. - Questions relying on disputed statistics without a source. ### Daily trivia cadence - Prepare at least 14 days of evergreen questions before the tournament. - Prepare matchday-specific questions in draft state. - Publish matchday-specific questions only after source data is final if they mention results. - Keep a reserve bank for postponed matches or emergency swaps. ## Prediction authoring Prediction templates must define: - What the fan predicts. - When the prediction locks. - How it settles. - What happens if the match is postponed, abandoned, or voided. - The score reward. - Any badge or challenge integration. Do not create prediction prompts that require privileged information or invite harmful behavior. Predictions are a game mechanic, not gambling. ## Sticker authoring Sticker albums should support both collection and memory: - Team crests teach the tournament field. - Stadium postcards encourage host-city exploration. - Matchday moments commemorate live events. - Final foils create late-tournament aspiration. Sticker rarity should be reviewed with the economy owner. Avoid creating rewards that allow users to farm premium packs indefinitely. ## Fan memory authoring Memory prompts should feel personal but safe. Good prompts: - “Where did you watch the opening match?” - “What was your reaction to the first goal you saw?” - “Save your final-day time capsule.” Avoid prompts that ask for: - Government IDs - Exact home addresses - Sensitive personal history - Private information about other people - Content that would require unsafe behavior at a stadium or watch party Always provide a text-only path when a memory prompt allows media upload. ## Achievement authoring Achievements are durable identity markers. Challenges can grant achievements, but achievements should not be treated as disposable campaign tasks. Achievement copy should answer: - What did the fan do? - Why is it memorable? - Is it visible to other users? - Does it remain meaningful after the tournament? ## Localization and accessibility - Keep sentence structures simple. - Avoid text embedded in images. - Do not rely only on color to communicate rarity, correctness, or completion. - Use alt text for sticker and badge art. - Consider screen-reader order for challenge progress. - Avoid abbreviations without first-use context, especially for stages and venues. ## Legal and licensing notes - Use official names only when the product has rights to do so. - Keep image and logo usage rights separate from data modeling. - Do not imply endorsement by FIFA, host cities, teams, or players unless covered by agreement. - Track asset licenses for badges, stickers, stadium images, and team marks. - For unlicensed prototypes, use placeholder visual assets while preserving content IDs. ## Pull request checklist - [ ] Content matches the correct seed file. - [ ] IDs follow conventions and are stable. - [ ] Copy is clear and localizable. - [ ] JSON parses. - [ ] Schema validation passes. - [ ] Cross-references resolve or are documented as dynamic. - [ ] Spoiler risk is handled. - [ ] Reward values match difficulty. - [ ] Live-data dependencies have risk flags. - [ ] Source notes exist for factual claims. - [ ] Accessibility and privacy needs are considered.