A simple personal budgeting tool, inspired by YNAB.
🚧 👷 🚧
Work is in progress / under construction. This is a hobby project and I'm only working on it occassionally. You're welcome to browse the code and follow along but it won't be complete for a while.
I love YNAB and have used the desktop version for years. At some point in the past they moved their business model over to a subscription service. I didn't see the value of switching as I had all the features I required in their original version.
The only 'issue' I had was the data syncing between different devices, which predominantly used Dropbox. I used to have several services using Dropbox, so I didn't think too much about using it, but over time I have migrated away from the platform and it just became another redundant app.
By disconnecting YNAB from Dropbox, I could only use the app on my Windows computer, which is inconvenient as I spend most of my time on other devices nowadays.
With this in mind, and as I was looking to expand my knowledge of serverless & other tech, I thought it was an ideal product to replicate.
- Domain Driven Design (DDD)
- Event Sourcing
- Command Query Responsibility Segregation (CQRS)
Here's a primer video on the theory & practice to get started.
- Serverless via SST (based on
create-sst
) - Authentication via @serverless-stack/lambda
- MySQL database via PlanetScale (used for event storage - "writes")
- ORM via Kysely
- Redis caching via Upstash (used to generate projections - "reads")
- GraphQL (and Pothos for TS schema building) - this is the data access layer from the frontend
- Event bus via Amazon EventBridge, which is used to update projections and to dispatch Server-Sent Events (SSE) to help keep the frontend in sync
- Monitoring with Sentry
- NativeBase for the design system
Name | Description |
---|---|
CACHE_URL | Location of the Redis cache on Upstash |
DATABASE_URL | Location of the MySQL database on PlanetScale |
GOOGLE_CLIENT_ID | OIDC key to use Google social login |
SENTRY_DSN | Location of the error/performance logs |
- Create a database at PlanetScale - use schema.mysql
- Create a redis cache at Upstash
- Create a new OAuth client with Google
- Create an account with Sentry
- Assign the relevant environment variables based on the above
- Install dependencies with
npm install
- Run the database with
npm run db:start
- In another shell, run
npm start
- the first time you do this it will take some time as it sets up the various bits of infrastructure. - In another shell, run
npm run web
- this will run the website at http://localhost:3000/
- Install dependencies with
npm install
- Run
npm run storybook
- Visit http://localhost:6006/ in the browser
I have created a domain outside of the AWS ecosystem, my setup looks like this:
Namecheap -> Cloudflare -> AWS
Namecheap uses Cloudflare as for DNS, and Cloudflare uses a CNAME entry to point to the urls created by AWS.
Cloudflare provide a free SSL certificate via Let's Encrypt, but to make it work with SST I've requested a public certificate through AWS Certfificate Manager (AWM) in the us-east-1
region.
The certificate uses DNS validation to ensure ownership of the domain.
The reason I'm not using Route 53 as recommended by SST is to avoid the monthly $.50 fee. This is something I would probably reconsider if I wasn't building a hobby project.