Skip to content

PBS frontend redesign - #12

Merged
saengel merged 5 commits into
mainfrom
feature/pbs-redesign
Oct 11, 2026
Merged

saengel merged 5 commits into
mainfrom
feature/pbs-redesign

Conversation

@saengel

@saengel saengel commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

Frontend redesign for the PBS dashboard.

saengel and others added 3 commits October 8, 2026 15:42
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gitvelocity-reviewer

Copy link
Copy Markdown

📊 Code Quality Score: 76/100

S 19 + A 15 + I 14 + R 13 + Q 12 + P 3 = 76 base. Extra Large tier (7244 effective lines, 146 files), ESF 1.0, so 76 x 1.0 = 76.

Category Score Factors
🔭 Scope 19/20 146 files change. The old App.jsx, Sidebar.jsx, Dashboard.jsx, the utils/* helpers and every components/charts/*.jsx file are deleted and replaced by src/app, src/components/ui, src/components/layout, src/features/browse, src/features/project and src/features/charts. It also touches index.html metadata, eslint.config.js, package.json, ci.yml, a new Playwright config and an og-image and font under public/.
🏗️ Architecture 15/20 Introduces BrowserRouter with AppRoutes, a lazy ChartsPage so recharts leaves the main bundle, and PageLayout as the shared landmark shell. Browse state moves into URL query params through useProjectQueryState. Dialog wraps a native <dialog> and is reused by the project dialog and FilterSheet as modal and sheet placements. Feature code imports from a components/ui kit and from lib/ selectors.
⚙️ Implementation 14/20 BrowsePage debounces the search input into the URL with useEffectEvent, resets the page limit during render when the filter signature changes, and moves focus to data-result-index after Show more. FilterSheet keeps a pending selection and applies it only on Show. Dialog ref-counts scrollLocks, ignores a close event fired while the dialog is open, and detects backdrop clicks from mousedown plus click. ProjectList switches between table and rows with useMediaQuery. Constellation draws 17 nodes and 25 edges from static arrays.
⚠️ Risk 13/20 The change replaces the whole production UI and changes how users reach views: tabs become routes and ?project=, ?q=, ?category= and ?view= query params. There is no feature flag or staged rollout in the diff. ci.yml now blocks merges on typecheck, Vitest and Playwright, and the build script runs tsc -b before vite build. The SPA needs host-level fallback for /charts and deep links, which the diff does not show.
✅ Quality 12/15 Vitest unit tests cover categories, endpoints, experience, api and chart selectors, with fixture-derived assertions. Component tests cover Dialog, SegmentedControl, SiteHeader, FilterSheet, ProjectCard, ProjectDetail, BrowsePage and ChartsPage, each with a vitest-axe check. Playwright specs browse, charts and layout run on desktop and mobile projects. ProjectCard.test.tsx regex-matches TopicTags.module.css, and layout.spec.ts asserts a 28px tag-row height. No test drives Hero, ProjectList, ActiveFilters, or Back/Forward search sync in BrowsePage.
🔒 Perf / Security 3/5 ExternalLink sets target="_blank" with rel="noreferrer". /charts and the 404 page set noindex, nofollow. The ChartsPage import is lazy-loaded to keep recharts out of the main bundle. Search input is debounced 150 ms. The 44px touch-target and axe checks in the e2e suite cover accessibility. No benchmark accompanies the change.

Was this score accurate? 👍 Yes · 👎 No

How this was scored →

Scored by GitVelocity · How are scores calculated?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Visible focus, keyboard scrolling, and zero-value chart rendering issues remain unresolved.

4 open findings
What changed in this PR

Rebuilds the PBS dashboard as a TypeScript, responsive React application with accessible browsing, project dialogs, analytics, routing, and expanded testing.

Changes:

  • Introduces normalized project data, URL-backed filtering, sorting, and responsive views.
  • Adds reusable UI/layout components and redesigned analytics charts.
  • Migrates testing and tooling to Vitest, Playwright, TypeScript, and stricter CI.
File Description
vite.config.ts Adds typed Vite/Vitest configuration.
vite.config.js Removes JavaScript Vite configuration.
tsconfig.node.json Configures Node-side TypeScript.
tsconfig.json Adds TypeScript project references.
tsconfig.app.json Configures strict application TypeScript.
src/​utils/​sortProjects.js Removes legacy sorting utility.
src/​utils/​sefariaTools.js Removes legacy endpoint utility.
src/​utils/​projectPreview.js Removes iframe preview utility.
src/​utils/​projectDetail.js Removes legacy detail helpers.
src/​utils/​pagination.js Removes page-number pagination.
src/​utils/​keywords.js Removes legacy keyword aggregation.
src/​utils/​experience.js Removes legacy experience mapping.
src/​utils/​categories.js Removes legacy category utility.
src/​utils/​__tests__/​techUsed.test.js Removes legacy technology tests.
src/​utils/​__tests__/​sortProjects.test.js Removes legacy sorting tests.
src/​utils/​__tests__/​sefariaTools.test.js Removes legacy endpoint tests.
src/​utils/​__tests__/​projectPreview.test.js Removes preview tests.
src/​utils/​__tests__/​projectDetail.test.js Removes detail helper tests.
src/​utils/​__tests__/​pagination.test.js Removes pagination tests.
src/​utils/​__tests__/​experience.test.js Removes legacy experience tests.
src/​utils/​__tests__/​categories.test.js Removes legacy category tests.
src/​Title.jsx Removes old dashboard header.
src/​test/​vitest-axe.d.ts Adds axe matcher typings.
src/​test/​setup.ts Configures DOM test shims.
src/​test/​factories.ts Adds normalized project factories.
src/​styles/​tokens.css Defines semantic design tokens.
src/​styles/​reset.css Adds global CSS reset.
src/​styles/​global.css Adds global typography and focus styles.
src/​main.tsx Adds typed application entry point.
src/​main.jsx Removes legacy entry point.
src/​lib/​url.ts Implements query-state serialization.
src/​lib/​tech.ts Adds typed technology parsing.
src/​lib/​sort.ts Adds typed project sorting.
src/​lib/​reach.ts Adds reach parsing and labels.
src/​lib/​format.ts Adds date and number formatting.
src/​lib/​filter.ts Adds search and filtering logic.
src/​lib/​experience.ts Adds typed experience mapping.
src/​lib/​endpoints.ts Adds endpoint normalization and grouping.
src/​lib/​categories.ts Adds category metadata and parsing.
src/​lib/​api.ts Adds normalized API client.
src/​lib/​__tests__/​url.test.ts Tests query-state behavior.
src/​lib/​__tests__/​tech.test.ts Tests technology parsing.
src/​lib/​__tests__/​sort.test.ts Tests typed sorting.
src/​lib/​__tests__/​reach.test.ts Tests reach parsing.
src/​lib/​__tests__/​format.test.ts Tests formatting helpers.
src/​lib/​__tests__/​filter.test.ts Tests search and filters.
src/​lib/​__tests__/​experience.test.ts Tests experience parsing.
src/​lib/​__tests__/​endpoints.test.ts Tests endpoint grouping.
src/​lib/​__tests__/​categories.test.ts Tests category parsing.
src/​lib/​__tests__/​api.test.ts Tests API behavior.
src/​hooks/​useProjects.ts Adds cached project loading.
src/​hooks/​useProjectQueryState.ts Connects browse state to URLs.
src/​hooks/​useMediaQuery.ts Adds reactive media queries.
src/​hooks/​useDocumentMeta.ts Manages route metadata.
src/​hooks/​useDebouncedValue.ts Adds reusable debouncing.
src/​features/​project/​ProjectDialog.tsx Adds responsive project dialog.
src/​features/​project/​ProjectDialog.module.css Styles project dialog layout.
src/​features/​project/​ProjectDetail.module.css Styles project details.
src/​features/​charts/​YearBarChart.tsx Adds yearly submissions chart.
src/​features/​charts/​HBarChart.tsx Adds horizontal bar chart.
src/​features/​charts/​HBarChart.module.css Styles horizontal bars.
src/​features/​charts/​DataTable.tsx Adds accessible chart tables.
src/​features/​charts/​DataTable.module.css Styles chart tables.
src/​features/​charts/​CumulativeLineChart.tsx Adds cumulative projects chart.
src/​features/​charts/​chartTheme.ts Centralizes chart styling.
src/​features/​charts/​ChartsPage.module.css Styles analytics page.
src/​features/​charts/​chartNotes.ts Configures chart annotations.
src/​features/​charts/​ChartCard.tsx Adds reusable chart container.
src/​features/​charts/​ChartCard.module.css Styles chart cards.
src/​features/​charts/​__tests__/​ChartsPage.test.tsx Tests analytics page.
src/​features/​browse/​TopicTags.tsx Adds clipped topic rows.
src/​features/​browse/​TopicTags.module.css Styles topic rows.
src/​features/​browse/​ShowMore.tsx Adds incremental loading control.
src/​features/​browse/​ShowMore.module.css Styles show-more control.
src/​features/​browse/​ResultsToolbar.tsx Adds search and view controls.
src/​features/​browse/​ResultsToolbar.module.css Styles results toolbar.
src/​features/​browse/​ResultsSkeleton.tsx Adds loading placeholders.
src/​features/​browse/​ProjectList.module.css Styles responsive project lists.
src/​features/​browse/​ProjectGrid.tsx Adds project grid rendering.
src/​features/​browse/​ProjectGrid.module.css Styles project grid.
src/​features/​browse/​ProjectCard.tsx Adds redesigned project cards.
src/​features/​browse/​ProjectCard.module.css Styles project cards.
src/​features/​browse/​FilterSheet.tsx Adds mobile filter sheet.
src/​features/​browse/​FilterSheet.module.css Styles filter sheet.
src/​features/​browse/​FilterPanel.tsx Adds category filter panel.
src/​features/​browse/​FilterPanel.module.css Styles filter controls.
src/​features/​browse/​BrowsePage.module.css Styles browse-page layout.
src/​features/​browse/​ActiveFilters.tsx Adds removable filter chips.
src/​features/​browse/​ActiveFilters.module.css Styles active filters.
src/​features/​browse/​__tests__/​ProjectCard.test.tsx Tests project cards.
src/​features/​browse/​__tests__/​FilterSheet.test.tsx Tests filter-sheet behavior.
src/​data/​fetchProjects.js Removes legacy API client.
src/​components/​ui/​VisuallyHidden.tsx Adds assistive-only content.
src/​components/​ui/​VisuallyHidden.module.css Styles visually hidden content.
src/​components/​ui/​Tag.tsx Adds reusable tags.
src/​components/​ui/​Tag.module.css Styles tag variants.
src/​components/​ui/​Skeleton.tsx Adds loading skeleton primitive.
src/​components/​ui/​Skeleton.module.css Styles skeleton animation.
src/​components/​ui/​Select.tsx Adds labelled select control.
src/​components/​ui/​Select.module.css Styles select control.
src/​components/​ui/​SegmentedControl.tsx Adds view toggle control.
src/​components/​ui/​SegmentedControl.module.css Styles segmented control.
src/​components/​ui/​SearchField.tsx Adds accessible search field.
src/​components/​ui/​SearchField.module.css Styles search input.
src/​components/​ui/​IconButton.tsx Adds icon-button primitive.
src/​components/​ui/​IconButton.module.css Styles icon buttons.
src/​components/​ui/​ExternalLink.tsx Standardizes external links.
src/​components/​ui/​EmptyState.tsx Adds reusable empty state.
src/​components/​ui/​EmptyState.module.css Styles empty states.
src/​components/​ui/​Dialog.tsx Adds native dialog primitive.
src/​components/​ui/​Dialog.module.css Styles modal and sheet dialogs.
src/​components/​ui/​cx.ts Adds class-name helper.
src/​components/​ui/​Checkbox.tsx Adds custom checkbox control.
src/​components/​ui/​Checkbox.module.css Styles checkbox control.
src/​components/​ui/​Button.tsx Adds button and link variants.
src/​components/​ui/​Button.module.css Styles button variants.
src/​components/​ui/​__tests__/​SegmentedControl.test.tsx Tests segmented control.
src/​components/​ui/​__tests__/​Dialog.test.tsx Tests dialog behavior.
src/​components/​SortDropdown.jsx Removes legacy sort dropdown.
src/​components/​Sidebar.jsx Removes tab sidebar.
src/​components/​ProjectGrid.jsx Removes legacy grid.
src/​components/​ProjectCard.jsx Removes legacy card.
src/​components/​Pagination.jsx Removes pagination component.
src/​components/​layout/​SkipLink.tsx Adds keyboard skip link.
src/​components/​layout/​SkipLink.module.css Styles skip link.
src/​components/​layout/​SiteHeader.module.css Styles responsive site header.
src/​components/​layout/​SiteFooter.tsx Adds redesigned footer.
src/​components/​layout/​SiteFooter.module.css Styles site footer.
src/​components/​layout/​SamekhLogo.tsx Adds developer logo link.
src/​components/​layout/​SamekhLogo.module.css Styles logo tile.
src/​components/​layout/​Hero.tsx Adds redesigned hero.
src/​components/​layout/​Container.tsx Adds shared content container.
src/​components/​layout/​Container.module.css Styles content container.
src/​components/​layout/​Constellation.tsx Adds decorative hero graphic.
src/​components/​layout/​Constellation.module.css Positions constellation graphic.
src/​components/​layout/​__tests__/​SiteHeader.test.tsx Tests header behavior.
src/​components/​icons/​topics/​index.tsx Adds custom topic icons.
src/​components/​icons/​CategoryIcon.tsx Adds category icon mapping.
src/​components/​icons/​CategoryIcon.module.css Styles category tiles.
src/​components/​Dashboard.jsx Removes legacy dashboard.
src/​components/​Controls.jsx Removes legacy controls.
src/​components/​ChartsAndAnalytics.jsx Removes legacy analytics view.
src/​components/​charts/​VibeCodedTrendChart.jsx Removes legacy vibe chart.
src/​components/​charts/​types/​PieChart.jsx Removes legacy pie wrapper.
src/​components/​charts/​types/​LineChart.jsx Removes legacy line wrapper.
src/​components/​charts/​types/​BarChart.jsx Removes legacy bar wrapper.
src/​components/​charts/​ToolUsagePieChart.jsx Removes endpoint pie chart.
src/​components/​charts/​TechUsedChart.jsx Removes legacy technology chart.
src/​components/​charts/​SubmissionsTrendChart.jsx Removes legacy trend chart.
src/​components/​charts/​KeywordFrequencyChart.jsx Removes legacy keyword chart.
src/​components/​charts/​ExperienceTrendChart.jsx Removes legacy experience chart.
src/​assets/​samech-logo.svg Adds Samekh vector asset.
src/​app/​routes.tsx Adds application routes.
src/​app/​PageLayout.tsx Adds shared page landmarks.
src/​app/​NotFound.tsx Adds client-side 404 page.
src/​app/​NotFound.module.css Styles the 404 page.
src/​app/​App.tsx Adds routed application shell.
src/​App.jsx Removes legacy application shell.
README.md Documents architecture and operation.
playwright.config.ts Configures responsive E2E tests.
package.json Adds redesigned app dependencies and scripts.
index.html Adds metadata and typed entry point.
eslint.config.js Enables strict TypeScript and accessibility linting.
e2e/​support.ts Adds deterministic E2E fixtures.
e2e/​screenshots.spec.ts Adds responsive screenshot generation.
e2e/​charts.spec.ts Adds analytics E2E coverage.
.prettierrc Adds formatting rules.
.prettierignore Excludes generated and fixture files.
.gitignore Ignores Playwright artifacts.
.github/​workflows/​ci.yml Adds typecheck, tests, and E2E CI.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/app/NotFound.module.css
Comment thread src/features/browse/ProjectList.module.css
Comment thread src/features/charts/ChartsPage.module.css
Comment thread src/features/charts/HBarChart.tsx Outdated
saengel and others added 2 commits October 11, 2026 10:51
- restore visible focus ring on skip-link heading (NotFound, ChartsPage)
- make the projects table scroller a keyboard-focusable named region
- draw no bar for zero-valued HBarChart rows, with a regression test

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Drops the checkbox, the active-filter chip, the ?open=1 URL param and the
openSourceOnly filter logic. The project dialog's View source code button is
unchanged. Departs from spec 5.5 and 7.1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@saengel
saengel merged commit 85739dd into main Oct 11, 2026
1 check passed
@saengel
saengel deleted the feature/pbs-redesign branch October 11, 2026 07:57
@gitvelocity-reviewer

Copy link
Copy Markdown

📊 Code Quality Score: 73/100

Base Score 73 (S19 + A15 + I14 + R9 + Q13 + P3) × ESF 1.0 (7221 effective lines, 147 files, Extra Large) = 73

Category Score Factors
🔭 Scope 19/20 147 files change, and the old App.jsx, Dashboard.jsx, ProjectDetailModal.jsx and chart components are deleted. They are replaced by src/app, src/features/browse, src/features/charts, src/features/project, src/components/ui, src/components/layout, src/lib and src/hooks. It also touches index.html (meta tags, OG image, fonts), package.json, eslint.config.js, playwright.config.ts and .github/workflows/ci.yml. Two routes exist, / and /charts, and * renders NotFound.
🏗️ Architecture 15/20 The tab switch in App.jsx is replaced by AppRoutes under BrowserRouter, with ChartsPage behind lazy() so recharts stays out of the main bundle. Features are split into src/features/*, shared primitives into src/components/ui, and pure logic into src/lib (filter, sort, categories, endpoints, experience, api). BrowsePage takes its state from useProjectQueryState over the URL instead of component useState. Dialog wraps the native <dialog> with showModal() in place of the hand-rolled backdrop modal. PageLayout centralises the skip link, header, main and footer.
⚙️ Implementation 14/20 Dialog keeps a module-level scrollLocks counter and ignores a close event that arrives while the dialog is open again, which covers the React strict-mode re-run. It also treats a backdrop click as a mousedown and a click that both land on the <dialog> element. BrowsePage debounces the search input by 150 ms into the URL, resets the page size when the `q
⚠️ Risk 9/20 It replaces the whole public front end, and the URL scheme now carries q, category, sort, view and project, so old bookmarks to / land on the new page. Data still comes from the unauthenticated https://www.sefaria.org/api/powered-by endpoint, now through fetchProjects with ApiError on bad status or shape and a Try again path. build now runs tsc -b first, so a type error blocks deploys. CI gains an e2e step that builds and serves the site. No auth, schema or migration is touched.
✅ Quality 13/15 Unit tests cover selectors.test.ts (fixture-pinned numbers such as 133 total, 23 undated, 58 in 2026, and zero-fill cases), endpoints.test.ts (a 26-row table), categories.test.ts, experience.test.ts, api.test.ts, Dialog.test.tsx (strict-mode stale close, backdrop click, focus return), FilterSheet.test.tsx, BrowsePage.test.tsx, ProjectDetail.test.tsx and ChartsPage.test.tsx. Most components also have a vitest-axe check. Playwright specs browse.spec.ts, charts.spec.ts and layout.spec.ts run on desktop and mobile projects against a stubbed API fixture. They check 44×44 touch targets, overflow at six widths, quote/hero overlap and axe with WCAG 2.2 AA tags. ProjectCard.test.tsx reads the CSS file to assert the tag-row clamp. No test drives useProjectQueryState or useDebouncedValue directly, and no test file is visible for lib/filter.ts or lib/sort.ts. No README or design doc is added.
🔒 Perf / Security 3/5 ChartsPage is lazy-loaded, so recharts is kept out of the initial bundle. ExternalLink sets target="_blank" with rel="noreferrer" and announces the new tab. /charts is noindex, nofollow and is not linked from the site. Show more caps the render at 24 items per step, and the heavy filter and sort work sits in useMemo. The font loading list is trimmed in index.html. No benchmark or bundle-size check accompanies the change.

Was this score accurate? 👍 Yes · 👎 No

How this was scored →

Scored by GitVelocity · How are scores calculated?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants