Fixed Build Errors in Digital Garden

Today I fixed several critical build errors in the digital garden:

The main issue was that multiple files were trying to write to the same output path (dist/file/index.html). This was happening because several notes had permalink: /file/ in their frontmatter, even though they were marked as not published (dg-publish: false):

This suggests that unpublished notes were still being processed during the build, which shouldn't happen. The fix addresses both the permalink conflict and ensures proper handling of unpublished notes.

The Fix

Modified notes.11tydata.js to implement a smarter permalink generation system:

  1. Files in subdirectories keep their structure:

    if (filePath.includes('/rangerschool/')) {
      return `/rangerschool/${fileName}/`;
    }
    
  2. Files are categorized by their suffix:

    • CY -> /cybersecurity/
    • RS -> /rangerschool/
    • AI -> /ai/
    • linux -> /linux/
  3. Frontmatter permalinks are only used if they:

    • Are not /file/ (which was causing conflicts)
    • End with a slash (for consistency)
  4. All other files default to /notes/filename/

2. Async Template Issues

Fixed an error with Eleventy's template processing:

Unfortunately you're using code that monkey patched some Eleventy internals and it isn't async-friendly. Change your code to use the async `read()` method on the template instead!

The Fix

  1. Made graph generation properly async in graph.js
  2. Added proper null checks for data objects
  3. Improved error handling throughout the permalink generation

3. Code Organization

The permalink generation code is now more robust:

permalink: (data) => {
  // Handle undefined data
  if (!data || !data.page) {
    console.warn('Data or page object is undefined');
    return '/notes/undefined/';
  }

  // Handle garden entry
  if (data.tags && data.tags.indexOf("gardenEntry") != -1) {
    return "/";
  }

  // Get file info
  const filePath = data.page.filePathStem || data.page.inputPath || '';
  const fileName = path.basename(filePath).replace(/\.md$/, '');
  
  // Category-based routing
  if (filePath.includes('/rangerschool/')) return `/rangerschool/${fileName}/`;
  if (fileName.endsWith('CY')) return `/cybersecurity/${fileName}/`;
  if (fileName.endsWith('RS')) return `/rangerschool/${fileName}/`;
  if (fileName.endsWith('AI')) return `/ai/${fileName}/`;
  if (fileName.match(/linux$/i)) return `/linux/${fileName}/`;

  // Valid frontmatter permalinks
  if (data.permalink && 
      data.permalink !== '/file/' && 
      data.permalink.endsWith('/')) {
    return data.permalink;
  }

  // Default case
  return `/notes/${fileName}/`;
}

4. Unpublished Notes Fix

Fixed the issue with unpublished notes being processed during the build. Modified collections.js to properly filter out notes with dg-publish: false:

function sortNotes(collection) {
  return collection.getFilteredByTag("note")
    // Filter out unpublished notes
    .filter(note => {
      // Check if note should be published
      const shouldPublish = note.data['dg-publish'] === true;
      if (!shouldPublish) {
        console.log(`Skipping unpublished note: ${note.filePathStem}`);
      }
      return shouldPublish;
    })
    .sort((a, b) => {
      // Sort daily notes by date
      // ... rest of sorting logic ...
    });
}

This ensures that:

  1. Only notes with dg-publish: true are included in the build
  2. Unpublished notes are logged for debugging
  3. The permalink conflicts are prevented at the source

Results

Pasted image 20250406001947