Building A Journal Web App From Scratch Using Only Cursor
Table of Contents
I wanted a Journaling app for myself for a very long time but I couldn’t find something with which I resonated. For such things I prefer them as web app, they enable you to use them from anywhere, they can even be installed on your phone like an app.
The main requirement for such an app was to be completely secure, all user contents must be end-to-end encrypted. The encryption method I chose was AES-256-GCM-SIV.
I have used LLM-assisted coding from time to time, but this is the first time that I used Cursor’s agent mode for building a complete project from scratch.
I didn’t ask it to one shot it, because then it won’t be my app. I had specific ideas and opinions in mind that I wanted in my app.
Features
- Privacy-first, end-to-end encrypted - both encryption and decryption happens on the client side
- Multi-journal layout, a Journal can have multiple Notebooks and a Notebook can have multiple Entries (content lives here)
- Each Journal will have their own key and user set passphrase
- Except for Journal name and dates, all other user input such as Notebook name, Entry title and content are encrypted on the client side
- Should be able to mask the content of Journal, which will be only revealed for active Notebook/Entry
- Different themes can be set per Journal basis
Tech Stack
Since this is a client (frontend) heavy project, therefore, it is clear that a SPA framework would be good fit for it along with REST API on the backend.
Therefore I chose Svelte on the frontend and Rust with Axum on the backend. I’ve experience with both of these and they both offer the best performance and developer ergonomics.
Rust programs are compiled into a binary which can directly run on compatible machines. We can also embed Svelte build files into the Rust binary, which gives you a single binary that runs a server which serves both REST API and client.
Building With Cursor
I don’t look at Cursor as a magic wand which can just do things when you ask it to, instead I think of it as somewhere between a junior and senior developer.
I prefer to break down my project goal into small step by step plans, so that I can verify agent’s work. By the way I was using Grok 4.6 High model.
Example Prompt:
- initialize backend directory as new cargo workspace, we will use crates such as Axum and SQLx (Postgres) to build REST APIs for the journal app.
- create pg_store trait which will use postgres as key-value store, this is similar to Redis’ kv store but backed by postgres database.
What I’ve noticed is that LLMs tend to make simple things very complicated, they abstract away one liners into a function which will be used only once. From time to time you have to nudge them into right direction, write important design patterns in AGENTS.md.
Writing backend was pretty straight forward once I figured out all the nuances of how agent works and added relevant instructions in AGENTS.md.
On the client side it was clear from the start that we will be using Svelte with SvelteKit in SPA mode, so my first prompt was to create a UI prototype in Svelte with TailwindCSS, DaisyUI and Bits-ui. The prototype was mostly good, it needed only few tweaks.
Since it had already created all the REST APIs and UI prototype, it had much better idea on flow and end product that I wanted so I just prompted it to integrate API right away. That it did in one shot, all the APIs were integrated and whole thing was working fine.
There were many minor issues and bad design choices here and there, that I pointed out and it fixed them all.
Conclusion
Letting an AI Agent build for you sounds very easy, but the nuanced choices made by these agents can easily derail the product if not guided properly. We should not see agents as a substitute for real human but like a junior developer and at times even a senior developer who needs guidance from the product manager.
I am going to keep on using the agents to build things that I wanted for myself for so long. Everything that I build will be open source, including this journal app which I’m calling HushJournal.