I started as a consultant for Dance Up Academy, a small dance school, helping find someone to build their next website. But I ended up doing it myself because the answer to every technical question we asked was “Wordpress”. Nothing against WP, but Dance Up Academy had been there, done that, and were looking for more.
This post, based on experience with one customer, wants to underscore some of the alternatives in 2022 for building software on a budget. My experience is that you can build both beautiful UIs and bespoke backend solutions for small customers way beyond the well-defined terrain of WordPress.
The school wanted to modernize, while making things like registration and course planning easier with a richer admin interface and better reflected their particular business needs. Earlier editions of their WordPress sites suffered maintenance issues, security holes, sub-par SEO, a half-baked mobile experience and, most of all, an admin platform poor enough that they fell back to managing all their data themselves in excel sheets.
This is the age of the Jamstack. The potential for small company websites has evolved so that developers can pick and choose from a wide-array of frameworks that incorporate modern web practices and services that are simple to use and have generous free-tiers. Let’s explore some of these modern tools.
Building UIs with modern static site frameworks
About fourteen years ago, Jekyll, a Ruby-based framework delighted developers with its simplicity. Years of evolution of static site generators followed, leading to richer, more complete frameworks with plugins, theming and integration with larger ecosystems. The most polished jewel of this evolutuon is probably Nextjs, heavily backed by Vercel. Nextjs allows you to straddle the line between the solid SEO and speed of static site generators, on one hand, and the fluid experience of single page applications (SPAs) on the other. You can opt out of server rendering on a per page level.
Dance Up Academy’s site, it is mostly static but the registration pages are dynamic allowing for smooth complex interactions and transitions. Other reasons Nextjs is popular include the possibility to tap into the vast React ecosystem, using libraries such as Framer Motion. It also offers its own solid components for things like optimized images, built in routing with localization, and a solid development build.
I also appreciate the repo with hundreds of up-to-date examples of different use cases for quick reference. It is agnostic about the api you use but it allows you to use serverless functions, to run as a Node app, or run as a static site on top of some other api.
Strong competitors to Nextjs include Gatsby (also React based), Sveltekit with Svelte, or Nuxtjs if you prefer Vue. It should be noted, hybridity brings its own complexity. For example, I wrestled with the merging of server-side css with dynamic css loaded at run time. In some ways, a pure SPA (single page application) or a pure MPA (multiple page app or server side app) are simpler. If you are not building a marketplace app, perhaps go the simpler SPA or MPA route
Creating designs faster with modern design tools
I am primarily a developer, not a designer. But web-based design platforms have changed how developers and designers interact. Figma is by far the leader in this area. I was very surprised to find that many marketing companies have not adopted Figma, still relying on building layouts in Adobe Illustrator and exporting them as pdfs or images for developers to use.
Figma on the other hand allows a much deeper, more agile level of cooperation as both designers and developers can interact with the style tokens and component designs in the same space, iterating and sharing ideas, often together in meetings. I was able to copy a large amount of styles straight from Figma into my code.
Developing with your favorite modern language
Smaller languages like Elixir offer impressive web frameworks (Phoenix). In my case, Kotlin has been my go-to tool in larger projects, so it was a time-saver to continue to use it in this project. Kotlin is as easy to learn as PHP but statically typed and most importantly gives you access to the vast Java ecosystem.
There are a number of pure Kotlin frameworks out there, my personal choice being http4k–I prefer it’s magic-free approach. The bottom line is that developers today should have the liberty to choose the language in which they feel the most productive–getting the most done, in the least amount of time.
Frictionless deployments with Infrastructure as a Service
14 years ago, Heroku pioneered the simplified deployment to the step of pushing your code to a git repo. This allowed small companies like Dance Up to automated deployments at no cost. All the big players like AWS and Google Cloud have their own heroku-like services today.
There are also plenty of small, low-cost cost alternatives like render and my personal favourite fly.io. Another breed of these specialise in pushing static sites to global CDNs together with excellent dev tooling and the use of lambas or serverless functions. Companies, like Vercel, Netlify, and Cloudflare, provide generous free tiers so you can build, preview and push your website to global CDNs with analytics and site performance analysis.
Vercel also is deeply integrated with Nextjs. With Dance Up Academy, the amount of time handling infrastructure has been less than 3 days in total, using a combination of Vercel, Heroku, and fly.io, and most of that time was due to the fact we did not use a database as a service and so needed to handle the extra security involved in maintaining your own database.
Simplify your data storage with databases as a service
About 10 years ago, Firebase started a revolution offering plug and play databases and ready to go auth that could be configured through a simple web UI. A slew of modern competitors have followed (in addition to Amazon of course), offering possibilities to create quick backends for the Jamstack – inexpensive and easy to create apis to be consumed by static sites, often at build time. I have tested Fauna, Hasura, and most recently Supabase, which is particularly interesting as you get the data-streaming of Firebase together with the power of PostgreSQL.
One downside of such services is that they may be architected in such a way that pushes you towards an unsound data model in order to handle performance or storage limitations (my experience with Firebase). Or, even worse, some of these just don’t turn out to be profitable and disappear, leaving you to scramble to find a replacement.
I may well have chosen Supabase for this project if it had been more mature, but in the end we went with our own PostgreSQL instance. This does add some extra maintenance–many database-as-a-service providers have solid security baked in and provide built-in tooling like alerts and info to optimize slow queries over time. These are things we have had to handle ourselves and will add a bit of maintenance cost.
Getting things done quickly
Some of the trends outlined above, empower small teams or individuals to create small but feature rich apps or websites very quickly. But to exploit “big project” software skills to make something maintainable and attractive on a small budget, you also need to ditch big project meetings.
The key to staying on budget in this project was little wasted effort in terms of meetings, design iterations and prioritization of features. We tried to eliminate layers of decision making by empowering the developer and designers to make as many decisions as possible on the fly. When consultations on specifications were really needed, it was always with a single customer representative–no time for consensus building.
Realizing the admin app
We started with the admin UI and backend. We used a traditional REST api, including user management, course and registration management, as well as a simple markdown based-api for the website content. This was all backed with a PostgreSQL database. The teachers are able to update any part of their website, and it is localized (something Nextjs makes easy).
In the backend, I stuck with familiar tools, http4k for glue code of the app, JOOQ as an ORM for generating typesafe sql queries, flyway for migrations, and gradle to build the app. We used Http4k’s Typesafe contracts which are validated and include OpenApi3 documentation, although to be honest I am not sure how useful this is for a small app.
Additionally, I went with Sendgrid for simple email integration, which has a free-tier good enough for this case. The admin UI, which is served from the same backend, is a simple Svelte single page app. The design is spartan and functional, but the customers have been very satisfied with it, particularly because every feature is tailored precisely to their needs: creating courses, tracking registrations, and updating website content. I was able to complete most of the initial code working Fridays and a few weeks over the Christmas holidays. I used Heroku’s free tier for the initial app, switching to the 7€ a month app when it went to production.
The website came last when the designs and admin apis were ready. We had a clever freelance designer who kept the design tokens limited and managed to make a small set of components that could be composed easily in different combinations to handle all the content. This was perhaps one of the single biggest time and expense savers–a simple, functional design. Every special case component in a single page would have added hours of work, so being able to generalize a design is key to staying on budget.
The only hiccups with the website were some problems with the server-rendered styles and some confusion about how to integrate dynamic pieces of UI into the server-rendered pages. The website came together in a matter of weeks and then small changes were made over the next few months as the school added content and images.
We stayed on budget (we are talking more VW budget than BMW), which was the biggest challenge. The school spent less than what marketing companies wanted them to pay for a WordPress site and got a custom solution in return.
The school has received positive feedback both from their teachers and customers. The amount they have spent on their “IT guy” has dropped from a few days of work a month, to a few days in the last year. I feel that what was key here was being committed to finding a happy path that involved combining tried and tested tools with new time-saving services and technologies, while being determined to not waste a cent of customer money.
What I might do differently in the future
The most expensive and vulnerable part of this stack is the database, from every perspective the amount of code needed, potential security threats, and maintenance costs. A reasonable question is why not just the most ubiquitous and low cost database available, SQLite. It does not require another server and all the extra security this entails.
Two of the reasons I have not used it much for web development is that 1. sqlite has been treated as a second class citizen by web frameworks and ORMS. 2. then there is the problem of persisting the file when you are running a web app in a container. But I have been experimenting with SQLDelight as my ORM together with Litestream, which allows you to sync your database with cloud storage. In theory this allows you to rebuild your app in docker without a volume attached. I really like this solution for a small business but it needs further verification as a viable solution.
I have grown to like Svelte over the last few years. Now it has its own answer to Nextjs, Sveltekit, which is still maturing. I feel using this will be a productivity boost over Nextjs for me in the future. Vercel is also investing in Sveltekit, meaning the infrastructure is likely to be as good as it is for Nextjs. I feel I am less likely to run into performance issues with Svelte and I find its built state handling and css solutions to be everything I need, while with React I find myself leaning on third party libraries to supplement React’s inline styles and built in state handling.
I am still not sold on serving my apps from cloud functions. The cold start problem is still relevant and even compounded by the ability to serve each page from a serverless function. I do expect to see this problem solved in the future but I will need to be convinced there is a reason a simple containerized web app is a worse solution.
In conclusion, I feel that small companies on a budget should be enjoying many of the technical innovations and custom solutions enjoyed by larger enterprises – the tools and services are cheap enough. It just requires stubborn developers and customers.
Does this sound interesting? Do you want to be a part of our crew?
Check our open vacancies
We are constantly looking for new software developers to join our team.
Check our open vacancies from the Finnish site or let us know about your expertise and what motivates you with an open application.
More from our pen