feat: comprehensive audit, design system, UX, and product improvements#208
feat: comprehensive audit, design system, UX, and product improvements#208tomymaritano merged 185 commits intomainfrom
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Notebooks now sync before notes in syncNow() to ensure note-notebook dependencies are satisfied. Adds pullNotebooks/pushNotebooks methods and applyRemoteNotebookChange for bidirectional notebook sync. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move validateNotebookTree from inline test definition to a shared module so it can be reused by the API route and other consumers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add conflict state to SyncStatusIndicator with amber warning icon and count. Conflicts now take priority over idle state so users discover them without navigating to Settings. Also export ConflictResolver from sync components barrel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DatabaseConnection.transaction() already calls the inner fn — no need for extra () at call site. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix pullNotebooks() to only advance cursor to last successfully applied change (prevents skipping failed changes on retry) - Fix tree validation snapshot to properly exclude deleted notebooks (prevents ghost parent references in validation) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add bidirectional notebook sync
test: add sync-core unit tests (62 tests)
feat: surface sync conflicts in status indicator
# Conflicts: # apps/desktop/src/main/services/apiClient.ts # apps/desktop/src/main/services/syncService.ts # packages/api/src/db/schema.ts # packages/api/src/routes/sync.ts # packages/storage-sqlite/src/migrations/index.ts
feat: add bidirectional tag sync
Configure automated code review with path-specific instructions for core, storage, desktop, and API packages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ration Add optional metadata (name, version, priority) to registerRemarkPlugin and registerRehypePlugin signatures for debugging and execution ordering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…improvements
Design System:
- Add Button primitive (primary/secondary/danger/ghost variants, loading state)
- Add Toast notification system (success/error/info/warning, auto-dismiss)
- Add Modal pattern (glass effect, portal, escape/overlay close)
- Add typography tokens (font-weight, line-height, letter-spacing)
UX Improvements:
- Add save indicator in editor ("Saving..." → "Saved")
- Flush pending saves on window close (prevent data loss)
- Show toast notifications for plugin install/uninstall/toggle
- Humanize AI error messages (raw codes → actionable user guidance)
- Add settings "Reset to Defaults" button in sidebar
- Add update notification banner at top of app window
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design System: - Replace ~60 hardcoded spacing values with --space-* tokens across 14 CSS modules - Consolidate 30+ ad-hoc button styles to Button primitive in all settings sections - Migrate AiSection inline styles to CSS module classes UX Features: - Add welcome screen for first-run onboarding with feature highlights - Add sync progress indicator in sidebar footer (pending count, status, retry) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search: - Add collapsible filter bar with status pills (All/Active/On Hold/Completed/Dropped) - Add tag filter dropdown populated from existing tags - Add sort controls (by title/created/updated, asc/desc) - Filter toggle button with active count badge Plugin Marketplace: - Wire BrowseTab to fetch plugins from API (https://api.readied.app/plugins) - Graceful offline fallback to static built-in list with notice - Add plugins:installFromUrl IPC handler (download + extract + validate) - Install button with loading state, toast feedback - Cross-reference installed plugins to show "Installed" badge - Auto-refresh installed tab after marketplace install Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tables: - Add comprehensive table CSS (tables.css) for editor/preview parity - Style WYSIWYG editor tables identical to preview (tokens, stripes, hover) - Style insert-table modal with glass effect and accent grid selection - Style sortable table headers with sort indicators - Add overflow-x:auto for wide tables, row hover effects - Remove hardcoded text-align so GFM alignment markers work Export: - Add YAML frontmatter to exported markdown (title, dates, tags, id) - Add per-note file export command (Cmd+Shift+E → save dialog) - Improve HTML clipboard conversion: tables, blockquotes, ordered lists, images, horizontal rules - Add data:exportNote IPC handler with save dialog Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # apps/desktop/package.json # pnpm-lock.yaml
Security: - Fix YAML frontmatter backslash escaping (CodeQL critical) - Validate plugin IDs with regex + path traversal check (P1) - Fix PowerShell path interpolation to use separate args - Add 50MB size limit and try/finally cleanup to installFromUrl - Fix semver regex to accept build metadata Accessibility: - Welcome screen: role=dialog, aria-modal, aria-labelledby, Escape handler - Modal: aria-labelledby, focus on open, tabIndex - Toast: aria-live=assertive for errors, polite for others - Welcome Skip button uses Button primitive UX fixes: - Save indicator no longer flashes on note switch (track noteId) - UpdateBanner handles download errors with retry - UpdatesSection installNow wrapped in try/catch - Welcome copy updated: "Local-First" instead of "Offline Forever" - Hero play overlay hidden when no video URL Code quality: - CSS keyframes renamed to kebab-case (Stylelint) - MagicLinkFlow border-radius uses --radius-xl not --space-4 - Button.module.css currentcolor lowercase - Toast word-break → overflow-wrap - .env.example with parser-safe placeholders - NoteListFilterBar unmount guard + error handling - SidebarFooter prevStatusRef always updated - PluginsSection slug/id matching improved - Stripe timestamp NaN guard - source.ts import order fixed - Test improvements (consistent patterns, comments) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oad) Security hardening: - encryptionService: enforce minimum 100k PBKDF2 iterations - encryptionService: validate hex strings before Buffer.from() - preload: validate HTTPS-only URLs for plugin install - preload: guard log:write against non-string payloads Sync/encryption: - syncService: emit status event when encryption not ready (UI visibility) - apiClient: add explicit type generics to all E2EE request calls CI: - ci.yml: add contents:read permission to label job Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix mcp-server TS2532 errors from noUncheckedIndexedAccess (optional chaining on regex matches) - Restructure ESLint config: type-aware rules only for src/ files in tsconfig projects - Ignore incomplete ai-assistant package - Result: 0 lint errors, 32 warnings (all non-blocking) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Main process: - exportNote: async writeFile, Unicode-safe filename sanitizer - plugins:install: tmpDir cleanup via finally block - plugins:installFromUrl: slug validation, URL parsing, JSON guard Renderer: - NoteListFilterBar: aria-pressed on pills, error logging in tags fetch - NoteEditor: guard saved flash against note switch (trackedNoteIdRef) - Welcome: auto-focus primary button on mount - UpdateBanner: include error message in UI, check startDownload result - SidebarFooter: "Synced Xm ago" display, subscribe to lastSyncAt - Modal: useId() for unique aria-labelledby - Toast: conditional role (alert vs status) Plugins & export: - PluginsSection: error toast on failed install/uninstall, validate API response - Section.module.css: rename plugin-spinner to pluginSpinner (camelCase) - exportMarkdown: escapeHtml in tables, escapeYamlScalar in frontmatter, async clipboard handlers - Button.module.css: danger hover uses color-mix tokens - Hero.tsx: non-interactive wrapper when no video URL Other: - .env.example: inline comments moved to own lines - bump-version.js: stricter semver regex Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # .env.example # apps/desktop/src/main/index.ts # apps/desktop/src/renderer/components/NoteEditor.tsx # apps/desktop/src/renderer/components/NoteListFilterBar.tsx # apps/desktop/src/renderer/components/UpdateBanner.tsx # apps/desktop/src/renderer/components/Welcome.tsx # apps/desktop/src/renderer/components/sidebar/SidebarFooter.tsx # apps/desktop/src/renderer/pages/settings/sections/PluginsSection.tsx # apps/desktop/src/renderer/pages/settings/sections/Section.module.css # apps/desktop/src/renderer/plugins/exportMarkdown.ts # apps/desktop/src/renderer/ui/patterns/Modal.tsx # apps/desktop/src/renderer/ui/primitives/Button.module.css # apps/desktop/src/renderer/ui/primitives/Toast.tsx # apps/web/components/landing/Hero.tsx # pnpm-lock.yaml # scripts/bump-version.js
## Summary - Add explicit rule: never push directly to `develop` or `main` - Add instruction for Claude Code to always create feature branches - Add "always branch from develop" and "clean up after merge" to hygiene rules 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **No user-facing changes** * Internal documentation update to development workflow and branch governance guidelines. This does not affect end-user functionality or features. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary Fixes two review findings from PR #198: - **P1**: Move `useId()` above early return in Modal to prevent React hook order violation - **P2**: Remove strict slug/id equality check in `plugins:installFromUrl` — marketplace slug and manifest id are independent identifiers ## Test plan - [x] `pnpm typecheck` — 17/17 pass - [x] `pnpm test` — 16/16 pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary Addresses P1 review finding from PR #200 and strengthens git flow rules. ### Plugin Install - Add cross-plugin overwrite protection: when marketplace serves wrong bundle (manifest.id ≠ requested slug), block only if it would overwrite an existing plugin directory — prevents silent overwrites without blocking valid installs where slug and manifest ID legitimately differ ### CLAUDE.md - Add explicit step-by-step workflow for Claude Code - Add explicit NEVER list (no direct commits to develop/main) ## Test plan - [x] `pnpm typecheck` — 17/17 pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced plugin installation safety to prevent accidental overwrites of existing plugins during installation from URL. * **Documentation** * Updated development workflow documentation and branch protection requirements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary Resolves merge conflicts between main and develop for the release PR #202: - `apps/desktop/src/main/index.ts`: Keep develop's cross-plugin overwrite protection (smarter than main's strict equality check) - `apps/desktop/src/renderer/ui/patterns/Modal.tsx`: Keep develop's useId() placement above early return (React hook order fix) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary Fixes all 12 review comments from PR #202 (CodeRabbit + Codex). - **NoteEditor**: Remove `note?.id` from save effect deps (P2 — prevents false "Saved" flash) - **exportNote**: Reject Windows reserved filenames (CON, PRN, AUX, etc.) - **installFromUrl**: Return `slugMismatch` in success response for UI awareness - **SidebarFooter**: 60s interval refresh for "Synced Xm ago" staleness - **UpdateBanner**: Fix optional error type + "Download failed: Download failed" duplication - **PluginsSection**: Add `slug` to marketplace response validation - **Section.module.css**: Keyframe `pluginSpin` → `plugin-spin` (stylelint) - **Toast**: Remove nested `aria-live` from container (spec compliance) - **tsconfig.json**: `jsx: "preserve"` for Next.js (was "react-jsx") - **.env.example**: Reference to CLAUDE.md for setup docs ## Test plan - [x] `pnpm typecheck` — 17/17 pass - [x] `pnpm test` — 16/16 pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Fixed handling of Windows reserved filenames in exports * Download failures now display specific error messages instead of generic text * Improved validation when installing marketplace plugins * Sync timestamp display now updates periodically * Enhanced accessibility for toast notifications <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary Merges main into develop to resolve all conflicts so PR #202 (release) can merge cleanly. All 5 conflicts resolved keeping develop's version (which has all review fixes from PRs #199-#204). ## Test plan - [x] `pnpm typecheck` — 17/17 pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 29 minutes and 16 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (10)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f8cec67549
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Block install when manifest.id !== pluginSlug regardless of whether the plugin already exists on disk — prevents silently installing the wrong plugin on first install from marketplace. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Release Summary
Major release with all review findings resolved and conflicts synced.
Highlights
Test plan
pnpm typecheck— 17/17 passpnpm test— 16/16 passpnpm lint— 0 errors🤖 Generated with Claude Code