TLDR: I managed to create FlashDictation by working every day at least for one hour in an Advent of Code fashion.
Warning: This article is very long.
Table of content
- Day 0: Launch AdventOfSaas 2021
- Day 1: Setup
- Day 2: Define MVP
- Day 3: Add video player
- Day 4: Simple correction
- Day 5: Issue transcripts
- Day 6: Easy solution for transcripts
- Day 7: First week done, goal for next week
- Day 8: Landing Page
- Day 9: Landing Page for Mobile
- Day 10: Navigation
- Day 11: Login
- Day 12: Login works
- Day 13: Add dictations
- Day 14: Share dictations
- Day 15: Makeup Part 1
- Day 16: Makeup Part 2
- Day 17: Production
- Day 18: Production ready?
- Day 19: Production ready!
- Day 20: Focus Marketing
- Day 21: HackerNews and IH entry
- Day 22: Break
- Day 23: Tiny video
- Day 24: ProductHunt Launch
- Day 25: Summary and Outlook
Day 0: Launch AdventOfSaaS 2021
Is it possible to bootstrap a successful SaaS business in 24 days? Let us find it out together: AdventOfSaaS 2021!
My name is Kiru. Join me on the journey of this project. I will keep this page up-to-date with daily progress and any interesting stats.
What is AdventOfSaaS?
You probably know AdventOfCode, where you solve a different puzzle every day. Similarly, I work on a SaaS (Software as a Service) project every day. The time spent varies depending on my workload. This project is done alongside my usual work. From 1.12.2021 to 25.12.2021, I pledge to dedicate at least 1h per day (with 4h weekend budget) and post daily updates here.
What has been done until now?
This launch post was written before December, as well as the project ideas were collected. No code has been written until now.
What am I going to work on?
Dictatly: I am trying to improve my French. One effective tool is dictation. I would like to watch a video or listen to a podcast and write down what I hear. Right now, I do this by hand and then go over the text to correct it. It would be simpler to use the existing transcript to autocorrect and show the mistakes, as well as track my mistakes.
Few notes on the idea:
- I did not find a tool that satisfies my need
- My usage is to learn languages, but it can be extended to a general dictation tool
- Not free after the beta phase
The first step is to create a landing page, which will contain more information.
What is a successful SaaS for me?
These are the milestones I set to rank the project success in the end:
- Project is online
- The project is usable by me to practice French
- At least one paying customer
- At least 5 new Twitter followers
- MRR to cover all the costs (server + domain and other services used)
- Double my Twitter follower count (new 122)
- 100 paying customers
- Goes viral
- Consistency: I manage to work for 24 days for 1h per day
Got more questions?
If something is not clear, or you just want to contact me, go ahead. Hit me on Twitter: @kiru_io
Day 1: Setup
What I planned to do and what I did
■ Publish this page on kiru.io ■ Get domain flashdictation.com ■ Add progress bar in days on the main page ■ Setup project on GitHub ■ Setup initial landing page with a simple description ■ Make a simple logo □ Define MVP (Minimal Viable Product) □ Define timeline ■ Publish on Twitter □ Publish on IndieHackers
How did the day go?
I registered the domain via Cloudflare. The webpage is a simple Next.js static page (for now) deployed via Cloudflare Pages. Why? Because it was the fastest way for me to get started. Cloudflare Pages deployment did not go smoothly. I ended up having the following error:
19:21:05.595 export PATH="$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH" 19:21:05.595 [0m 19:21:05.938 [32m> Successfully installed Yarn 1.22.4! Please open another terminal where the `yarn` command will now be available.[0m 19:21:06.302 Installing NPM modules using Yarn version 1.22.4 19:21:06.745 yarn install v1.22.4 19:21:06.836 [1/4] Resolving packages... 19:21:07.046 [2/4] Fetching packages... 19:21:19.165 error [email protected]: The engine "node" is incompatible with this module. Expected version ">=12.22.0". Got "12.18.0" 19:21:19.177 error Found incompatible module. 19:21:19.178 info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command. 19:21:19.199 Error during Yarn install 19:21:19.202 Failed: build command exited with code: 1
It turned out, without any config, CloudFlare uses node version 12.18.0. To fix this I had to set the following
Once that was done, everything went as expected.
For the logo, I used Hatchful by Shopify. I did not define the MVP (Minimal Viable Product) yet, since the idea was not clear to me as well. So I spent most of the time writing down what I expect, and what problem it should solve.
Go checkout what I produced today: Flashdictation.com
Day 2: Define MVP
The main goal of today is to define the MVP, e.g. more in detail and the tiny steps needed to go there. The detailed tasks help me to stay focused, and not get distracted by other (nice to have) features. For the audio, I need a way to show a player on my page. I will try with this component: react-component. It seems easy to use and allows audio and video - so I don’t have to implement it by myself.
For testing, I will use the innerFrench video - especially since they come with proper subtitles, and the transcripts are free.
Day 3: Add video player
Today’s goal was to experiment with the video player. It was fairly easy to add the player, most of the time I spent making the page prettier.
The final result is:
Tomorrow, I am going to add the correction logic. That should be enough to test the MVP. The next step is to add a few shortcuts to control the player. With the above mockup, I can easily explain this project to anyone.
Day 4: Simple correction
I managed to complete the simplest MVP:
- A video player to listen, pause and play
- The input to type what I hear
- Once done, the correction
Today I focused on implementing the correction part. Initially, I spent some time coming up with a simple algorithm but wasted too much time. I ended up using a diff-library (well I didn’t think “correction” in terms of “diffing”, I was trying to find miss-matched words, which in the end is “diffing” duh!)
This is the result:
There are a few changes I will make:
- The corrections are not perfect, the punctuations should be ignored (or I can add an option)
- The correction results are not intuitive to read (for non-programmers anyway), I will work on that in the future
- Don’t show the untyped text (e.g. in the above screenshot everything after “Et d’ailleurs” should be hidden)
- In the above screenshot you see, I had Grammarly activated. I will disable it in the future.
Day 5: Issue transcripts
Started with updating the todos on FlashDictation.com. Apart from that, added a shortcut for the video-player (Key 1) for starting and stopping. That makes it easier to type what I hear without having to move my cursor and hit the Play/Pause button.
This completes (imho) all the features needed to use the tool. Until now I hardcoded the transcript and the video. Optimally, I would like the user to enter a YouTube link and play the video. Getting the captions via YouTube API seems possible.
I spent most of today figuring out how easy it is to integrate the API. It seems doable, but I wanted to avoid adding an external dependency. There are a few alternatives:
Limited set of audio+transcripts The alternative to YouTube links is, that I collect audio+transcripts (free to use) and allow only pre-selected ones.
While researching, I learned about the
podcast:transcript tag for RSS feeds, which points to the transcript.
This seems a great way to get the transcripts of the audio. I don’t have a proper idea what is the best solution. A very simple approach is to provide some audio+transcripts.
Later on, I can still replace them by something more dynamic.
Day 6: Easy solution for transcripts
My initial idea was to create an app like this:
After trying to figure out the best way to integrate the YouTube-API (I wasted already ½-hour to figure out why the API-credentials were wrong.), I decided to give up for now (not because it’s hard, just because it’s too much effort for an MVP) and go further with a predefined set of dictations.
For english dictations, I will stick to these freely available short stories, and use the videos from YouTube. Later on, I have to find other resources for different languages (maybe ask on r/languagelearning ?).
For tomorrow these are the plans:
- replace the YouTube link with an audio for one of the short stories
- hard-code the text from the short stories
- design the proper landing page, as well as define some goals.
Day 7: First week done, goal for next week
Today marks one week I have been working every day for at least 1 hour. At the beginning, I made huge progress, got the PoC implemented very fast, and deployed it to flashdictation.com. Now I have something working, but I need some goals for the next two weeks.
This project is called AdventOfSaaS - so where is the SaaS part? That is something I have been thinking about the last two days. How to monetize this project? What I have now is a web app to practice dictation. It is not perfect, does not work for anyone - but solved my problem. I could even extend it, such that I can paste the link to a video and enter the transcripts and create a “dictation” page for that video. That way, the user can share that link. Once you land on the page, you can see the video and an input area to type what you hear. Once done, let me correct your mistakes - as for now.
So how to monetize? One way is to charge to create the “dictation” page and target teachers. As a teacher, you can create a dictation page and send it to your students. They can listen to the audio once - and type what they hear, and send it back to you. You can use the “auto-correction” tool to see what mistakes they made, and send it back to them
- so they can correct them. You have to pay certain amount (let’s say $3.77/month) to create an account.
For the above use case, I need to change Flashdictation as follows:
- Allow creating a dictation page (video/audio + transcript)
- On the main page, show a “test dictation” - so you know how it feels to use the dictation
- Allow creating a teacher-account
- One teacher account contains “dictations”
- The number of users per dictation is limited
Deadline: 7 days! By 14th I want the MVP (with the above features) to be done.
Day 8: Landing Page
Today I worked on redesigning the landing page. This is how it looks like now:
This is how it looks like now. It is not done yet, but almost:
I need to add some infographics and explain what is going on. The page should be optimized for mobile as well. Today I only focused on the desktop version. Tomorrow, I will fix the audio-player (it should auto-play and show somehow it is muted), and test it on mobile.
The written text should also be synchronized with the audio. I need to add a “correct me” button. Once that is done, I can write down the final features.
I am pretty happy with today’s progress. 💪
Day 9: Landing Page for Mobile
Continued on the landing page. Replaced the blue buttons with actual text and a logo, so it’s more clear what each part stands for. I need to add more text to describe further in details, what every part is. I don’t like if you end up on a landing page, and you don’t understand what the project is about. Nowadays, the focus is on fancy design and less text. But I don’t see why we can’t have both. Anyways, this is the result after today’s work.
I also added Plausible.io to track how many people are using the page. Let’s see tomorrow how many people visited the page.
Note to me: Add Plausible.io from the beginning next time!
Day 10: Navigation
Added navigation to the page, visually this does not change much:
Behind the scene, I had to re-organize the code. The current online version is broken, since I host the page via Cloudflare (they only support static next.js builds).
Next, (haha) I have to move away from Cloudflare. Maybe try Vercel or build on a VPS?
Day 11: Login
I moved away from Cloudflare Static pages to Vercel. Until now, I only had static content, and no server-rendered part. That might change, so I move rather now than later. There are not many visible changes today, but I reorganized the code, and started adding the login components. It takes more than a few hours to finish that, so I decide not to deploy the half-broken parts. I will complete it tomorrow and push a version. A few days ago, I wrote a mail to innerfrench ( A French podcast, targeted at beginners. ), and got a replay:
This is great news! Next, I need to find some good English examples!
Day 12: Login works
I have a working authentication system! Initially I wanted to add NextAuth.js and Google authenticator. That approach needs a hosted database instance (to store dictations + text). In the end, I decided to try out Supabase. why?
- I don’t have to host a database
- Supports Authentication
- Native support for Next.js
- The free tier is good enough, the Pro tier is relatively cheap (20$/month)
- Possibility of migrating to a self-hosted version if needed
I found this nice project from Vercel, with Stripe and Supabase integration. Took it as a template and adapted it for my use case. This is the current result:
The UI looks ugly - since I had to adapt some css, and did not spend much time to make it prettier. What counts is, that I can login and create an account. I will focus on having all features done and then spend one or two days on makeup.
For now, you can create an account and login. Be aware, I will wipe the database before I publish it on ProductHunt (or anywhere).
Tomorrow, I should work on the following tasks
- Add a WIP banner (so people know it is not complete yet)
- Implement the ability to create “dictations” by given a URL + text
- Generate a unique link for dictation
Day 13: Add dictations
From yesterday’s plan:
- Implement the ability to create “dictations” by given a URL + text
- Generate a unique link for dictation
Those are implemented. Now I can add new dictations, and see them. It took me some time to grasp the Supabase Row-level Security feature, but once I understood it, the implementation was straightforward.
The form looks ugly (as usual), I did not spend much time making it better:
The login and creating dictation workflow works as expected. I should add some checks (e.g. empty values and so on), but for now, I have something working:
For tomorrow, I will focus on the following two items:
- Add a WIP banner (so people know it’s not complete yet) (from yesterday)
- Show dictation page, where user can type what they hear and we show a diff!
- Fix login in production ( I can’t login for some reason)
Day 14: Share dictations
Let’s begin with the simplest change: Added a WIP based on this blog post:
Implemented the actual dictation page. The user can type what he hears and see a score. For the score, right now I use the Levenshtein distance (for non-programmers: An algorithm which gives you how close two words are). It is not the best score, but I get a single value for free. I have to brainstorm more about what is a good metric.
The workflow looks like this:
You can still not login in to production. I have to setup a proper production environment in Supabase, because the URL which is sent in the mail (for the magic-link) is hard-coded. I tried to fix it in a few minutes, but it will take longer than that. I decide to postpone it until all features are complete.
For tomorrow, I will spend some time to make all the ui-components consistent, and test on mobile. I got asked where is the link to flashdictation.com a few times, so added a prominent link on the top of this page (with the logo).
Day 15: Makeup Part 1
Before I changed all pages to be consistent, I re-evaluated the todos, and reorganized them:
This is the result after re-doing the dictation pages:
The landing page is not completed yet, as well as the login and the actual dictation page (which you share). I did not have much time to finish those today.
The goal for tomorrow is to make the login and dictation page consistent with the above pages.
I will update flashdictation.com once all of those pages are complete.
Day 16: Makeup Part 2
As planned, I finished the redesign of the login and dictation pages:
I did not manage to fix the production environment, since there are still some database changes missing. Hopefully should be done by tomorrow.
Day 17: Production
No UI changes today. I tried to fix the production environment, but there were too many issues. The main problem is, that I have to setup a different Supabase project and copy all data. Unfortunately, that is not easy. So I decided to re-do the database and recreate the data. Most of them being Stripe-products. Then I spent some time fixing stripe production.
Obviously, this did not work as flawlessly. Finally, I gave up and thought I can at least fix Vercel to have the landing page fixed. After ignoring a bunch of TypeScript errors, I have a new version online:
Day 18: Production ready?
Managed to fix the production environment (by copying all data from dev to production). But be aware, I will wipe the database before I put the project on ProductHunt.
I am preparing to add Stripe integration. A warning is shown once you hit 5 dictations:
There are not many changes, and my time to work alongside is limited. Therefore, I will focus now on completing a “SaaS” project, then having all the features. Once the project is online and I have a few users using them, I can still add new features.
These are the missing steps:
- Add Stripe integration
- Reset database
- Fix all og-tags
- Add terms and services + privacy page
- Add pricing information on the landing page and examples
- Make a small marketing plan (when to put it on which platform)
The goal should be to invest next week in marketing (aka promoting the project on different platforms). Wish me luck.
Day 19: Production ready!
Today was the longest I worked on this project at once. I wanted to finish almost all tasks which needed to be done before going live. I don’t know where to start, there were too many changes. Among the major tasks done are these:
Added pricing to the landing page:
Added Stripe integration: This was something I have been postponing for a while. Just out of fear it would take longer than I expected. In the end it did! I spent too much time debugging a stripe-api call issue, but eventually managed to fix everything. There is still a tiny bug left on production - but I don’t know exactly how to fix that. Once I create a subscription, Stripe forwards me to a page, but that page contains the Vercel URL - instead of flashdictation.com (for now that is not a huge issue, I will focus on marketing and fix it later).
Once you click on subscription, you will be forwarded to Stripe, where you can provide your payment information:
Some tiny tasks
- Checked all pages on mobile
- Added footer and privacy information
- Added contact information
- Fixed all bugs (e.g edit did not work before)
Next week, I will focus on promoting the project. Finding some customers, and fixing any major bugs.
Day 20: Focus Marketing
Today I distributed the project link to a few friends, and got some feedback back. All of them are techies though and not my real target audience. I noted the feedback, but will wait to see what actual users say.
The current project which is online, is usable, but I have to dogfeed it a bit. For the rest of the week, I will focus on putting the project on various platforms.
This is my plan for the last few days:
- Getting feedback from other users
- Add on IndieHackers.com as product
- Add chat-bot Integration? (I like them, an easy way to contact)
- Add on Supabase
- Prepare a short video (try Remotion?)?
- Publish on Product Hunt and ask for retweet
- Cleanup and analyze traffic until now
- How much time did I spent in total
- How much money did it cost? What is the break even?
Day 22: Break
Today I took the day off.
Day 21: HackerNews and IH entry
I didn’t have time to add the attribution for the icons. Fixed that today. Also published the project on Supabase and IndieHackers.com as product.
I forgot that the plan from yesterday (20.12.2021) does not contain postings the project on HackerNews. Here we go: Show HN: Dictations for Teachers Made Easier . Same on IndieHackers. I put the project online: Flashdictation, but waiting for approval.
Day 23: Tiny video
I wanted to create a short video - but I am not very skilled in editing videos. I tried to use veed.io, but it was too cumbersome (just for me, took me too much time). I decide to try Remotion. It was on my bucket list for a long time, but never found time. This was the motivation I needed to try it out. The library was surprisingly easy to use. It makes editing videos as fun as programming. I still struggle to wrap around the concepts (e.g. Sequence / Composition / Still ), but it’s quite fun to debug a “video”.
Anyways, here is the video I tweeted:
👋👋— Kiru (@kiru_io) December 23, 2021
Checkout my latest project: https://t.co/8dPSscYr1v ! 🚀🚀
A dicatation tool for teachers and language learner🤓! Just the beginning - more feature will come!
Developed in 23 days. Documented on https://t.co/OcGcC0jxjZ 💪
btw, RT is very much appreciated 🙏 pic.twitter.com/DTNlM9pjQZ
Day 24: ProductHunt Launch
Many people in my bubble (aka Twitter, and the news I read) see ProductHunt (PH) launch as the holy grail. Therefore I waited a while to put it on ProductHunt:
To be honest, choosing the 24th of December to launch the project on PH was not my wisest move. On the other hand, my target audience is not on ProductHunt. I just hope it will help to rank the page a bit higher on Google (aka generate some backlinks).
Apart from that, I re-read everything I wrote until now and corrected some mistakes. You can see the diff here.
For the next time, a few lessons I already learned regarding writing:
- Read what I wrote the day before and correct. I don’t see the mistakes immediately, the next day I can check If I understood what I wrote.
- Pass everything through Grammerly to catch all typos.
- Put more images. Start adding screenshots from the beginning. (Link to flashdictation.com changes each time 🤦️)
- Spent more time on writing than coding. Maybe write before you code and then re-view what you wrote?
Day 25: Summary and Outlook
Today marks the 25th and last day of this project. It has been an interesting journey so far. This journal entry will be longer than usual. I will cover the following topics
- What I achieved
- Hours spent
- Lessons learned
Hours spent From the beginning I tracked every minute I spent on this project. The idea is to know how much this project costs me and what the break-even point is. I will keep tracking the hours and once I have some income, I will post more about that. In total, I spend 61h and 38min on the project. The following graphics show the hours spend by week and by the hour (the axis are hidden by intention)
Most of my work was done after work, and in the third week I spend a weekend to finish almost all features which were left. It was not planned, but in the last week I did not have much time to work alongside my job - so I decide to do a sprint and spend less time in the last week.
Numbers The following charts shows the number of visitors from Plausible.io:
I made the mistake to include on day9. With 118 unique visitors, I don’t have many - but nevertheless more than 1 (which is me). Considering that many block tracking, 118 not blocked visitors is not bad. I am quite happy with that.
Another of my goals was to attract more Twitter followers:
I consider this a success. I gained 6 new followers and 1315 people visited my profile.
What I achieved
At the beginning I defined some levels on how to evaluate this project. I reached Level 0 and Level 1 (at least 5 new Twitter followers and one paying customer). I don’t have any paying customers except myself (yes I subscribed and pay for my own SaaS, it’s called eat your own dog food). Apart from the defined goals, my main success is definitely having something online, even this blog entry is a success in my eyes. This project, despite having no actual users shows to me how much can be done by just being consistent, and keeps me motivated.
Lessons Learned Here are some lessons I learned. Which are mostly for me to improve for the next time.
- Add Plausible.io or any other user counter from the beginning
- Consistency beats procrastination
- It is possible to develop a SaaS project in ~62h hours for me
- Technical choices are irrelevant to validate your idea
- Writing is hard: I still struggle to convert my thoughts to keystrokes.
- Add proper descriptions from the beginning, it is hard to follow what my goals and intentions are. Spend more time on writing.
- Growing on Twitter is hard.
- Setup a Twitter automation: Until today I post to Twitter every day by hand. This should be automated next time.
- Spend more time on Marketing. Next time, I will dedicate half of the time on creating marketing material)
- Learn to create proper og-tags (with proper twitter-cards)
Outlook This is not going to be my last piece about Flash dictation. I will continue developing it, especially adding more features. I will not post any daily update, since I think the frequency is too high (especially on Twitter, I will experiment with weekly updates). The goal is still to attract an actual user. Despite having no user, I will keep using it to learn French. I have more plans to market it to language learners. This is just the beginning.
Thank you everyone for supporting me! 🙏🙏🙏