Do folder notes to work on Obsidian Publish?

I can’t seem to get folder notes to work on Obsidian Publish pages.

I thought folder notes would function like index pages on Obsidian Publish pages, so that clicking on a folder in the sidebar would open the corresponding folder note (in the main browser pane). For example, if I have a folder named “2024” and the enclosed folder note is named “2024.md”, clicking on the folder would open the note. It does on the desktop app (1.7.7, MacOS) but not in a browser.

Am I misunderstanding? Is there some setting I’m missing? Thanks much!

Publish doesn’t run plugins, which is required for the click-folder-to-open-note behavior to work. Publish limitations - Obsidian Help

Good to know, and thank you. But that doesn’t mean either (a) that a folder note couldn’t function like an index file in a web directory, or (b) that there isn’t another way to do it. So let me rephrase: I’d really like to find a way to do that on the web. Thanks!

The folder note itself is just a note and will work like any other note. You can still structure your notes and folders in an index-like way. The only thing not working is clicking on the folder in the sidebar to load the note. There may be some other way to achieve the effect, but I don’t use Publish so don’t know the options.

1 Like

FYI. I’m using a custom domain for my Obs Publish site, so custom javascript is an option. I used the app Cursor to generate a JS that :point_right:t3: loads the folder note like an index page :point_left:t3:: click on a folder n the sidebar and the folder note loads. VERY cool. This is probably some serious spaghetti code, and it may include some workarounds related to a few other weird things my mite does. One issue I wasn’t able to solve is that when a folder note loads, it seems to reload the whole page, resulting in a reload “flash” — not great. But hopefully this can be useful for someone else to build on. Code follows:

/**
 * Auto-expand Obsidian Publish graph viewer with error handling
 */
(function() {
    // Check if we're on the start page (multiple possible paths)
    const path = window.location.pathname;
    const isStartPage = path === '/start_here' || 
                       path === '/start_here/' || 
                       path === '/' ||
                       path === '';
    
    if (!isStartPage) {
        console.log('Not on start page:', path);
        return; // Exit early if not on start page
    }

    console.log('On start page, initializing graph expansion');

    // Add CSS to hide label and adjust positioning
    try {
        const style = document.createElement('style');
        style.textContent = `
            .site-body-left-column,
            .site-body-right-column {
                font-family: "Atkinson Hyperlegible", sans-serif !important;
            }
            .markdown-preview-view {
                font-family: "Hoefler Text", Georgia, serif !important;
                transition: opacity 0.1s ease-out !important;
            }
            h1, h2, h3, h4, h5, h6 {
                font-family: "Atkinson Hyperlegible", sans-serif !important;
            }
            .published-section-header {
                display: none !important;
            }
            .graph-view-container {
                margin-top: 100px !important;
            }
            .extra-title {
                z-index: 9999 !important;
                position: relative !important;
                background: var(--background-primary) !important;
            }
            /* Icon styles - catch all SVGs */
            .svg-icon {
                color: var(--text-muted) !important;
                stroke: var(--text-muted) !important;
            }
        `;
        document.head.appendChild(style);
    } catch(e) {
        console.error('Style injection failed:', e);
    }

    function clickExpandButton() {
        try {
            const expandButton = document.querySelector('.graph-expand');
            const globalButton = document.querySelector('.graph-global');
            
            if (expandButton && globalButton) {
                console.log('Found buttons, attempting clicks...');
                globalButton.click();
                expandButton.click();
                return true;
            }
            console.log('Buttons not found yet');
            return false;
        } catch(e) {
            console.error('Click attempt failed:', e);
            return false;
        }
    }

    let attempts = 0;
    const maxAttempts = 20;
    
    function tryExpand() {
        if (attempts >= maxAttempts) {
            console.log('Max attempts reached');
            return;
        }
        
        if (!clickExpandButton()) {
            attempts++;
            requestAnimationFrame(tryExpand);
        }
    }

    // Wait for DOM to be ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(tryExpand, 100);
            setTimeout(tryExpand, 500);
            setTimeout(tryExpand, 1000);
        });
    } else {
        setTimeout(tryExpand, 100);
        setTimeout(tryExpand, 500);
        setTimeout(tryExpand, 1000);
    }
})();

/* ADDED TB 24-11-18-21:20hrs*/
/* https://forum.obsidian.md/t/customize-powered-by-obsidian-on-graph-view/47261/8 */

function setupGraphSettings() {
    if (app && app.graph && app.graph.renderer) {
        app.graph.renderer.hidePowerTag = true;
        console.log('Graph settings successfully applied.');
    } else {
        console.log('Graph renderer still not available, retrying in 10ms...');
        setTimeout(setupGraphSettings, 10); // Retry after 10ms
    }
}

// Initial call to setupGraphSettings
setupGraphSettings();


/* ADDED 241120-1306hrs */
// Folder note functionality
(function() {
    // Add transition styles
    const style = document.createElement('style');
    style.textContent = `
        .publish-renderer {
            transition: opacity 0.1s ease-out;
            opacity: 1;
        }
        .publish-renderer.transitioning {
            opacity: 0;
        }
    `;
    document.head.appendChild(style);

    function initFolderNoteHandler() {
        console.log('Attempting to initialize folder note handler');

        const navView = document.querySelector('.nav-view');
        console.log('Nav view found:', !!navView);

        if (!navView) {
            console.log('Could not find nav view');
            return false;
        }

        function handleFolderClick(event) {
            // Ignore clicks on collapse icons or links
            if (event.target.closest('.collapse-icon') || event.target.closest('a')) {
                return;
            }

            const treeItem = event.target.closest('.tree-item-self.mod-collapsible');
            if (!treeItem) {
                console.log('Not a folder click');
                return;
            }

            const folderPath = treeItem.getAttribute('data-path');
            console.log('Clicked folder path:', folderPath);

            if (!folderPath) return;

            // Prevent default behavior
            event.preventDefault();
            event.stopPropagation();

            const folderNotePath = `${window.location.origin}/${folderPath}/${folderPath.split('/').pop()}`;
            console.log('Checking for note at:', folderNotePath);

            fetch(folderNotePath, { method: 'HEAD' })
                .then(response => {
                    console.log('Fetch response:', response.status);
                    if (response.ok) {
                        console.log('Found folder note, navigating...');
                        // Add transition class
                        const content = document.querySelector('.publish-renderer');
                        if (content) {
                            content.classList.add('transitioning');
                            // Wait for transition to complete before navigating
                            setTimeout(() => {
                                window.location.href = folderNotePath;
                            }, 100); // Reduced from 150ms to 100ms
                        } else {
                            window.location.href = folderNotePath;
                        }
                    }
                })
                .catch(error => {
                    console.log('Fetch error:', error);
                });
        }

        navView.addEventListener('click', handleFolderClick);
        console.log('Click handler attached to nav view');
        return true;
    }

    // Initialize immediately
    if (!initFolderNoteHandler()) {
        let attempts = 0;
        const maxAttempts = 10;
        const interval = setInterval(() => {
            console.log('Retrying folder note handler initialization...');
            if (initFolderNoteHandler() || attempts >= maxAttempts) {
                clearInterval(interval);
            }
            attempts++;
        }, 1000);
    }

    // Add fade-in on page load
    document.addEventListener('DOMContentLoaded', () => {
        const content = document.querySelector('.publish-renderer');
        if (content && content.classList.contains('transitioning')) {
            content.classList.remove('transitioning');
        }
    });
})();