Building Serverless Mind-Palace
A Blog and a Notion Alternative
I started working on this site after my resume/portfolio site. I realized it would be great to have a centralized place where someone could see the actual implementation of my projects or learn more about my work. For this site, I wanted to have a cool, distinct interface. I really liked the sleek color scheme that Claude uses, and I’m a big fan of turquoise. That’s why I ended up creating a design system that brings the two together.
Usually, I use Notion as a second brain to store information I need to come back to anything ranging from work notes, future plans, surveys over a new tech/tool, or just quick cheatsheets (which I call “Resources”). However, I started reading about potential data privacy concerns with hosted workspaces, and data security is something I have been leaning into recently. I wanted full ownership of my data without paying a subscription. This led to the idea of baking a secure “Vault” feature directly into this site.
Since I was building a secure vault and wanted to stick to this color palette, I went with a cyberpunk-inspired terminal theme that seamlessly transitions into a sleek, SaaS-like reader interface. It’s a quick, snappy website to showcase my public posts, but with a hidden, private backend serving as a personal, free alternative to Notion.
How It Works (The Architecture)
To give an overview of the implementation, the site avoids traditional backend servers (like Node.js or PostgreSQL) entirely. Instead, it relies on a hybrid architecture that splits the workload between the build step and the browser. Here are the layers making it happen:
- The Public Layer: I can just write standard Markdown files via Decap CMS or during the build process, Astro takes these files and compiles them into ultra-fast, static HTML pages. No database queries! No loading spinners, just raw static speed :D
- The Private Layer: This is where things get interesting. Before Astro even touches the code, a Python script (
encrypt_vault.py) runs in my GitHub Actions pipeline. It scans a specific/vaultdirectory containing my private Markdown files. Instead of turning these into HTML, it takes the raw text, generates a random cryptographic salt, and encrypts everything using AES-256-GCM and a PBKDF2 key derivation function. It then bundles all these encrypted files along with their hierarchical parent-child relationships into a singleencrypted.jsonfile.
- GhostTerminal & The Amnesia Protocol: To actually read my vault, I don’t go to a separate login page. I built hidden triggers directly into the UI. Regardless of the device, I can tap a specific invisible sector on the screen three times (or hit
Shift + Alt + V), and a sleek authentication modal elegantly blurs the background and prompts me for access.
// GhostTerminal.jsx - The Secret Trigger
const handleSecretTrigger = (e) => {
e.preventDefault();
if (terminalState === 'unlocked') return; // Do nothing if already in
const newCount = clickCount + 1;
setClickCount(newCount);
// Reset the counter if a second passes between clicks
if (clickTimeout.current) clearTimeout(clickTimeout.current);
clickTimeout.current = setTimeout(() => setClickCount(0), 1000);
// If 3 rapid clicks are detected, trigger the modal for master key
if (newCount >= 3) {
setClickCount(0);
setTerminalState('prompting');
}
};
Once the modal prompts me, I enter my master password. The browser uses the native WebCrypto API to hash my input against the salt stored in the JSON file. If it matches, the vault unlocks and I am dropped into the “Datapad”.
The Datapad is a custom React interface that features a hierarchical Explorer sidebar (grouping logs and resources under their parent projects) and a dynamic, floating Table of Contents that tracks my reading progress.
The coolest part is what I call the Amnesia Protocol. The decrypted markdown files are never saved to the hard drive or localStorage. They exist purely in the browser’s volatile sessionStorage.
// A snippet of the decryption routine
const decryptedBuffer = await window.crypto.subtle.decrypt(
{ name: "AES-GCM", iv },
key,
ciphertext
);
const decoded = new TextDecoder().decode(decryptedBuffer);
// Save strictly to volatile RAM.
sessionStorage.setItem('volatileRamLogs', decoded);
The moment I close the browser tab, the memory is wiped clean. The data ceases to exist in a readable format until I trigger the terminal and enter the password again.
Miscellanies updates
The site after creation went through a UI update. this stemmed from the need to have a separate place for holding the resources. I wanted to store lookup information that I tend to usually search every once in a while.
While I was doing this I ended up having an update to the site which allows a datapad like configuration which has a much more cleaner UI/UX for traversing the content
Deep Dive Log: Nuances about how the optimization was done and what were the new updates
Engineering Trade-offs
No system is perfect, and building a serverless vault requires accepting a few specific architectural trade-offs:
- The Payload Size (JSON Bloat): Because the database is just a flat JSON file, the Python script bundles every single vault log into one payload. Right now, downloading a few megabytes of encrypted text takes milliseconds. But if this vault scales to
10,000entries, then the browser would have to download a massive file just to read a single note. For a personal site, this limit is acceptable, but it wouldn’t work for a large-scale SaaS app. - Client-Side Vulnerabilities: The cryptography sitting on the GitHub repository is practically bulletproof. However, because the decryption happens inside the browser’s DOM, the text is theoretically vulnerable to malicious browser extensions installed on my local machine. It relies on the local environment being secure.
Conclusion
What started as a simple portfolio site evolved into a fully autonomous, serverless mind-palace. By combining Astro’s static generation speeds with React’s dynamic client-side rendering and wrapping it all in a Python-powered cryptographic build step, I ended up with a system that gives me the best of both worlds. All of this while looking cool :D
As for anyone on the internet? They can browse my projects, resources, and standard blog posts instantly, while I retain a mathematically secure, entirely free workspace hidden just beneath the surface. No databases to manage, no monthly server costs, and total ownership over my data.