Move setActiveTabPath after tab content is loaded to prevent Editor's
useEffect from firing before the tab exists in the tabs array. Add
try/catch around editor.replaceBlocks for defensive error handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace per-tab BlockNote instances with one shared editor that swaps
content via replaceBlocks(). Cached blocks per tab path make subsequent
switches instant — only first open parses markdown. Cache entries are
cleaned up when tabs close.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of unmounting/remounting BlockNoteTab on every tab switch
(via key={activeTabPath}), render all open tabs simultaneously and
toggle visibility with CSS display:none/block. This eliminates
editor recreation and markdown re-parsing on switch. Also adds a
loading skeleton for new tabs and uses a ref for tabs to avoid
stale closures in handleSelectNote.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add requestAnimationFrame throttling to ResizeHandle so mouse move
events are batched per frame instead of triggering setState on every
pixel. Wrap Sidebar in React.memo so it skips re-rendering when only
the parent wrapper div width changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap Editor in React.memo to prevent re-renders from parent width
changes. Memoize the base wikilink items array with useMemo so it
only recomputes when entries change, not on every keystroke.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace plain .map() rendering with Virtuoso for virtual scrolling of
9000+ notes. Add useMemo to all filtering/sorting chains (filtered,
sorted, searched, typeCounts, displayed). Use entry.snippet directly
instead of computing snippets from allContent. Wrap NoteList in
React.memo to prevent unnecessary re-renders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add snippet: string to VaultEntry TypeScript interface to match the
Rust backend. Update mock data with snippets for all entries. Add
.laputa-cache.json to .gitignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add VaultEntry.snippet field (first ~160 chars of content, markdown-stripped).
Implement scan_vault_cached() with git-based incremental caching:
- Writes .laputa-cache.json to vault dir
- On same HEAD: returns cached entries + uncommitted new files
- On different HEAD: re-parses only changed files via git diff
- Falls back to full scan when git unavailable or cache corrupt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use titleBarStyle: Transparent for native window frame on top
- Add paddingTop: 38px to Sidebar to make room for title bar
- Keep solution simple: native traffic lights + dragging work out-of-the-box
- Removed custom traffic lights and drag handlers
- Detect new components added (frames with names)
- Detect components removed
- Detect height/structural changes
- Add high-priority layout tasks
Now catches additions like macOS title bar that were previously missed.
- Detect design patterns (color-coding systems, contrast improvements, spacing)
- Analyze design intent and explain **why** changes were made
- Add critical warnings for dynamic implementations (e.g., color-coding must be type-based, not hardcoded)
- Include intent analysis in output for Claude Code
This helps Claude Code understand the **system** behind changes, not just apply spot modifications.
- Note 1: 'modern stack...' → 'modern stack and updated visual language...'
- Note 2: 'hiring priorities...' → 'hiring priorities with the engineering team leads...'
Changes are cosmetic mockup text only, no code implementation needed.
- Check for CodeScene in ~/.claude/mcp.json (MCP setup)
- Fallback to ~/.codescene/token (CLI setup)
- Now works with standard Claude Code + CodeScene MCP
- Add .git/hooks/pre-commit with CodeScene integration
- Warns on large file changes (>500 lines)
- Suggests Claude Code + MCP for detailed analysis
- Bypassable with --no-verify or [skip codescene]
- Add .github/HOOKS.md documentation
- CodeScene doesn't have an official GitHub Action
- Use local CodeScene CLI or MCP tools instead
- Other checks (tests, coverage, lint, docs) still enforced
- Empty state rendering with keyboard shortcut hints
- Tab bar rendering and switching between tabs
- Close tab interaction
- Breadcrumb bar with note type, title, and word count
- New note button in tab bar
- BlockNote editor rendering
- Modified indicator and diff toggle button
- Inspector panel integration
- Renders four-panel layout with sidebar, note list, editor
- Loads and displays vault entries from mock data
- Shows empty state when no note is selected
- Keyboard shortcut Cmd+S shows toast
- Verifies default sidebar selection (All Notes)
- Remove Sidebar tests for removed elements (app title, search bar)
- Update Inspector tests: header is now 'Properties' not 'Inspector'
- Fix status pill test to check inline styles instead of old CSS class
- Update relationship tests to use frontmatter-based rendering
- Fix 'no relationships' test to use content without relationship keys
- Fix editor scroll (min-height: 0 + overflow)
- Properties panel extends full height
- Moved Diff button to git-branch icon in breadcrumb bar
- Minor CSS fixes for app layout
- Remove .dark CSS variables block from index.css
- Remove theme toggle state and Cmd+Shift+T shortcut from Sidebar
- Remove dark class initialization from main.tsx
- Hardcode BlockNote theme to 'light' in Editor
- shadcn dark: classes left in place (harmless, no-op without .dark class)
Install Tailwind CSS v4 + shadcn/ui with Radix UI primitives. Migrate all
UI components (Sidebar, NoteList, Editor tabs, Inspector, dialogs, palette)
from BEM CSS to Tailwind utility classes and shadcn components (Button,
Input, Dialog, Badge, etc.). Map theme system to shadcn CSS variables while
preserving BlockNote editor styles untouched. Remove 8 old CSS files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>