Overview
Map notes let players store and share strategy notes for stage+mode combinations. Notes surface contextually in rotation views, tournament map lists, and SendouQ, and are browsable via a dedicated /notes page.
Core Concepts
Note
A note is authored by either a user or a team. Each note targets a specific stage+mode pair (both required for v1, schema allows nullable for future stage-only/mode-only/general notes).
A note contains:
- Optional custom title (fallback: auto-generated e.g. "{Author}'s {weapon} notes", "{Team name} notes")
- 1-4 weapon tags (shown in list views and used for filtering)
- 1-5 tabs
Tab
Each tab within a note represents a distinct aspect (e.g. "Hold", "Retake", "Opening"). A tab contains:
- Tab name
- One curated lucide icon (from a fixed set of ~10-15 relevant icons)
- Optional tldraw drawing (one per tab)
- Optional text body (plain text for free users, markdown for supporters)
- At least one of drawing or text is required per tab
Authorship & Permissions
| Note type |
Who can create |
Who can edit |
Who sees it |
| Personal (private) |
Any logged-in user |
Author only |
Author only |
| Personal (public) |
Users with permission (account age gated, same as calendar events) |
Author only |
Everyone (incl. anonymous) |
| Team |
Team managers & coaches |
Team managers & coaches |
All team members |
| Team (public) |
Team managers & coaches |
Team managers & coaches |
Everyone (incl. anonymous) |
Supporter-only features
- Markdown in note text (free users get plain text)
- Multiple notes per stage+mode (free users limited to one)
Following teams' notes
Users can follow other teams to see their public notes alongside their own. Notes you see for any stage+mode:
- All notes you authored
- All notes of teams you are a member of
- All public notes from teams you follow
When a user has no notes for a stage+mode, the fallback is showing popular public notes sorted by follower count descending.
Pages & Routes
All code lives in app/features/notes/.
| Route |
Purpose |
/notes |
Browse/search/filter all notes (your own, team, followed, public) |
/notes/new |
Create a new note |
/notes/:noteId |
View a note; edit if you have permission |
/notes page
List view showing note metadata:
- Title (custom or auto-generated)
- Author (user or team name + avatar)
- Weapon tag icons
- Follower count (public notes)
- Last updated
No drawing previews in the list (too heavy to render tldraw thumbnails).
Filters:
- Stage
- Mode
- Weapon
- Author type (my notes / team notes / followed / public)
/notes/new
Create form. Also reachable from /plans (new button to save a plan as a note).
/notes/:noteId
Full note view with:
- Title, author info, stage+mode
- Follow button with count (for team public notes)
- Tabbed content area (tab name + lucide icon per tab)
- tldraw drawing (view or edit mode)
- Text content below drawing
- Edit button (if user has permission)
Entry Points
Rotation view (front page)
One note icon overlays each rotation pair (two maps). Clicking navigates to /notes?stage=X&stage=Y&mode=Z showing notes for both maps.
If user has notes for those maps: show the note icon.
If user has no notes: still show icon, fallback to popular public notes.
Tournament map list
Note icon appears for resolved maps (after picks/bans complete), linking to /notes?stage=X&mode=Y.
SendouQ
Note icon on the current match map, linking to the relevant notes page.
Data Model
Tables
MapNote {
id: number (PK)
authorType: "USER" | "TEAM"
authorId: number (userId or teamId)
stageId: number | null (nullable for future flexibility)
mode: ModeShort | null (nullable for future flexibility)
title: string | null
isPublic: boolean (default false)
weapons: JSONColumnType<number[]> (1-4 weapon IDs)
createdAt: Generated<number>
updatedAt: number
}
MapNoteTab {
id: number (PK)
noteId: number (FK -> MapNote)
sortOrder: number
name: string
icon: string (lucide icon identifier from curated set)
drawing: JSONColumnTypeNullable<TldrawData>
text: string | null
}
MapNoteFollow {
userId: number (FK -> User)
teamId: number (FK -> Team)
createdAt: Generated<number>
PK: (userId, teamId)
}
Indexes
MapNote(authorType, authorId) — fetch all notes by author
MapNote(stageId, mode) — fetch notes for a stage+mode
MapNote(isPublic) — public notes browsing
MapNoteFollow(userId) — teams a user follows
MapNoteFollow(teamId) — follower count
Open Questions
-
tldraw storage optimization: Weapon images may be stored as blobs in tldraw JSON. Investigate saving weapon references (IDs) instead and injecting actual images at render time. Measure actual payload sizes and adjust note/tab limits accordingly.
-
Version history for team notes: Multiple managers/coaches can edit team notes. Consider adding version history (possibly supporter-only to manage data volume). For v1, last-write-wins with "last edited by X" metadata may suffice.
Files to Create
| File |
Purpose |
app/features/notes/routes/notes.tsx |
Browse/search page |
app/features/notes/routes/notes.new.tsx |
Create note page |
app/features/notes/routes/notes.$noteId.tsx |
View/edit note page |
app/features/notes/NotesRepository.server.ts |
Database queries |
app/features/notes/notes-constants.ts |
Tab limit, curated icons, weapon tag limit |
app/features/notes/notes-types.ts |
TypeScript types |
app/features/notes/components/ |
UI components |
app/features/notes/loaders/ |
Route loaders |
app/features/notes/actions/ |
Route actions |
| New migration |
MapNote, MapNoteTab, MapNoteFollow tables |
app/db/tables.ts |
Add new table types |
app/routes.ts |
Register new routes |
Files to Modify
| File |
Change |
| Rotation view component |
Add note icon overlay on rotation pairs |
| Tournament match map display |
Add note icon for resolved maps |
| SendouQ match view |
Add note icon for current map |
/plans page |
Add "Save as note" button |
Overview
Map notes let players store and share strategy notes for stage+mode combinations. Notes surface contextually in rotation views, tournament map lists, and SendouQ, and are browsable via a dedicated
/notespage.Core Concepts
Note
A note is authored by either a user or a team. Each note targets a specific stage+mode pair (both required for v1, schema allows nullable for future stage-only/mode-only/general notes).
A note contains:
Tab
Each tab within a note represents a distinct aspect (e.g. "Hold", "Retake", "Opening"). A tab contains:
Authorship & Permissions
Supporter-only features
Following teams' notes
Users can follow other teams to see their public notes alongside their own. Notes you see for any stage+mode:
When a user has no notes for a stage+mode, the fallback is showing popular public notes sorted by follower count descending.
Pages & Routes
All code lives in
app/features/notes/./notes/notes/new/notes/:noteId/notespageList view showing note metadata:
No drawing previews in the list (too heavy to render tldraw thumbnails).
Filters:
/notes/newCreate form. Also reachable from
/plans(new button to save a plan as a note)./notes/:noteIdFull note view with:
Entry Points
Rotation view (front page)
One note icon overlays each rotation pair (two maps). Clicking navigates to
/notes?stage=X&stage=Y&mode=Zshowing notes for both maps.If user has notes for those maps: show the note icon.
If user has no notes: still show icon, fallback to popular public notes.
Tournament map list
Note icon appears for resolved maps (after picks/bans complete), linking to
/notes?stage=X&mode=Y.SendouQ
Note icon on the current match map, linking to the relevant notes page.
Data Model
Tables
Indexes
MapNote(authorType, authorId)— fetch all notes by authorMapNote(stageId, mode)— fetch notes for a stage+modeMapNote(isPublic)— public notes browsingMapNoteFollow(userId)— teams a user followsMapNoteFollow(teamId)— follower countOpen Questions
tldraw storage optimization: Weapon images may be stored as blobs in tldraw JSON. Investigate saving weapon references (IDs) instead and injecting actual images at render time. Measure actual payload sizes and adjust note/tab limits accordingly.
Version history for team notes: Multiple managers/coaches can edit team notes. Consider adding version history (possibly supporter-only to manage data volume). For v1, last-write-wins with "last edited by X" metadata may suffice.
Files to Create
app/features/notes/routes/notes.tsxapp/features/notes/routes/notes.new.tsxapp/features/notes/routes/notes.$noteId.tsxapp/features/notes/NotesRepository.server.tsapp/features/notes/notes-constants.tsapp/features/notes/notes-types.tsapp/features/notes/components/app/features/notes/loaders/app/features/notes/actions/MapNote,MapNoteTab,MapNoteFollowtablesapp/db/tables.tsapp/routes.tsFiles to Modify
/planspage