[2025 Retrospective]
This project from 2023 captures my mindset after extensive use of my v2 note-taking app and gaining valuable experience at an educational startup.
What I Would Do Differently Now:
- Implement a landing page explaining the features, common questions and a quick start to helps users discover a valuable app.
- Think like real users (not developer) to improve the UX becoming more accessible.
- Manage Errors in more friendly way to allow the user understand why is it failing (this only in case it fail, I alway keep in mind the quality)
This post is preserved as a snapshot of my growth. Follow the journey to v1, v2 and v4.
The Opportunity
I have been using my note-taking app v2 Palace App extensively, and I have identified several areas for improvement:
- Lack of Offline Access: The app was useless without an internet connection.
- Authentication Complexity: Implementing custom authentication from scratch is brittle and introduces unnecessary security risks.
- Inefficient Note Organization: Grouping in tags is not useful, it adds another step to create the note, the tree structure is a natural way of grouping notes.
- Payment Issue: I was very busy and forgot to pay for my server for a month. It was deleted, and I lost all my notes 😭.
The design - Part 1
I was reflecting a lot on authentication. I decided to use Google Authentication to simplify the user’s workflow. With just one click, the app would save notes on their Google Drive. This would give the responsibility for the notes to the user, in case I forgot to pay the server again.
In my last job, I was fascinated with the big knowledge graph we drew, so I wanted to have that same view for my notes.
I thought there could be a more efficient way to draw the graph than using Dagger. I started my investigation and found a way to draw with repulsion forces from physics. I found other libraries that were wrappers of other libraries, and only God and their creators know how they work inside. I discovered drawing graphs in SVG, which looks amazing, but there was no way to create my HTML notes inside them. Other libraries used WebGL with Three.js, allowing me to draw a massive amount of items, but I didn’t have full control of the UI. Then I started reading about the possibilities of drawing with Canvas and discovered WebGPU. Finally, I read about how Figma efficiently draws its graphics.
After all that, I came to a conclusion:
there is no single efficient and flexible library to draw graphs. The best solution would be to build my own algorithm based on Sugiyama as a pipeline (declarative programming) to understand how the data moves and make it easy to modify. Then, I would write tests for multiple cases. Once everything worked, I would move the algorithm to Rust with WebAssembly. Finally, for the best efficiency, I would create a library to transform the Markdown AST into Canvas API graphics. If I had enough time and resources, I would even create the library with WebGPU. With great engineering, I think I could draw millions of HTML nodes.
Design of new improvements over Palace App
The design - Part 2
But let’s return to the principles (KISS, YAGNI, MVP). I was keen to use the app soon, and I knew that WebGL/WebGPU would be very time-consuming. While following the MVP approach and looking for a better way to display notes in a tree structure, new concerns came up:
How could I avoid server costs? Forgetting to pay for the server could lead to my containers being removed, impacting both me and other users. Preferring long-term simplicity, I found a way to save notes in the browser: IndexedDB.
The advantages were huge:
- The user is responsible for their own notes.
- Notes are accessible offline.
- Server expenses are eliminated.
So, the app doesn’t rely on APIs, databases, or authentication. This became my great long-term strategy. It’s a decentralized note-taking app 🎉, and that prompted a new logo.

Finally, I expressed these ideas in a new design.
The Implementation in Frontend
I took the best engineering parts from my Palace App, like Clean Architecture, Functional Programming, Storybook, and React with Next.js. Then, I added Trophy testing, which focuses on testing the essentials. It starts with ESLint, Prettier, and typing, then continues with the classic testing pyramid, but always remembering to focus on the essentials and avoid a fake 100% coverage.
First, I set up IndexedDB to save my notes. Then, I created my Sidebar component to display notes in a tree structure, my preview component to display the note enriched with Markdown, and the edit component with a powerful editor based on what Notion uses. I chose Slate.js and created a basic preview-on-edit mode, with serialization to save to IndexedDB.
Next, I needed to make it a Progressive Web Application (PWA). I tried to use a Next.js plugin to set up the service worker. I defined my cache strategy (cache first, with the server as a fallback), so the HTML, JS, and CSS would come from the cache. Only the notes would come from IndexedDB. But the plugin was not working correctly. I researched a lot but found no issues related to my problem in its repository. I read the README completely and noticed it was only a wrapper for Workbox. I went to study the Workbox documentation, but in their latest changes, they removed the cache strategies. But why? If that is essential, should I work with an old version? Should I continue researching and try to force a solution?
That complication gave me a valuable reflection:
Not all libraries from the internet have good quality. That’s the reason it’s better to keep improving my fundamentals (HTML, CSS, JS, and React) instead of adding libraries without understanding the real problem. It reminded me of my last job, where there were re-render issues and unpredictable behavior. I explained why that happened and how to avoid it (e.g., ignoring the dependency array from useEffect, which should be an error, not a warning; calling setState inside another setState, etc.). I feel it doesn’t matter how many years of experience or titles you have if you don’t understand the fundamentals and the philosophy behind the technology. You can break the rules, but only if you understand them first.
Based on this experience and my good understanding of the Service Worker lifecycle, React lifecycle, and Next.js hydration, I decided to set up the service worker from scratch, without libraries. This was a great decision in the long term. It gave me flexibility, helped me continue improving my JS skills, and means I won’t spend time figuring out issues or looking for another library when I need to set up a service worker in another technology.
Then, I set up my manifest, tested locally with an SSL server, installed the PWA, and verified that my entire workflow was correct. Finally, I created my CI/CD pipeline and launched 🚀.
Final Words
This project brought a storm of ideas, forcing me to find a balance between innovation and MVP, which is a powerful skill. Imagine you create a new product: without innovation, it is only a copy; without a good MVP, you need more investment.
On the other hand, I hear a lot about decentralization. I think this application is another insight into decentralization. I’m offering the same value without a backend, without a remote DB, offline, completely private, and saving an expense of $72 per year on a server!
In this project, I didn’t use libraries to manage state because I gained a deeper understanding of React’s lifecycle and its philosophy, and the same for my JavaScript skills. This mindset helped me build my profile as a T-shaped Software Engineer.
So, what is next? I have to tell you, this version is the most stable, and I haven’t created another one from scratch. So, did I stop here? No. I’ve continued developing more software, and I’ve re-discovered many patterns inspired by Philosophy and Art. I entered a creative epoch. My creativity + my engineering + my curiosity for many topics require the best tools. Now, imagine: What could my next requirements be?, and How would they force me to become in a Frontend Architect?