Repository navigation
feat(dashboard): first-run and empty states where the user lands - #154
Open
UltimaPhoenix wants to merge 1 commit into
Open
UltimaPhoenix wants to merge 1 commit into
UltimaPhoenix wants to merge 1 commit into
Conversation
/knowledge shows a set-up block while the knowledge table is empty, and one line above the map once it is set up but no lesson exists yet. /lessons with no lesson and no filter shows an example lesson, the diagnostic command for this install and the pacing read from Settings. A filtered-empty list names the filters that hid everything and offers Search all time / Clear every filter. The command comes from core/runtime.ts doctorHint(channel); copy is host-neutral outside the /devcoach:setup hint. ui_home=auto is unchanged.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First run and empty states. A new user now lands on a page that says what to do next, not a blank map.
What changes
/knowledge, not set up (empty knowledge table)0 lessons total · 0 / 2 today · 0 this week · Available now/devcoach:setup), keep working (pacing from Settings), and the diagnostic command for this install with Copy/knowledge, set up, no lesson yet/lessons)/lessons, no lesson, no filter📭 No lessons match the current filters.(no filter is set)/lessons, filters hide everythingcore/runtime.ts: newdoctorHint(channel)on top ofclassifyPath./devcoach:setupunder the plugin,devcoach doctorfor Homebrew and npm-global,npx -y devcoach doctorfor everything else.createAppreads the running process's channel once;AppOptions.channeloverrides it for tests./devcoach:setup, inside<span data-plugin-hint>, and a test enforces that.ui_home=auto/resolveHomePath,DEFAULT_SETTINGS, the cue engine, and every hook. The empty states are pull-only. The<nav>is untouched.docs/usage/web-ui.md(stats bar, before the first lesson, filtered-empty).CLAUDE.mdmentionsdoctorHint.Decisions
Decisions taken in the PR:
?search=kafka&period=week./devcoach:setup", not "in Claude Code". The command only exists with the plugin, and a Claude Code user with a plain MCP entry has no such command. The dashboard's own install channel says nothing about which host the user's agent runs in, so the hint is always shown with that qualifier./devcoach:setuptoo, worded "In Claude Code, run/devcoach:setup: it checks the runtime, the server and your profile." That is whatplugin/commands/setup.mddoes: the launcher's doctor first, then the server, then the profile./lessonsalso says "First, set up your profile" while the knowledge table is empty. The ruling puts set-up on/knowledge, but someone who opens Lessons first would otherwise wait for lessons that cannot come. It is computed only when there are no lessons, so the knowledge lookup costs nothing in normal use.tests/web-first-run.test.ts.tests/setup.tsgives each test file its own HOME, andweb.test.tsseeds a lesson for its whole file in a top-levelbeforeAll, so it can never be empty. The filtered-empty test stays inweb.test.ts.doctorHintlives incore/runtime.ts, next to the channel table it maps, andapp.tscalls it. The brief listedapp.ts; this keeps install knowledge in one place, andcorestill never importsweb.activeFilterslist, andanyFilteris now its length, so the sentence can never disagree with the chips. Labels are unchanged. PR 4's renames ofFEEDBACK_LABELS/sharedLabelflow into both.busy_timeout) with a shortened body and the 💡 tip. It is a<figure>with a<figcaption>"What a lesson looks like", notaria-hidden, so screen-reader users get the example too. The/knowledgestrip links to/lessonsas the ruling says, and this example sits there.data-copy, so nothing ends up in a JS literal. No new asset./knowledgedoes not loadshare.js.CHANGELOG
Suggested line for
[Unreleased]→ Added (not edited here, to avoid a conflict with the request-guard PR's CHANGELOG entry):Tests
tests/web-first-run.test.ts(new, brand-new sandbox, run in order):/knowledgehas the set-up block and no stats line;/lessonshas the ghost lesson, the doctor command and the pacing sentence.3/90→ "at most 3 lessons a day, 1 hour 30 minutes apart",1/45→ singular,5/0→ no "apart",2/60→ "1 hour".data-plugin-hintspans, for four channels × both pages, and every hint carries/devcoach:setup(mutation-checked: putting "Claude Code" in the lessons copy fails it)./lessons, and the stats line is gone.tests/web.test.ts: a filter that matches nothing names it, with both links (search+period), only Clear every filter without a period, "No lessons in 📅 …" for a date range alone, "a, b and c" for three filters, and the user's search text stays escaped.tests/runtime.test.ts:doctorHintfor every channel, and throughclassifyPathfor a plugin runtime and a Cellar path (Homebrew wins over/node_modules/devcoach/).npm run lintpasses. The 3 infos are pre-existing, intests/cli.test.ts.npm run typecheckpasses.npm run test:cov: 403 passed, coverage 94.88 lines · 93.65 statements · 96.92 functions · 84.50 branches. Thresholds are 92 / 91 / 95 / 76.02 functions · 84.49 branches. Thresholds are 92 / 91 / 95 / 76.Before / after
Slideshow — each screen BEFORE (red band: without this PR), then AFTER (green band: with this PR), with one line saying what changed. It plays by itself; click it to open it full size.
Dark
Videos — the first frame is the title; a full red BEFORE or green AFTER card opens every segment, and the band in the same colour stays above the recording until the segment ends.
Recorded in real Chrome (Playwright,
channel: "chrome") ondevcoach ui --port 7879at 1200 × 800 and 420 × 800, light and dark, with the same script for both sides. BEFORE ran from a checkout ofdevelop(2.7.1), AFTER from this branch. Every caption is read from the page. The three sandboxes are:scripts/screenshots/fixture.ziprestored withDELETE FROM lessonson the sandbox db;?search=kafka&period=week.At 420 px the nav still makes every page 555 px wide on both sides: the nav is a separate decision, not this PR's. The stills are clipped to the 420 px viewport.
Light, 3 min: BEFORE then AFTER at 1200 px, then BEFORE then AFTER at 420 px. Three sandboxes: a brand-new install (/ lands on /knowledge: an empty map under a row of zeros → the “Set up devcoach” block; /lessons: “No lessons match the current filters.” with no filter set → “No lessons yet”, an example lesson, npx -y devcoach doctor, the pacing), the fixture with its lessons deleted (row of zeros → one line above the map, whose link opens /lessons), and search “kafka” in the last 7 days (→ the filters named, Search all time · Clear every filter).
pr-133-before-after-light.mp4
Dark, the same run: BEFORE then AFTER at 1200 px, then at 420 px. Captions are read from the page. At 420 the nav still overflows on both sides; the nav is a separate decision.
pr-133-before-after-dark.mp4
Side by side — BEFORE on the left, AFTER on the right.
A brand-new install, /knowledge: BEFORE an empty map and “0 lessons total · 0 / 2 today · 0 this week · Available now”; AFTER the “Set up devcoach” block: say “set up devcoach” to your agent (plugin: /devcoach:setup), keep working (at most 2 a day, 4 hours apart), and npx -y devcoach doctor with Copy. (1200 px, light)
Dark
A brand-new install, /knowledge: BEFORE an empty map and “0 lessons total · 0 / 2 today · 0 this week · Available now”; AFTER the “Set up devcoach” block: say “set up devcoach” to your agent (plugin: /devcoach:setup), keep working (at most 2 a day, 4 hours apart), and npx -y devcoach doctor with Copy. (420 px, light; 420 px stills are clipped to the viewport)
Dark
A brand-new install, /lessons: BEFORE “No lessons match the current filters.” with no filter set; AFTER “No lessons yet”, a reminder to set up the profile first, a greyed example lesson, the doctor command with Copy, and the pacing read from Settings. (1200 px, light)
Dark
A brand-new install, /lessons: BEFORE “No lessons match the current filters.” with no filter set; AFTER “No lessons yet”, a reminder to set up the profile first, a greyed example lesson, the doctor command with Copy, and the pacing read from Settings. (420 px, light; 420 px stills are clipped to the viewport)
Dark
Topics, no lesson (fixture with its lessons deleted), /knowledge: BEFORE the same row of zeros above the map; AFTER one line: “No lesson yet — the first one arrives after real work in your agent, at most 2 a day, 4 hours apart. What a lesson looks like →”. (1200 px, light)
Dark
Topics, no lesson (fixture with its lessons deleted), /knowledge: BEFORE the same row of zeros above the map; AFTER one line: “No lesson yet — the first one arrives after real work in your agent, at most 2 a day, 4 hours apart. What a lesson looks like →”. (420 px, light; 420 px stills are clipped to the viewport)
Dark
A filter that matches nothing (search “kafka”, last 7 days): BEFORE “No lessons match the current filters.” + Clear all filters; AFTER “No lessons match 🔍 "kafka" in 🕐 Last 7 days.” + Search all time · Clear every filter. (1200 px, light)
Dark
A filter that matches nothing (search “kafka”, last 7 days): BEFORE “No lessons match the current filters.” + Clear all filters; AFTER “No lessons match 🔍 "kafka" in 🕐 Last 7 days.” + Search all time · Clear every filter. (420 px, light; 420 px stills are clipped to the viewport)
Dark
Verified by hand in real Chrome: Copy on
/knowledgeand/lessonsputsnpx -y devcoach doctoron the clipboard. The label reads "✓ Copied" and goes back to "Copy" after 1.5 s.Not verified
section+aria-labelledby, and the example is afigure+figcaption.AppOptions.channel), not by a real plugin or Homebrew install.🤖 Generated with Claude Code