Day 2 of 30. Zero lines of code yesterday, but today we're laying the foundation.
Picking a tech stack for allscreenshots is an important decision. It's easy to spend days researching, comparing benchmarks, reading opinions and all of that.
However, we're not doing that for this project. We're going to pick something we know well and that we can move fast in. Here's what we chose and why,
something we decided in about an hour, but with the idea that new insights may lead to new solutions.
The backend: Kotlin with Spring Boot
Kotlin on the backend. With a team who is mostly specialised in Java, Kotlin is our next step up. Combined with Spring Boot, and in the future perhaps other frameworks, it's a solid foundation for our app.
Our main reasons for picking Kotlin on the backend:
We're fast in it. We have years of great experience with Spring Boot which matters more than anything else. The "best" framework is the one where you can ship features without constantly checking documentation. Also, LLM models are really good for the boring parts of the code, like generating the boilerplate, which makes us move just a bit faster.
It's boring in a good way. Spring Boot has solved most problems we'll encounter. Authentication, scheduling, database access, API validation, testing: all of these functionalities are included. There are well-documented way to do all of it, and most problems have been solved before.
The JVM is actually great for this workload. We'll be running headless browsers, managing job queues and handling concurrent API requests.
The JVM handles concurrency extremely well, and Kotlin's coroutines give us async capabilities when we need them.
Deployment is simple now. The old complaint about Spring Boot was heavy containers and slow startups. With modern containerization and decent VPS hosting, our app will boot in a few seconds, and will be able to handle a decent load.
We've done this before. We've built a few apps with Spring Boot and Kotlin, and we know what we're doing. We can leverage some of the best practices we've learned over the years, and use some of the software solutions, and CI/CD approach from our previous projects.
The trade-off? There might be a higher memory footprint than applications written in Go for example.
We'll need a solution with at least 1GB RAM, but more is better, and we'll dive a bit deeper in our decision-making process regarding hosting
("Why We Didn't Pick a Cloud Provider", or something like that) in a future post.
The frontend: React
For similar reasons as why we picked our backend technology, we picked React because:
- We know it well, and we've built earlier projects in React before.
- The ecosystem is mature, with a lot of plugins and tools.
- For an application of any size bigger than 100 lines, a typed language is a must, and React's support for TypeScript is great.
Technically, for a dashboard with a few pages, anything modern works - React, Vue, Svelte, whatever. Pick what you're productive in. For us, that's React.
We're having an ongoing discussion if we should pick React or NextJS, but we're a little undecided at the moment, so we're sticking to what we know, so we're leaning towards React for now.
We're keeping the frontend minimal. A landing page, a screenshot demo page, a login flow, some admin panels, a dashboard showing API usage and managing keys, and for our advanced users an audit log and several enterprise features. Our initial design covers around 10 pages in total. We don't have a need for complex state management, and focus on the functionality for now.
Of course, we'll use Vite for the build tooling because it's fast and simple. Also, we use Tailwind for styling because it allows us to create a presentable
design in a short amount of time without spending a large amount of time on dealing with CSS.
The database: Postgres
This one was easy, and we had zero hesitation in choosing Postgres. Postgres is the right default for almost everything.
- Rock solid reliability
- Great tooling and hosting options
- We already know it can handle non-relational data if we need it
- JSON columns for flexible data when we don't want to add migrations
- Excellent performance for our scale
We considered going "serverless" with something like a hosted version of Postgres like PlanetScale or Neon. But a managed Postgres on our VPS or a cheap managed instance keeps things simple and predictable and avoids things like cold starts, connection pooling complexity, and potential other surprises.
The stuff we're not using
Worth mentioning what we deliberately skipped:
- Kubernetes - Great when you have a big team, but at the moment, it's overkill for us. A single VPS or two will handle our load for a long time.
- Microservices - While we appreciate the concept of microservices, we're aiming to keep things simple, so we're going for a modular Monolith, until there's really a compelling reason to switch to a different architecture.
- GraphQL - REST is simpler for this use case, and we have a well-defined API, so at the moment, we think GraphQL would be overkill
- NoSQL - No see no benefit over Postgres for our data model, plus if we need to, Postgres is a pretty good NoSQL database.
- Serverless functions - Headless browsers and serverless are not a great combination. We're aiming for performance, and things like cold starts isn't great for our latency requirements, plus a lot of serverless functions have a maximum duration, which isn't great for our use case.
What we set up today
- Created the GitHub repository (monorepo:
/api,/web,/infra) - Initialized the Spring Boot project with Kotlin, added basic dependencies
- Initialized the React project with Vite and Tailwind
- Set up a basic GitHub Actions workflow: build and test on every push
- Wrote a placeholder README documenting our stack choices
No running app yet. But the skeleton is there, our CI is green (for now...), and tomorrow we can start writing actual features.
Tomorrow: architecture sketch
Day 3 we'll draw out how the pieces fit together. How does a screenshot request flow through the system? Where do the images go? What happens when things fail?
Book of the day
As before, we have a small book recommendation. As we mentioned before, we use Postgres for everything, and we often say "just use Postgres", and you'll be fine. Well, it seems Joel and Aaron agree with us, and they wrote a book about it with the great title "Just Use Postgres".
Just Use Postgres by Joel Clermont & Aaron Saray
This book landed at the perfect time. The core argument: Postgres can do far more than most developers realize, and reaching for additional tools often adds complexity without real benefit.
Queues? Postgres can do it. Full-text search? Postgres handles it. JSON documents? Postgres has you covered. Cron jobs? Yep. These days, Postgres even handles
Vector Database pretty well, so in the age of AI, Postgres just became even better.
Please note: we're not saying never use specialized tools. A product like Redis or Elasticsearch are great tools! But for a bootstrapped SaaS trying to keep costs and complexity low, Postgres as the foundation makes a lot of sense to us. This book reinforced that instinct and showed us features we didn't know existed.
If you're defaulting to "Postgres for data, Redis for queues, Elasticsearch for search" without questioning it and want to benefit from some simplification, this book is worth a read.
Current stats:
- Hours spent: 3 (1 yesterday + 2 today)
- Lines of code: ~50 (boilerplate)
- Revenue: $0
- Paying customers: 0
- Repository created: ✓
- CI pipeline: ✓
Top comments (0)