debugging

star 13

Debug issues in the Second Brain Nuxt 4 + @nuxt/content v3 project. Use for any bug, test failure, or unexpected behavior.

alexanderop By alexanderop schedule Updated 3/15/2026

name: debugging description: Debug issues in the Second Brain Nuxt 4 + @nuxt/content v3 project. Use for any bug, test failure, or unexpected behavior.

Second Brain Debugging

Overview

This skill adapts systematic debugging for the Second Brain stack:

  • Nuxt 4 with Vue 3 Composition API
  • @nuxt/content v3 with SQLite and minimark format
  • @nuxt/ui v4 components
  • D3.js for knowledge graph visualization

Core principle: ALWAYS trace data flow before attempting fixes.

Stack-Specific Gotchas

Before debugging, internalize these common pitfalls:

Issue Symptom Cause
Empty graph edges Nodes show, no connections Missing .select('body') in query
Links not extracted Backlinks/graph empty Minimark parsed as object, not array
404 on content page Page not found Slug mismatch (/slug vs slug)
Stale backlinks Old connections shown useAsyncData cache not invalidated
Silent API failure Empty response, no error try-catch returns {} or []
Wrong mentions Unrelated content matched Title regex too broad
Graph crashes on filter D3 error after filtering Edge source/target type mismatch

The Four Phases

Phase 1: Identify the Layer

Data flows through these layers:

Content File (Markdown)
    ↓ Parsed by Nuxt Content
Minimark AST (body.value array)
    ↓ Queried via queryCollection
API Endpoint (server/api/*.ts)
    ↓ Returned as JSON
Vue Composable (useBacklinks, useMentions)
    ↓ Rendered in component
User Interface

First question: Which layer is broken?

  1. Content layer - Check frontmatter, markdown syntax
  2. AST layer - Check minimark structure: [tag, props, ...children]
  3. Query layer - Check .select('body'), path matching
  4. API layer - Check response structure, error handling
  5. Client layer - Check composable logic, reactivity

Quick diagnostic:

# Check if content is queryable
pnpm nuxi dev
# Visit http://localhost:3000/api/graph
# Empty edges? → Layer 2-3 issue
# Empty nodes? → Layer 1 issue
# Correct data but UI wrong? → Layer 4-5 issue

Phase 2: Trace Data Flow

For content/link issues:

  1. Check raw content file:

    • Frontmatter has title and type?
    • Wiki-links use correct format [[slug]]?
    • File in /content/ directory?
  2. Check minimark extraction:

    // In server/api/graph.get.ts, temporarily add:
    console.log("Body structure:", JSON.stringify(item.body, null, 2));
    // Verify: { type: 'minimark', value: [[...arrays...]] }
    // NOT: { type: 'minimark', value: [{...objects...}] }
    
  3. Check query selection:

    // Must explicitly select body:
    queryCollection(event, "content")
      .select("path", "stem", "title", "type", "body") // ← body required!
      .all();
    
  4. Check API response:

    curl http://localhost:3000/api/graph | jq '.edges | length'
    curl http://localhost:3000/api/backlinks | jq 'keys | length'
    

For graph visualization issues:

  1. Check nodes exist before filtering
  2. Check edge source/target types (string vs object after D3)
  3. Check filter state in URL query params

Phase 3: Hypothesis Testing

Form ONE hypothesis:

  • "The body isn't being selected because..."
  • "Links aren't extracted because minimark format is..."
  • "The cache is stale because..."

Test minimally:

# Run relevant tests first
vp test --project unit -- minimark  # For link extraction
vp test -- graph                    # For API issues

Add targeted logging:

// In extractLinksFromBody (server/utils/minimark.ts)
console.log("Body type:", body?.type);
console.log("Body value is array?", Array.isArray(body?.value));
console.log("First node:", JSON.stringify(body?.value?.[0]));

Phase 4: Fix and Verify

  1. Create failing test first:

    // tests/unit/utils/minimark.test.ts
    it("extracts links from nested minimark", () => {
      const body = {
        type: "minimark",
        value: [["a", { href: "/target" }, "Link text"]],
      };
      expect(extractLinksFromBody(body)).toContain("target");
    });
    
  2. Implement fix in ONE place

  3. Verify with full test suite:

    vp test
    vp check && pnpm typecheck
    
  4. If fix doesn't work after 3 attempts:

    • Question the architecture
    • Is the data model fundamentally sound?
    • Should slug normalization be centralized?

Quick Debugging Commands

# Run all tests
vp test

# Run specific test file
vp test --project unit -- minimark
vp test -- graph.nuxt

# Type check
pnpm typecheck

# Start dev server for manual testing
pnpm dev

# Check API responses
curl -s http://localhost:3000/api/graph | jq '.nodes | length'
curl -s http://localhost:3000/api/graph | jq '.edges | length'
curl -s http://localhost:3000/api/backlinks | jq 'keys'
curl -s "http://localhost:3000/api/mentions?slug=test&title=Test" | jq

Key Files by Subsystem

Content Pipeline

  • /content/*.md - Raw content files
  • /content.config.ts - Collection schema (title, type required)
  • /modules/wikilinks.ts - [[link]] to anchor transformation

Link Extraction

  • /server/utils/minimark.ts - Extract links from AST
  • Body format: { type: 'minimark', value: [...arrays...] }
  • Link format: ['a', { href: '/slug' }, 'text']

API Endpoints

  • /server/api/graph.get.ts - Nodes and edges for D3
  • /server/api/backlinks.get.ts - Reverse link index
  • /server/api/mentions.get.ts - Unlinked mentions search

Client Composables

  • /app/composables/useBacklinks.ts - Fetch backlinks
  • /app/composables/useMentions.ts - Fetch mentions
  • /app/composables/useGraphFilters.ts - Graph filter state

Pages

  • /app/pages/[...slug].vue - Content page
  • /app/pages/graph.vue - Knowledge graph

Common Fixes

"Graph shows nodes but no edges"

// Fix: Add .select('body') to query
queryCollection(event, "content")
  .select("path", "stem", "title", "type", "tags", "body") // ← ADD body
  .all();

"Links not being extracted"

// Check minimark format - must be ARRAY based
// Wrong: { tag: 'a', props: { href: '/' }, children: [] }
// Right: ['a', { href: '/' }, 'text']

// Fix extractLinksFromMinimark to handle arrays:
function extractLinksFromMinimark(node: unknown): string[] {
  if (!Array.isArray(node)) return [];
  const [tag, props, ...children] = node;
  // ...
}

"Stale backlinks after content edit"

// Force refresh with key
const { data: backlinks, refresh } = await useAsyncData(
  `backlinks-${Date.now()}`, // or add content hash
  () => $fetch("/api/backlinks"),
);

"Content page 404"

// Check slug normalization
// Route uses: /atomic-habits (with slash)
// queryCollection expects path: '/atomic-habits' (with slash)
// Backlinks use slug: 'atomic-habits' (no slash)

// Ensure consistent normalization:
const slug = route.path.startsWith("/") ? route.path : `/${route.path}`;

Red Flags - STOP

If you catch yourself:

  • Guessing which layer the bug is in
  • Adding fixes to multiple files at once
  • Skipping the test before fixing
  • Not checking minimark format
  • Assuming body is included by default

STOP. Return to Phase 1.

Install via CLI
npx skills add https://github.com/alexanderop/second-brain-nuxt --skill debugging
Repository Details
star Stars 13
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator