Building MVPs fast on Django
A productive setup to get the benefits of traditional Django with sprinkles of javascript goodness.
This is a guide for technical (co-)founders in startups who are optimising to discover product-market fit with Django.
For building MVPs, speed is important. In this post, I’d like to share a lean alternative to the single-page Javascript app plus API backend that is popular today. It’s made us 5-10x more productive at Gyana, and I’m quite excited about it!
Disclaimer: This is an opinionated guide! There are developers with far more experience than me, who will likely say the exact opposite. As ever, YMMV.
To understand the reasoning behind my decisions, here are some technical principles that guided me. They are the non-obvious things I’ve learned building MVPs, and getting it wrong repeatedly:
You are limited to a budget of 20k lines of code (LOC)
Optimise for consistent feature velocity
Avoid custom solutions for problems outside your value add
Build in consistent layers
Better to spend more time writing less code than vice versa
Consistency is golden
Magic is fine, but be open to reading the source
Running Django in production is a solved problem
Some technologies are good for scaffolding but not production and vice versa
Here’s the guide. I’ve tried to make it succinct, specific and with links where possible. Any questions, feel free to reach out!
Part 1: Scaffold
Build a working app and lay down the basic architecture.
Get SaaS Pegasus ($295) and generate your app with Postgres, Tailwind, Heroku Python. Run it locally, join the Slack community to troubleshoot.
Push your app to Github.
Deploy your app on Heroku and check the public herokuapp URL works.
Learn Django. Read the docs, go deep.
Get familiar with the Django package ecosystem.
Manually build CRUDL views for a Django model using model forms, CBVs and templates, and turn it into a cookie cutter template for apps.
Generate an app for each key data model in your app with your template. E.g. for an e-commerce store - “product”, “invoice”, “basket”.
Add the business logic, data modelling and template changes to get a basic flow through the app.
You will have an ugly (close to unusable?) app, but where the functionality is working.
Part 2: Delight
Build a great UX to delight your end user.
Prototype the styles with Tailwind, abstract re-usable styles as classes.
Add Turbo Drive with the relevant Django helpers.
Use Turbo Frames (and possibly Turbo Streams) to merge different pages into a single view, without writing JS.
Use Stimulus to add snippets of interactivity, like modals or popups. It is modern JQuery. Get inspired.
Still not enough? Write React components, wrap them into web components and use them in Django templates. Use functional components with hooks. Interact with the backend over DRF with coreapi.
For custom widgets (e.g. multi select), wrap a popular React UI library as a Django widget, and update a hidden input.
You will have a great UX on top of a working feature set.
Why it works
Django itself is an opinionated framework, full of the hard-fought learnings of past-generations of developers. Take the time to fit your UX into the Django abstractions, and it pays dividends.
Pro tip: Lean into the Django apps structure with pre-determined file names. App separation improve cohesion, and the common file structure makes development easier. Done right, you’ll never lose sight of the entire codebase.
Building features in pure Django is far more productive than Javascript plus Django APIs. It is fast to iterate and experiment on your core flows and business logic. As you become proficient, you’ll be moving close to the speed of thought.
Using the technologies in part 2, you can iteratively improve the UX in specific parts of the app in a deliberate and consistent way. They are ordered roughly by complexity. Choosing which one to use in each situation is an art but you get better at it over time.
This separation of concern between functionality and UX maps onto the separate levers you’ll be optimising with your MVP. For me, that’s the most powerful part and why we ❤️ the approach at Gyana.
Thanks to Cory Zue, whose articles on modern javascript for Django catalysed my search for a better Django stack. If you’re looking for support in your Django journey, I can highly recommend his SaaSPegasus community.
Thanks for taking the time to read. If you’d like to get notifications for future posts like this, subscribe below.