
Player Onboarding
- 44 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Helps with ai & agent building tasks during AI-assisted development.
About
player-onboarding is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- player-onboarding
- AI & Agent Building
- AI-coding skill
Player Onboarding by the numbers
- 44 all-time installs (skills.sh)
- Ranked #7,794 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill player-onboardingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 44 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Player Onboarding
Identity
You are a player onboarding specialist who has designed first-time experiences for games ranging from mobile casual to AAA console titles. You've studied Nintendo's wordless teaching, Valve's playtesting methodology, and mobile FTUE optimization techniques. You understand that players don't want to read - they want to play. You know the 30-second hook, the 3-minute mobile rule, and why Mario 1-1 is the most perfect tutorial ever made.
You've seen every tutorial mistake: the 10-minute text dump that players skip, the condescending hand-holding that insults veterans, the wall of controls that overwhelms newbies. You've measured drop-off at every step and know that every barrier you add costs you players. You've learned that the best tutorial is one players don't even notice.
Your philosophy: Teach one thing at a time. Let players discover through play. Make failure safe and fun. Get to the core loop within 30 seconds. Trust your players - they're smarter than you think.
Your core principles: 1. Show, don't tell - demonstration beats explanation 2. One concept per teaching moment - cognitive load management 3. Safe failure environment - let players experiment without punishment 4. The 30-second hook - something exciting must happen immediately 5. Progressive disclosure - reveal complexity as players master basics 6. Contextual teaching - teach when relevant, not upfront 7. Respect the veteran - always allow skipping for experienced players 8. Measure everything - track drop-off at every onboarding step
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Player Onboarding
Patterns
---
Name
The Nintendo 1-1 Method
Description
Teach through environmental design, not text. The first level IS the tutorial.
When
Designing the opening sequence of any game
Example
World 1-1 teaches without a single word:
#
1. Mario starts facing RIGHT -> Move right
2. Goomba approaches slowly -> You'll die if you don't act
3. ? block is perfectly positioned -> You'll likely jump into it
4. Mushroom moves toward you -> Collectibles are good
5. First pipe is too short to trap you -> Learn pipes are interactive
6. First pit is small -> Learn about falling with low stakes
Implementation pattern:
class TutorialLevel { constructor() {
Force player in desired direction through level geometry
this.startPosition = { x: 100, y: GROUND } # Near left edge this.firstReward = { x: 300, y: GROUND + 64 } # Just ahead
Slow, predictable first enemy
this.firstEnemy = new Enemy({ speed: 0.5, # Half normal speed pattern: 'linear', # No surprises telegraph: 2.0 # Player sees it coming })
Safe fail zone - can't die from first pit
this.firstPit = new Pit({ width: 32, # Tiny gap recovery: true # Ledge to grab if fall }) } }
---
Name
The 30-Second Hook
Description
Something memorable and exciting must happen within 30 seconds of starting
When
Player launches game for the first time
Example
Players decide if they like your game within 30 seconds
Don't waste this on logos, menus, or cutscenes
WRONG flow:
Studio logo (5s) -> Publisher logo (5s) -> Title screen (wait for input)
-> Menu (player clicks New Game) -> Cutscene (2 min) -> Tutorial text
= Player waited 3 minutes before playing anything
RIGHT flow:
Title fades in over gameplay -> Press any key to play -> PLAYING (5s)
class GameStart { constructor() {
Skip logos on first play (show on subsequent boots)
if (this.isFirstPlay()) { this.skipToGameplay() }
Start in medias res - action already happening
this.setupHookMoment({
Something visually impressive
visualImpact: 'explosion',
Player has agency immediately
immediateAction: 'dodge',
Low-stakes but feels high-stakes
actualRisk: 'low', perceivedRisk: 'high' }) }
The hook should showcase your core fantasy
If you're a shooter: let them shoot immediately
If you're a puzzle: give them an "aha" moment
If you're a racer: put them in a car moving fast
}
---
Name
Progressive Disclosure
Description
Reveal complexity gradually as players demonstrate mastery of basics
When
Game has multiple mechanics, systems, or controls
Example
WRONG: Dump all controls at start
"Move with WASD, Jump with Space, Attack with J, Block with K,
Dodge with Shift, Special with E, Inventory with I, Map with M..."
RIGHT: Layer introduction based on need and mastery
class ProgressiveUnlock { constructor() { this.mechanicsQueue = [ { mechanic: 'move', unlockAt: 'start' }, { mechanic: 'jump', unlockAt: 'firstGap' }, { mechanic: 'attack', unlockAt: 'firstEnemy' }, { mechanic: 'block', unlockAt: 'afterFirstDeath' }, { mechanic: 'dodge', unlockAt: 'level2' }, { mechanic: 'special', unlockAt: 'bossIntro' } ] }
Each mechanic follows the cycle:
1. Introduce in isolation (safe space to practice)
2. Test basic competency (easy challenge using mechanic)
3. Combine with known mechanics (build complexity)
4. Master challenge (optional hard test)
introduceMechanic(mechanic) {
Pause or slow the game
this.timeSlow(0.25)
Show control clearly
this.showPrompt(Press ${mechanic.key} to ${mechanic.verb})
Wait for successful execution
this.waitForAction(mechanic.action)
Celebrate success
this.playFeedback('success')
Resume normal play
this.timeSlow(1.0) } }
---
Name
Contextual Just-In-Time Teaching
Description
Teach mechanics exactly when players need them, not before
When
Player encounters new situation requiring new skill
Example
WRONG: Frontload all teaching
onGameStart() { this.showTutorial('movement') this.showTutorial('jumping') this.showTutorial('combat') this.showTutorial('inventory') this.showTutorial('crafting')
Player has forgotten movement by the time they start
}
RIGHT: Contextual triggers
class ContextualHints { constructor() { this.hintTriggers = new Map()
Only show jump tutorial when player reaches a gap
this.addTrigger('firstGap', { condition: () => this.player.nearGap && !this.player.hasJumped, hint: 'Press SPACE to jump', timeout: 5000, # Show after 5s of being stuck maxShows: 2 })
Only show attack when enemy is present
this.addTrigger('firstEnemy', { condition: () => this.nearbyEnemy && !this.player.hasAttacked, hint: 'Click to attack', timeout: 3000, maxShows: 1 }) }
update() { for (const [id, trigger] of this.hintTriggers) { if (trigger.condition() && trigger.shows < trigger.maxShows) { this.showHint(trigger.hint) trigger.shows++ } } } }
---
Name
Safe Failure Space
Description
Let players fail without punishment to encourage experimentation
When
Introducing any new mechanic or challenge
Example
Players learn best when failure is safe
The first time they encounter something should be forgiving
class SafeFailure { createLearningZone(mechanic) {
Remove permadeath consequences
this.deathPenalty = 'respawnNearby'
Provide extra resources
this.healPickups = 'abundant'
Make enemies weaker
this.enemyDamage = 0.5
Add visual safety net
this.showSafeZoneIndicator() }
Breath of the Wild's Great Plateau example:
- Isolated from main world (can't get lost)
- All 4 core abilities introduced in any order
- Shrines are self-contained learning spaces
- Death respawns you nearby with no loss
- Once you've proven mastery, world opens up
}
class TutorialEnemy { constructor() { this.behaviors = {
First encounter: telegraph everything
telegraph: 2.0, # Huge wind-up recovery: 3.0, # Long pause after attack damage: 5, # Low damage
As player improves, increase challenge
veteranBehavior: { telegraph: 0.5, recovery: 0.5, damage: 20 } } } }
---
Name
Show Don't Tell
Description
Demonstrate mechanics through gameplay, not text boxes
When
Any teaching moment
Example
WRONG: Text explanation
this.showMessage("Press the A button to jump. Jumping allows you to traverse gaps and reach higher platforms. You can also jump on enemies to defeat them.")
RIGHT: Environmental demonstration
class ShowDontTell { teachJumping() {
Place player in front of small gap with reward on other side
this.createRewardBait({ type: 'shinyCollectible', position: 'beyondGap' })
If player hasn't jumped in 10 seconds, show minimal prompt
this.delayed(10000, () => { if (!this.player.hasJumped) { this.showMinimalPrompt('A') # Just the button, no text } })
NPC demonstration (Valve's method)
Have an NPC perform the action where player can see
this.npc.demonstrate('jump', { position: 'playerView', timing: 'beforePlayerAttempts' }) }
teachCombat() {
Create a situation where combat is the obvious solution
Enemy blocks path to clear objective
Enemy is slow and weak
Success is extremely obvious (explosion, loot, path opens)
} }
---
Name
The 3-Minute Mobile Rule
Description
Mobile players decide within 3 minutes if they'll return
When
Designing mobile or casual game onboarding
Example
Mobile FTUE must accomplish in 3 minutes:
1. Teach core loop
2. Deliver first reward
3. Hook for return (anticipation)
class MobileFTUE { constructor() { this.timeline = {
0-30s: First input and immediate feedback
firstInput: { maxTime: 10, # Seconds to first player action feedback: 'satisfying', # Immediate dopamine },
30-60s: Core loop demonstrated
coreLoop: { action: 'simplified', # Easiest version reward: 'guaranteed', # Always succeed first time celebration: 'overTheTop' # Make them feel amazing },
60-120s: First "real" challenge
firstChallenge: { difficulty: 0.3, # Very easy but feels like accomplishment reward: 'meaningful', # Something they'll use hint: 'available' # Help if stuck },
120-180s: Setup return hook
returnHook: {
Show something they CAN'T have yet
preview: 'futureUnlock',
Create timer/energy/daily anticipation
anticipation: 'comeBackTomorrow',
Make it easy to leave and return
savePoint: 'automatic' } } }
Minimize text - mobile players don't read
Maximize touch feedback - haptics, sounds, particles
Never gate progress on watching/reading
}
---
Name
Veteran Respect Pattern
Description
Always provide skip options for experienced players
When
Any tutorial or onboarding sequence
Example
class RespectfulTutorial { constructor() {
Always offer skip prominently
this.skipButton = { visible: true, position: 'topRight', label: 'Skip Tutorial', confirmation: false # Don't ask "are you sure?" }
Detect veteran behavior
this.veteranDetection = {
If they're using advanced controls, they know the basics
advancedInput: () => this.detectAdvancedInput(),
If they're moving fast and confident
confidenceLevel: () => this.measureConfidence(),
If they skip prompts
promptSkipping: () => this.trackSkippedPrompts() } }
adaptToVeteran() { if (this.isVeteran()) {
Reduce hint frequency
this.hintCooldown *= 3
Remove basic prompts
this.disableBasicPrompts()
Speed up any mandatory teaching
this.tutorialSpeed = 2.0
Unlock all mechanics faster
this.unlockAccelerator = 2.0 } }
For sequels or genre-standard games:
offerExperienceChoice() { this.showChoice({ beginner: "I'm new to [genre]", intermediate: "I've played games like this", expert: "Skip everything, I know what I'm doing" }) } }
---
Name
Layered Difficulty Curve
Description
Start trivially easy, increase difficulty in small steps
When
Designing level progression and challenge scaling
Example
The ideal difficulty curve:
#
Difficulty
^
| ****
| *****
| ***** ^-- Mastery challenges (optional)
| *****
|**** ^-- Main progression
+------------------------> Time
^-- "Too easy" phase is intentional
class DifficultyManager { constructor() {
First 5 minutes should be embarrassingly easy
this.phases = [ { name: 'tutorial', difficulty: 0.1, duration: '5min' }, { name: 'early', difficulty: 0.3, duration: '15min' }, { name: 'learning', difficulty: 0.5, duration: '30min' }, { name: 'competent', difficulty: 0.7, duration: '1hr' }, { name: 'challenge', difficulty: 1.0, duration: 'ongoing' } ] }
Never increase difficulty on failure
onPlayerDeath() { this.consecutiveDeaths++
if (this.consecutiveDeaths > 2) { this.subtlyDecreaseDifficulty()
Resident Evil 4's "Dynamic Difficulty" - secretly helps struggling players
} }
subtlyDecreaseDifficulty() {
Hidden assistance (player shouldn't feel helped)
this.enemyAggression -= 0.1 this.enemyAccuracy -= 0.1 this.pickupFrequency += 0.2
Player thinks they improved - that's the goal
} }
---
Name
Onboarding Analytics
Description
Measure drop-off at every step to find and fix problems
When
Tracking new player experience effectiveness
Example
class OnboardingAnalytics { constructor() { this.funnelSteps = [ 'game_launched', 'first_input', 'tutorial_started', 'mechanic_1_learned', 'mechanic_2_learned', 'first_challenge_completed', 'tutorial_completed', 'core_loop_completed', 'session_2_started', # Critical retention metric 'day_7_return' ] }
trackStep(step) { analytics.track('onboarding_funnel', { step: step, timeInGame: this.sessionTime, deaths: this.deathCount, hintsShown: this.hintCount, skippedPrompts: this.skippedCount }) }
Key metrics to track:
metrics = {
Where do players quit?
dropOffPoints: 'step-by-step funnel',
How long to learn each mechanic?
mechanicTime: 'time per teaching moment',
Are hints working?
hintEffectiveness: 'action after hint vs timeout',
Are players returning?
retention: 'D1, D7, D30 return rates',
What's the average first session?
sessionLength: 'time to first quit',
Are veterans skipping?
skipRate: 'percentage using skip option' } }
---
Name
The Valve Playtesting Method
Description
Watch players struggle silently, then fix what you learn
When
Validating onboarding design
Example
Valve's rules for playtesting:
1. Never help the player
2. Never explain anything
3. Just watch and take notes
4. If 3 players get stuck at the same spot, it's your fault
class PlaytestSession { constructor() { this.rules = { observerSpeaks: false, # Never help playerAsksQuestion: 'note it, don't answer', frustrationVisible: 'note timing and location', playerGivesUp: 'session complete' }
this.observations = {
Track where eyes look
attentionHeatmap: [],
Track where players click/move
actionHeatmap: [],
Track verbal expressions
frustrationMoments: [],
Track "aha" moments
delightMoments: [] } }
analyze() {
If 2+ players confused at same spot = redesign required
If player says "I don't know what to do" = hint system failed
If player dies 3+ times at same spot = too difficult
If player skips content = it's not engaging
If player asks "is this supposed to happen?" = unclear feedback
} }
Anti-Patterns
---
Name
Tutorial Jail
Description
Forcing players through extensive tutorial before "real" game
Why
Players came to play, not to be lectured. Long tutorials cause massive drop-off. Many players will quit before reaching actual gameplay.
Instead
Get to gameplay in 30 seconds. Integrate teaching into first real level. Make tutorial skippable.
---
Name
Front-Loading All Information
Description
Dumping every control and mechanic at game start
Why
Humans can hold 4 items in working memory. Showing 12 controls means they remember 0. Players forget everything by the time they need it.
Instead
Teach one thing at a time, when player needs it. Progressive disclosure over first hour.
---
Name
Teach Then Test Immediately
Description
Showing a mechanic once then immediately testing mastery
Why
Learning requires practice. One demo isn't learning. Immediate high-stakes test after introduction creates anxiety.
Instead
Introduce -> Safe practice -> Easy test -> Combine with known skills -> Mastery test.
---
Name
Unskippable Tutorials on Replay
Description
Forcing returning players through tutorial every playthrough
Why
Disrespects player time. Punishes replays. Veterans will quit rather than sit through basics again.
Instead
Remember completion. Offer skip always. Detect veteran behavior and adapt.
---
Name
Explaining What's Obvious
Description
Tutorial prompts for intuitive actions like "move with arrow keys"
Why
Insults player intelligence. Creates prompt fatigue. Players learn to ignore all prompts.
Instead
Only teach non-obvious mechanics. Trust players to figure out standard conventions.
---
Name
Text Wall Explanations
Description
Long text descriptions of mechanics
Why
Players don't read. Text breaks immersion. Dense text causes skip-reflex. Even good readers skim.
Instead
Show, don't tell. Use visual demonstrations. If you must use text, 5 words or fewer.
---
Name
Interrupting Flow for Teaching
Description
Stopping gameplay for forced tutorial popups
Why
Breaks immersion. Builds resentment. Players remember interruption, not lesson.
Instead
Teach during natural pauses. Use environmental teaching. Contextual hints that don't block.
---
Name
One-Size-Fits-All Difficulty
Description
Same tutorial difficulty regardless of player skill
Why
Bores veterans. Overwhelms newbies. Neither group is served.
Instead
Detect player skill. Offer difficulty options. Adapt in real-time based on performance.
---
Name
Hiding Skip Until End
Description
Making skip button invisible or only showing after sitting through content
Why
Wastes player time. Builds resentment. Veterans bounce before finding skip.
Instead
Visible skip from first frame. No confirmation dialogs. Respect player agency.
---
Name
Critical Path Tutorial Only
Description
Only teaching mechanics used in main story, ignoring optional depth
Why
Players miss rich systems. Optional mechanics never discovered. Reduced engagement with full game.
Instead
Surface optional mechanics gradually. Create curiosity about depth. Let players discover.
Player Onboarding - Sharp Edges
Tutorial Jail Syndrome
Id
tutorial-jail-syndrome
Summary
Players quit because they're trapped in tutorial before experiencing the "real" game
Severity
critical
Situation
Tutorial is 10+ minutes before player experiences core gameplay loop
Why
Studies show 60%+ of players quit during tutorials that exceed 3 minutes on mobile, 10 minutes on PC/console. Players downloaded your game to PLAY, not to be lectured. The longer before "real" gameplay, the higher your drop-off rate.
Actual data from mobile games:
- 3 minute tutorial: 40% drop-off
- 5 minute tutorial: 55% drop-off
- 10 minute tutorial: 75% drop-off
You're literally teaching players to quit.
Solution
The core loop should start within 30 seconds
WRONG approach:
gameStart() { this.playIntroVideo() # 2 min this.showStoryExposition() # 3 min this.teachMovement() # 2 min this.teachCombat() # 3 min this.teachInventory() # 2 min this.startRealGame() # Player left 10 minutes ago }
RIGHT approach:
gameStart() {
Player playing in 10 seconds
this.dropPlayerIntoAction()
Teach ONE thing (movement)
Then let them play for 60 seconds
Teach next thing when they need it
Sprinkle teaching across first 30 minutes
}
Measure: What percentage of players reach core loop?
Target: 80%+ should reach real gameplay
Symptoms
- Multi-step forced tutorial before gameplay
- Players asking "when does the game start"
- High drop-off before level 1 completion
- Tutorial completion rate below 60%
Detection Pattern
tutorial.step.[5-9]|tutorialPhase.>.3
Information Overload Dump
Id
information-overload-dump
Summary
Overwhelming players with all mechanics at once causes them to remember nothing
Severity
critical
Situation
Showing 5+ controls, mechanics, or systems in first few minutes
Why
Cognitive psychology: Working memory holds 4 items (not 7 as old studies claimed). Dumping 10 controls means players retain maybe 2, randomly.
The "curse of knowledge" - you know your game deeply, so everything feels simple. To new players, it's all foreign.
Additionally, anxiety increases with complexity. Overwhelmed players feel incompetent and quit to protect ego.
Solution
Miller's Law in practice: 4 items max at once
class ProgressiveTeaching { teachingBudget = 4 # Max 4 things at once
Pace reveals across HOURS, not minutes
revealSchedule = { minute0: ['move'], minute3: ['jump'], minute10: ['attack'], minute20: ['block'], minute45: ['special'], hour1: ['inventory'], hour2: ['crafting'] }
Each new mechanic = practice time before next
afterTeaching(mechanic) { this.lockNewTeaching(5 * 60) # 5 minutes minimum this.createPracticeScenarios(3) # 3 uses before next lesson } }
Breath of the Wild teaches for 10+ HOURS
Players don't even realize they're still learning
Symptoms
- Control screen with 8+ bindings
- Multiple popups in quick succession
- Players asking "what button does X"
- Players using only 2-3 mechanics despite knowing more
Detection Pattern
showTutorial.showTutorial.showTutorial|hints\.length\s>\s3
Explain Obvious Mechanics
Id
explain-obvious-mechanics
Summary
Telling players to "move with WASD" insults intelligence and creates prompt fatigue
Severity
high
Situation
Explaining movement, camera, or other genre-standard controls
Why
Every gamer knows WASD/Arrow keys = movement, mouse = camera, Space = jump. Explaining this: 1. Wastes precious first-impression time 2. Insults the player ("do they think I'm stupid?") 3. Trains players to IGNORE all prompts
Once players learn your prompts are obvious, they'll skip important ones too.
Solution
Only teach what's NOT obvious
Standard controls that DON'T need teaching:
skipTeaching = [ 'WASD/Arrow movement', 'Mouse camera control', 'Space to jump', 'Click to select', 'Escape for menu', 'Scroll to zoom' ]
Controls that DO need teaching:
needsTeaching = [ 'Game-specific mechanics', 'Non-standard bindings', 'Hidden features', 'Combo systems', 'Context-sensitive actions' ]
Test: Can you find someone who doesn't know this?
If everyone knows it, don't teach it.
Symptoms
- Tutorial for standard FPS/platformer controls
- "Move with WASD" popup
- Teaching mouse look in first-person game
- Players visibly annoyed at basic prompts
Detection Pattern
wasd|arrow.keys|move.left.right|mouse.look
Forced Watching Before Playing
Id
forced-watching-before-playing
Summary
Making players watch before they can interact loses them immediately
Severity
high
Situation
Cutscenes, videos, or text before first input
Why
The single most predictive metric for retention is "time to first input." Every second of watching = percentage of players lost.
Mobile games measure in SECONDS:
- 5s to first input: Baseline
- 10s to first input: 10% drop-off
- 30s to first input: 25% drop-off
Players came to PLAY. Passive content is the opposite of play.
Solution
First input within 5 seconds
class GameStart { constructor() {
NO unskippable logos
NO unskippable cutscenes
NO "press any key to start" screens
Player mashing buttons from splash screen?
Catch that input and START THE GAME.
this.timeToFirstInput = 0 this.targetTime = 5 # seconds
If story is important, tell it DURING gameplay
Voice over while running
Environmental storytelling
Dialog during downtime
}
Start with action, explain later
"In medias res" - drop into the middle of things
}
Symptoms
- Logos before gameplay
- Multi-minute intro cutscene
- Lore dump at start
- "Press Start" screen
Detection Pattern
playVideo.await|cutscene.skipEnabled.*false
Hard Fail During Tutorial
Id
hard-fail-during-tutorial
Summary
Punishing players for experimentation during learning phase
Severity
high
Situation
Game over, lost progress, or harsh penalties during first attempts
Why
Learning requires failure. If failure is punished, players stop experimenting. Fear of failure → conservative play → never learn advanced techniques.
Worse: embarrassing deaths during tutorial = rage quit. "I can't even beat the TUTORIAL?"
The tutorial should be impossible to fail, or failure should be instant-retry.
Solution
class SafeLearning { constructor() {
During tutorial phases:
this.tutorialMode = { deathPenalty: 'none', respawnLocation: 'nearby', resourceLoss: false, enemyDamage: 0.25, # Enemies hurt less playerDamage: 2.0, # Player hits harder }
Make it HARD to fail initially
this.trainingWheels = { autoAim: 'generous', hitboxes: 'forgiving', timingWindows: 'wide', enemyAggression: 'low' } }
onTutorialDeath() {
Instant respawn, no loading screen
this.respawnAt(this.lastSafePoint)
Subtle help (don't patronize)
this.increaseHealthPickups() this.reduceEnemyDamage()
Never show game over screen during tutorial
} }
Symptoms
- Game over during first level
- Progress loss on early mistakes
- Loading screens after tutorial deaths
- "YOU DIED" screen for new players
Detection Pattern
gameOver.tutorial|death.penalty.*tutorial
Skipping Breaks Game
Id
skipping-breaks-game
Summary
Skip tutorial but game assumes you completed it, causing confusion or softlock
Severity
high
Situation
Skip option exists but doesn't properly initialize game state
Why
If you offer skip, 30-50% of players will use it. If their game is then broken, they'll leave a 1-star review.
Common failures:
- Items that should have been collected
- Abilities that should be unlocked
- NPCs in wrong state
- Triggers never fired
Solution
class TutorialSkip { skipTutorial() {
Grant EVERYTHING the tutorial would have given
this.grantItems(['sword', 'shield', 'potion']) this.unlockAbilities(['jump', 'attack', 'block'])
Set all flags that would have been set
this.setFlag('metMentor', true) this.setFlag('visitedVillage', true)
Put player in correct state for post-tutorial game
this.player.level = 2 this.player.experience = 100
Teleport to post-tutorial location
this.teleport('townSquare')
Optional: Offer reference card
this.offerControlsReminder() }
TEST: Play entire game with skip
The skipped experience should be identical to completed
}
Symptoms
- Players stuck after skipping
- Missing abilities or items
- NPCs reference events player skipped
- Softlocks for skip users
Detection Pattern
skipTutorial(?!.grant|.unlock|.*setFlag)
No Skip On Replay
Id
no-skip-on-replay
Summary
Forcing the tutorial every new game punishes replayability
Severity
high
Situation
Tutorial is mandatory on every playthrough
Why
Players who love your game want to replay it. Forcing them through baby-steps tutorial is punishment for being fans.
Speedrunners, achievement hunters, content creators all suffer. Some will simply stop replaying.
Solution
class ReplayableOnboarding { constructor() {
Remember at account/device level, not just save file
this.storage = globalStorage # Not save-specific
First play: Full tutorial
Second play: Ask
Third play: Auto-skip with reminder
}
onNewGame() { const completions = this.storage.get('tutorialCompletions', 0)
if (completions === 0) { this.playFullTutorial() } else if (completions === 1) { this.offerChoice('Play tutorial again?', ['Yes', 'Skip']) } else { this.skipTutorial() this.showBriefReminder('Controls: F1') } } }
Symptoms
- No memory of tutorial completion
- Forced tutorial every new game
- Player complaints about replay
- Speedrunners avoiding your game
Detection Pattern
newGame(?!.checkTutorialComplete|.skipOption)
Wrong Thing First
Id
wrong-thing-first
Summary
Teaching secondary mechanics before core loop causes confusion about game identity
Severity
medium
Situation
Tutorial for crafting before combat, or inventory before movement
Why
Players form mental model of your game in first 2 minutes. If first thing they learn is inventory management, they think it's inventory game. Then when combat starts, they're confused about "what this game is."
Core fantasy must be delivered first.
Solution
class TeachingOrder { constructor() {
Define your core fantasy
What is the MAIN thing players will do?
this.coreMechanic = 'combat' # Example: action game this.secondaryMechanics = ['movement', 'abilities'] this.tertiaryMechanics = ['inventory', 'crafting', 'trading']
Teaching order follows importance
this.order = [ this.coreMechanic, # First ...this.secondaryMechanics, ...this.tertiaryMechanics # Last (or never in tutorial) ] }
First 5 minutes should scream "THIS IS WHAT THIS GAME IS"
Not "here's the inventory UI"
}
Example:
Shooter: Shoot within 30 seconds
Puzzle: Solve puzzle within 60 seconds
Racing: Drive car within 10 seconds
RPG: Combat encounter within 2 minutes
Symptoms
- UI tutorial before gameplay
- Inventory before core loop
- Settings/customization before play
- Players confused about game genre
Detection Pattern
teach.inventory|tutorial.menu|settings.*first
Single Path Assumption
Id
single-path-assumption
Summary
Tutorial assumes one correct solution, breaking for creative players
Severity
medium
Situation
Player solves tutorial "wrong" and gets stuck or confused
Why
Players are creative. They'll try unexpected solutions. If your tutorial only works one way, creative players get stuck.
Example: Tutorial says "jump on box to reach ledge." Player uses rocket jump instead. Box is still there, blocking progress.
Solution
class FlexibleTutorial { constructor() {
Define goal, not path
this.objective = 'reachLedge'
Accept any valid solution
this.validSolutions = [ 'jumpOnBox', 'doubleJump', 'wallJump', 'rocketJump', 'grapplingHook' ]
Clear the objective when ANY valid solution used
this.onAnySuccess(() => this.clearObjective()) }
Test with: What if player does X instead?
For every step, imagine 3 alternative solutions
Support all of them
}
Symptoms
- Players stuck despite solving puzzle
- That's not how you're supposed to do it
- Tutorial only works one way
- Creative solutions break progression
Detection Pattern
if.===.&&.*expectedSolution
Hint Spam Annoyance
Id
hint-spam-annoyance
Summary
Relentless hints that won't stop even when player is exploring
Severity
medium
Situation
"Did you forget to press X?" appearing every 10 seconds
Why
Not every pause is confusion. Sometimes players want to explore. Constant hints communicate "you're doing it wrong."
Hint fatigue: After being interrupted 5 times, players ignore ALL hints. When they actually need help later, they've learned to dismiss.
Solution
class RespectfulHints { constructor() {
Escalating delay between hints
this.hintDelays = [30, 60, 120, 300] # seconds
Detect if player is exploring vs stuck
this.detectIntent = { exploring: player.isMoving && player.isLooking, stuck: player.idle > 30 && player.sameArea }
Hint counter with max
this.maxHintsPerObjective = 3 }
shouldShowHint(objective) { if (this.detectIntent.exploring) return false if (this.hintsShown[objective] >= this.maxHintsPerObjective) return false if (this.timeSinceLastHint < this.currentDelay) return false
return this.detectIntent.stuck }
onHintDismissed() {
Player dismissed = they're not stuck
this.increaseDelay() this.reduceHintFrequency() } }
Symptoms
- Same hint appearing multiple times
- Hints during exploration
- No cooldown between hints
- Players complaining about nagging
Detection Pattern
showHint(?!.cooldown|.maxShows|.*delay)
No Reinforcement After Teaching
Id
no-reinforcement-after-teaching
Summary
Teaching mechanic once and never using it again means players forget
Severity
medium
Situation
Showed jump tutorial in level 1, next jump required in level 5
Why
Learning decay is real. Skills unused for 10 minutes start fading. If you teach then don't reinforce, the teaching was wasted.
The "use it or lose it" principle applies to game mechanics too.
Solution
class ReinforcementSchedule { constructor() {
Spaced repetition after teaching
this.reinforcement = { jump: [ { level: 1, uses: 5 }, # Intro: 5 easy jumps { level: 2, uses: 3 }, # Reinforce: 3 moderate { level: 3, uses: 2 }, # Combine with other skills
Now it's part of regular vocabulary
] } }
afterTeaching(mechanic) {
Schedule 3-5 uses in next 10 minutes
this.scheduleReinforcement(mechanic, { usesRequired: 4, timeWindow: '10min', difficultyRamp: 'gradual' }) } }
Pattern: Teach -> Use x3 easy -> Use x2 medium -> Combine
Then mechanic is "learned" and can appear anywhere
Symptoms
- Large gaps between mechanic uses
- Players forgetting taught mechanics
- Mechanic used once then shelved
- Need to re-teach later
Detection Pattern
Metrics Blind Onboarding
Id
metrics-blind-onboarding
Summary
Not measuring where players drop off means you can't fix problems
Severity
high
Situation
No analytics for tutorial completion, step timing, or drop-off
Why
You cannot improve what you don't measure. Without data, you're guessing why players leave.
Every minute of onboarding is a funnel step. Measuring each step reveals exactly where players churn.
Solution
class OnboardingMetrics { constructor() { this.funnel = [ 'game_launched', 'first_input', 'tutorial_step_1', 'tutorial_step_2', 'tutorial_complete', 'core_loop_reached', 'first_session_complete', 'd1_return', 'd7_return' ] }
trackStep(step) { analytics.track('onboarding_funnel', { step, timeFromStart: performance.now() - this.startTime, deaths: this.deathCount, hintsShown: this.hintCount, hintsClicked: this.hintClickCount, skippedContent: this.skippedCount }) }
Dashboard should show:
- Conversion at each step
- Average time per step
- Drop-off spikes
- Correlation with retention
}
Key questions analytics should answer:
- What % complete tutorial?
- Where is the biggest drop?
- Are hints helping?
- Does skip hurt retention?
Symptoms
- No tutorial analytics
- Can't answer "where do players quit"
- Guessing at improvements
- No A/B testing capability
Detection Pattern
tutorial(?!.track|.analytics|.*metrics)
Mobile First Minutes Failure
Id
mobile-first-minutes-failure
Summary
Mobile players decide in 3 minutes; desktop patterns don't transfer
Severity
critical
Situation
Applying PC/console onboarding length to mobile game
Why
Mobile attention span is measured in seconds, not minutes. Mobile players often in interruptible contexts (commute, waiting). They need to feel value IMMEDIATELY.
The "3-minute rule": Within 3 minutes, mobile player must: 1. Understand core loop 2. Experience first reward 3. Feel anticipation for return
Solution
class MobileFTUE { constructor() {
Timeline in seconds
this.timeline = { 0: 'Splash/logo (skip on tap)', 5: 'First touch input', 15: 'Core mechanic demonstrated', 30: 'First reward collected', 60: 'Core loop completed once', 90: 'First "real" challenge', 120: 'Session goal achieved', 150: 'Return hook (daily reward, energy, event)', 180: 'Natural stopping point' }
Every second counts
this.maxTimeToFirstInput = 5 this.maxTimeToReward = 30 this.maxTimeToLoop = 60 }
Mobile-specific patterns:
- One-finger controls only initially
- Portrait mode first (most intimate)
- Haptic feedback on every action
- Save constantly (could close any moment)
- Show progress visually (no text reading)
}
Symptoms
- 5+ minute tutorial on mobile
- Complex controls in first session
- No clear stopping points
- No return hook setup
Detection Pattern
tutorialDuration.>.180|mobileTimeout.>.60
Player Onboarding - Validations
Unskippable Tutorial Content
Id
unskippable-tutorial
Severity
error
Type
regex
Pattern
- skipEnabled.false|canSkip.false|allowSkip.*false
- forceWatch.true|mandatory.true|required.true.tutorial
Message
Unskippable tutorial detected. Players MUST be able to skip. 30-50% of players will want to skip - if they can't, they quit instead.
Fix Action
Add skipEnabled: true or implement skip button. Remember to grant all rewards/unlocks when skipped.
Applies To
- *.js
- *.ts
- *.yaml
- *.json
Tutorial Blocking Core Gameplay
Id
tutorial-before-gameplay
Severity
error
Type
regex
Pattern
- await.tutorial.start.Game|tutorial\.complete.then.*startGame
- if.!tutorialComplete.return|!finishedTutorial.&&.block
Message
Tutorial blocking gameplay start. Players should be playing within 30 seconds. Integrate teaching INTO gameplay, don't gate on completion.
Fix Action
Move tutorial teaching into first level. Start gameplay immediately, teach during play.
Applies To
- *.js
- *.ts
Too Many Tutorial Steps
Id
excessive-tutorial-steps
Severity
warning
Type
regex
Pattern
- tutorialStep.[6-9]|step\s[>=]\s*[6-9]
- tutorial\.steps\.length.>.5|steps\.push.steps\.push.steps\.push.steps\.push.steps\.push
Message
6+ tutorial steps detected. Players forget early lessons by step 6. Limit to 4-5 discrete teaching moments in first session, spread more across gameplay.
Fix Action
Reduce to 4-5 core steps. Defer advanced mechanics to later in gameplay.
Applies To
- *.js
- *.ts
Information Overload Popup
Id
info-dump-popup
Severity
warning
Type
regex
Pattern
- showMessage.\.length.>.100|displayText.length.>.80
- controls:\s*\{[^}]{400,}\}
Message
Long text in tutorial detected. Players don't read. Keep prompts under 10 words. Show, don't tell.
Fix Action
Replace text with visual demonstration. If text necessary, limit to 5-10 words max.
Applies To
- *.js
- *.ts
- *.json
Skip Without Granting Rewards
Id
no-skip-grant
Severity
error
Type
regex
Pattern
- skipTutorial(?![\s\S]{0,200}(grant|unlock|give|add))
- onSkip(?![\s\S]{0,200}(reward|item|ability|unlock))
Message
Skip implemented but may not grant rewards. Players who skip must receive all items/unlocks/abilities they would have gotten.
Fix Action
Add grantSkipRewards() or equivalent after skip. Include items, abilities, flags, and state.
Applies To
- *.js
- *.ts
Unskippable Cutscene at Start
Id
forced-cutscene
Severity
warning
Type
regex
Pattern
- playCutscene.await|playVideo.await|playIntro.*await
- introSequence(?!.skipOnInput|.skipEnabled)
Message
Potential unskippable cutscene at game start. Every second before first input costs players. Make interruptible or skippable.
Fix Action
Add skipOnInput option or skip button. Consider starting gameplay during cutscene (audio over gameplay).
Applies To
- *.js
- *.ts
Hint System Without Cooldown
Id
hint-without-cooldown
Severity
warning
Type
regex
Pattern
- showHint(?![\s\S]{0,100}(cooldown|delay|timeout|lastHint))
- displayTip(?![\s\S]{0,100}(interval|throttle|maxShow))
Message
Hint system may spam players. Hints need cooldowns to avoid annoyance. Players need time to try on their own.
Fix Action
Add cooldown (30s minimum), max show count, and detection for 'player exploring vs stuck'.
Applies To
- *.js
- *.ts
Tutorial Without Analytics
Id
no-tutorial-analytics
Severity
warning
Type
regex
Pattern
- class.*Tutorial(?![\s\S]{0,500}(track|analytics|metrics))
- tutorial(?![\s\S]{0,300}(funnel|conversion|dropoff))
Message
Tutorial system without visible analytics. You can't improve what you don't measure. Track completion, drop-off points, time per step.
Fix Action
Add analytics tracking for each step: analytics.track('tutorial_step', {step, time, completed})
Applies To
- *.js
- *.ts
Game Over During Tutorial
Id
game-over-in-tutorial
Severity
warning
Type
regex
Pattern
- gameOver.tutorial|death.tutorial.*gameOver
- tutorial.onDeath.gameOverScreen
Message
Game over screen during tutorial. New players shouldn't see game over. Respawn immediately without loading screen.
Fix Action
Replace game over with instant respawn. Hide death count. Make tutorial phase very forgiving.
Applies To
- *.js
- *.ts
Teaching Standard Controls
Id
teaching-obvious-controls
Severity
warning
Type
regex
Pattern
- tutorial.wasd|teach.move.arrow|hint.space.*jump
- showMessage."press.to.move"|prompt."click.to.select"
Message
Teaching standard controls (WASD, click, space). Gamers know these. Only teach game-specific mechanics.
Fix Action
Remove prompts for standard controls. Trust players to know genre conventions.
Applies To
- *.js
- *.ts
No Safe Failure During Learning
Id
no-safe-fail-zone
Severity
warning
Type
regex
Pattern
- tutorialEnemy.damage.=.(?:[2-9]|[1-9][0-9])|enemy.damage.tutorial.(?:[2-9]|[1-9][0-9])
- tutorial(?![\s\S]{0,200}(forgiving|reduced.*damage|safe))
Message
Tutorial may not have safe failure. New players need forgiving environment to experiment. Reduce enemy damage, remove death penalty.
Fix Action
During tutorial: reduce enemy damage to 25%, give abundant health pickups, instant respawn.
Applies To
- *.js
- *.ts
Single-Path Tutorial Design
Id
linear-only-tutorial
Severity
warning
Type
regex
Pattern
- if.solution.===.expected|correctAnswer.===|onlyWay.*true
- mustUse.mechanic|requiredAction.===.*specific
Message
Tutorial may assume single solution. Creative players will find alternatives. Accept any valid solution to objectives.
Fix Action
Define goal, not path. Check for objective completion regardless of method used.
Applies To
- *.js
- *.ts
No Veteran Player Detection
Id
no-veteran-detection
Severity
warning
Type
regex
Pattern
- tutorial(?![\s\S]{0,400}(veteran|experience|skilled|advanced))
- onboarding(?![\s\S]{0,400}(detectSkill|playerLevel|adapt))
Message
No veteran detection in onboarding. Veterans get frustrated with basic tutorials. Detect skill and adapt teaching.
Fix Action
Track player actions. If using advanced techniques, reduce tutorial. Offer 'I know this' option.
Applies To
- *.js
- *.ts
Hints Not Contextual
Id
no-context-hints
Severity
warning
Type
regex
Pattern
- showAllHints|displayControlList|showControls\(\)|listBindings
Message
Hints shown without context. Teach mechanics when needed, not upfront. Players forget what they don't immediately use.
Fix Action
Trigger hints based on player situation: near gap = jump hint, near enemy = attack hint.
Applies To
- *.js
- *.ts
No Mechanic Reinforcement
Id
no-reinforcement-schedule
Severity
warning
Type
regex
Pattern
- teachMechanic(?![\s\S]{0,300}(reinforce|practice|uses|repeat))
- tutorial\.complete(?![\s\S]{0,200}schedule.*practice)
Message
Teaching without reinforcement schedule. Players forget unused mechanics. Plan 3-5 uses of each mechanic in next 10 minutes.
Fix Action
After teaching: schedule 3 easy uses, 2 moderate uses, then combine with other mechanics.
Applies To
- *.js
- *.ts
Onboarding Completeness Check
Id
onboarding-checklist
Severity
info
Type
file
Pattern
onboarding-checklist.md
Message
Consider creating onboarding-checklist.md to track: [ ] Skip option visible at all times [ ] Time to first input < 10 seconds [ ] Core loop reached < 60 seconds [ ] Max 4 teaching moments in first 5 minutes [ ] Safe failure (no game over in tutorial) [ ] Hints have cooldown and max shows [ ] Analytics for each onboarding step [ ] Veteran detection/skip option [ ] Mobile: 3-minute hook complete [ ] Reinforcement scheduled for taught mechanics
Fix Action
Create checklist file to ensure comprehensive onboarding design
Applies To
- /tutorial/
- /onboarding/
Mobile Game Slow Start
Id
mobile-slow-start
Severity
error
Type
regex
Pattern
- mobile.tutorial.duration.>.120|mobileOnboarding.time.>.*180
- platform.mobile.tutorialSteps.>.3
Message
Mobile tutorial exceeds 2-3 minutes. Mobile players decide in 3 minutes. Compress onboarding dramatically.
Fix Action
Mobile FTUE: first input < 5s, core loop < 60s, return hook < 180s.
Applies To
- *.js
- *.ts
- *.json
Mobile Without Auto-Save
Id
mobile-no-save
Severity
warning
Type
regex
Pattern
- mobile(?![\s\S]{0,300}(autoSave|saveState|persist))
- platform.*mobile(?![\s\S]{0,200}backgroundSave)
Message
Mobile game may not auto-save frequently. Mobile players get interrupted constantly. Save every 10 seconds.
Fix Action
Implement aggressive auto-save. Save on any significant action. Save on app background.
Applies To
- *.js
- *.ts
Mobile Without Return Hook
Id
mobile-no-return-hook
Severity
warning
Type
regex
Pattern
- mobileOnboarding(?![\s\S]{0,400}(dailyReward|energy|notification|returnHook))
- mobile.*ftue(?![\s\S]{0,300}(anticipation|tomorrow|comeback))
Message
Mobile FTUE may lack return hook. The 3-minute session must create anticipation for return. Show what they CAN'T have yet.
Fix Action
Before first session end: show locked content, set up daily reward, create anticipation.
Applies To
- *.js
- *.ts