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!
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.
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 loads the folder note like an index page : 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');
}
});
})();