| name | quest-pattern-frontend |
| description | Integrates journal quest sections into the Digivice frontend — SignalR reception through Pinia syncers, static JSON, presenters, and Journal UI. Use when the user explicitly asks to wire a new journal category (legendary weapons, DRI agents) or add a quest to an existing category on the frontend. |
| disable-model-invocation | true |
Quest Pattern — Frontend Integration
Wire journal quest data from SignalR reception through Journal UI.
Stops at rendered section + working modal. Does not touch backend C#.
User responsibility: backend already emits the new field/quest in
InitialState and JournalChanged. Do not invoke or verify
quest-pattern-backend — assume the user confirmed that separately.
No frontend tests (project rule).
Reuse rule (critical)
Quest entities are shared across all journal categories. Do not create
per-quest DTOs, models, syncers, or card components.
| Layer | Reuse as-is |
|---|
| DTOs | QuestDTO, StepDTO, RequisiteDTO |
| Models | Quest, Step, Requisite |
| Events converters | QuestConverter, StepConverter, RequisiteConverter (events/converters/) |
| Syncers | QuestSyncer, StepSyncer, RequisiteSyncer |
| Presenter converters | QuestConverter (presenters/converter/) |
| UI | JournalQuestCard, JournalQuestsSection, QuestModal tree |
Create new types/files only when adding a new category slot on Journal
(first Legendary Weapon section, first DRI Agent section, etc.) or when
registering new static quest JSON in an existing category.
Two workflows
| Workflow | When | Scope |
|---|
| A — New category slot | First item in legendaryWeapons, driAgents, etc. | Full pipeline (DTO → UI) |
| B — Quest in existing category | New quest id under side quests, legendary weapons, etc. | Static data + repository + i18n |
Use the decision helper at the end to pick A or B.
Category map
| Category | Journal property | Static JSON folder | Section accent | i18n section key |
|---|
| Main quest | mainQuest (single) | database/quest/main-quest.json | Yellow (hardcoded in Journal.vue) | journal.mainQuest |
| Side quests | sideQuests | database/quest/side-quest/ | cyan | journal.sideQuests |
| Legendary weapons | legendaryWeapons | database/quest/legendary-weapons/ | purple | journal.legendaryWeapons |
| DRI agents | driAgents | database/quest/dri-agents/ | rose | journal.driAgents |
Aside section order (fixed): Main → Side → Legendary → DRI.
All new collapsible sections use JournalQuestsSection with
defaultExpanded: false (starts closed, same as side quests today).
All new list sections use display-mode="side" and
calculateNewStatus: true (locked/done/new card variants).
Section invariant (mandatory)
A journal section only exists when it has at least one quest. An empty
section is invalid — do not wire a category slot, JournalQuestsSection, or
repository getter for a section with zero quests.
| Rule | Detail |
|---|
| Workflow A | Do not start until at least one quest id is ready (static JSON + backend in InitialState) |
| Workflow B | Category already wired; append quest to existing non-empty section |
| UI | No empty-state messaging — if the section renders, it always has cards |
If the user asks to add a section without a quest, stop and ask for the
first quest id before proceeding.
Accent color rule (mandatory)
Before implementing, if the user did not specify the section accent color,
ask which Tailwind color to use.
| Status | Color |
|---|
| Occupied — not selectable | yellow (main quest, hardcoded) |
| Occupied — not selectable | cyan (side quests) |
| Reserved | purple (legendary weapons) |
| Reserved | rose (DRI agents; replaces unused red in palette) |
Rules:
- Color must be a standard Tailwind palette name (e.g.
purple, rose,
emerald). If the user picks a name that is not a Tailwind color, ask them
to choose another.
- New accent must differ from cyan and yellow.
- Add the color to
journal-section-palette.ts by copying the cyan/red
token pattern — only the color name changes (text-{color}-400,
border-{color}-800, hover:bg-{color}-900/30, etc.).
- Extend
JournalSectionAccentColor with the new literal.
Definitions layout (static JSON)
Frontend/src/database/quest/
├── main-quest.json
├── side-quest/
├── legendary-weapons/
└── dri-agents/
Ids: always camelCase in JSON (muramasa, driAgentGuilmon). Must
match backend quest id.
i18n: i18n/locales/{en-US,pt-BR}/quest/{category}/{id}.json — register
imports in each locale index.ts. Section titles live in journal.json.
Quest titles/descriptions/steps use i18n. Digimon and digievolution proper
names stay literal in JSON — never pass through $t() (see AI/BUSINESS_RULES.md).
Workflow A — New category slot
Copy and track progress. Skip steps marked SKIP when the condition is met.
0. Preconditions
1. SignalR handlers (usually SKIP)
Files: events/signalr.handlers.ts, events/signalr.service.ts, main.ts
SKIP if handlers unchanged. Only verify JournalDTO will carry the new field.
2. DTO
File: events/dto/journal.dto.ts
3. Model
File: models/journal/journal.ts
4. Events converter
File: events/converters/journal.converter.ts
5. Syncer
File: stores/syncers/journal.syncer.ts
Sync limitation: syncers only patch quests already present from
InitialState. They do not add quests or bootstrap journal alone.
6. Pinia store (usually SKIP)
File: stores/use-game-store.ts
SKIP unless store actions need a new branch (rare).
7. Static quest JSON (per quest in category)
For each quest id:
8. Repository
File: repositories/quest.repository.ts
9. ViewModel + presenters
| File | Change |
|---|
viewmodels/quest/journal.viewmodel.ts | New collection field |
presenters/journal/journal.presenter.ts | Map repository → QuestModalPresenter.getQuestViewModel |
presenters/journal/quest-modal.presenter.ts | Resolve quest id from new section (after main/side checks) |
Presenter converter (presenters/converter/quest.converter.ts): SKIP — pass
{ calculateNewStatus: true } for list categories.
10. UI
File: components/journal/Journal.vue
File: components/journal/journal-section-palette.ts
File: i18n/locales/{en-US,pt-BR}/journal.json
11. Manual verification
12. Retrofeed
Update frontend-status.md: category wired, quest ids, accent color.
Workflow B — Quest in existing category
Minimal checklist when the category slot already exists on Journal.
0. Preconditions
1. Static quest JSON
2. Repository
File: repositories/quest.repository.ts
SKIP DTO, model, events converter, syncer, Journal.vue section shell,
journal.viewmodel.ts, palette — category already wired.
3. Presenters (conditional)
4. Manual verification
5. Retrofeed
Append quest id under the category in frontend-status.md.
Decision helper
New quest id only (category already on Journal)?
→ Workflow B
New property on Journal (first item in category)?
→ At least one quest id ready?
NO → Stop; ask for first quest (do not wire empty section)
YES → Workflow A
→ Accent color specified by user?
NO → Ask (Tailwind name; not cyan/yellow)
YES → Validate Tailwind + palette entry
→ Backend sends collection in InitialState?
(user confirms — do not run backend skill)
Debugging (mid-integration)
| Symptom | Likely cause |
|---|
| Section empty after connect | Misconfiguration: InitialState missing collection, repository array empty, or section wired without quests (invalid) |
| Card shows but modal empty | QuestModalPresenter missing branch or id mismatch |
| Live updates ignored | JournalChanged delta id not in store; or syncJournal no-op (journal null) |
| Wrong step state | Step number mismatch between JSON and backend |
| Missing translations | Locale index.ts import omitted |
Additional resources
- Pipeline diagram and file map: frontend-pipeline.md
- Integration status: frontend-status.md
- Business rules:
AI/BUSINESS_RULES.md (Journal §2.3)
- Code rules:
AI/CODE_RULES.md (Frontend sections)