Project: 4th Brain — Developer’s Log, Feb 8, 2025
Added Support for Syncing Embedded Images
· Software development
Project: 4th Brain is a work-in-progress platform and plugin for Obsidian. Currently being developed with Supabase as its backend, this open-source project focuses on multi-channel publishing, standardized PKM patterns, and AI-augmented knowledge management.
In my previous log entry, I shared the GitHub repository for Project 4th Brain (an open-source Obsidian plugin being developed with a Supabase backend), and although the code is in its early stages with nothing yet ready for prime time, I made it public for transparency. I implemented the functionality for creating a new website (site entry) from within Obsidian and for publishing Obsidian markdown documents into it with document versioning supported. I am still focused on the networking and server storage; none of this can yet be served in a front-end website, but I’ll be getting to that part soon.
For context, and for those who don’t know, the first part of the 4th Brain platform being built is an open-source alternative to Obsidian Publish allowing you to host your own Obsidian-managed websites on your own Supabase server. This will enable you to run your sites on any cloud provider of choice or the Supabase cloud service. Initially, this will give people a foundation for building their own websites, using Obsidian as the content management client, with more website front-end customization capability than Obsidian Publish affords; a purely open-source solution that you can hack to your heart’s content.
Image Sync Support Added
Somewhere over the course of the week, I had an “Oh, shit!” moment when it suddenly occurred to me that I’d made no concession for the images embedded in your local vault’s markdown documents! Luckily, Supabase has support for File Storage, so I was able to implement that functionality today.
At first, I believed that if I wanted to extract the embedded images (attachments) from a markdown document, I’d first have to parse the document into an Abstract Syntax Tree (AST). I learned, however, that these embeds were already available in the cached metadata of the file…
const fileCache: CachedMetadata | null = this.app.metadataCache.getFileCache(file);
const embeds: EmbedCache[] = fileCache.embeds;
Uploading them to the sever bucket was not difficult, but honoring the goal to support multiple users and multiple sites on a single server was tricky. My solution in the end was to have a single file storage bucket on the server, with folders named with each site’s slug like so…
🪣 resources (bucket)
📂 site-1
📂 site-2
📂 site-3
Within each site, the path for each file mirrors the Obsidian vault path to the file.
Each site in the bucket is secured so that only the site owner can insert, update, and delete in their respective site folder. This is achieved with a special policy for each operation type (insert, update, delete) that ensures the authenticated user is the site owner for the bucket folder they’re operating in.
Next Steps
Now that we can sync both the markdown document and all attached images to the backend server from within Obsidian, I’m just back where I was before I remembered that I’d need to support syncing file attachments (DOH!). At this point, I’ve got a simple headless CMS with Obsidian as the client.
I’m eager to start working on the part that renders server data in a website.
I do not yet know if I will need to add a web server container to the Docker compose file (and use something like Java / Spring or Node.js) or if I can get away with using Supabase Edge Functions.
I’m closing with similar questions to those I had last week, in case you have an opinion to contribute:
- Should the site be generated into a static site for screaming-fast performance or should pages be queried at runtime and cached on the server?
- If an app server technology is used, what’s the ideal language for the server-side stuff? Java (e.g. Spring Boot), Node.js or Supabase Edge Workers?
- How will website keyword search be supported? Full-text search supported in the Postgres database or something like Apache Solr that might be more robust and better performing at scale?
Anyhoo…if you care to look at any of the code so far, these are the main three classes of interest:
- main.ts — the main Obsidian plugin file
- supabase-service.ts — the SupabaseService class
- init-supabase.sql — the script that creates the database tables, indexes, functions, and policies
If you’re interested in following along or contributing to the vision for this platform, you can:
💬 Contact me to share your thoughts and ideas
First published on Medium on .