Day 12: Building an MVP – Frontend Theme and Backend Architecture
Lav and CofounderGPT prepared a mockup for our MVP, so it’s my turn to convert it into a working application. I’ll delegate as much as I can to CofounderGPT because we want to be efficient and be able to test the Knowlo idea with some real users as soon as possible.
While building a working app will take more than one day, I think I can fit it into 3 or 4 days of work. I’ll use the first day to test if I can create a frontend fast using React and Tailwind and prepare the backend application’s basic architecture. If I manage to prepare the frontend and the architecture in 1 day, I am confident that CofounderGPT can help me to code everything quickly.
Preparing the Frontend Application
As Lav mentioned in one of our previous articles, we’ll use React and Tailwind for our frontend application. React is the most popular frontend framework at the moment. There are many useful open-source components and libraries for React, which will help us to move fast. Also, it’ll be relatively easy to find a freelance developer that knows React if we need help. Tailwind CSS is an open-source CSS framework that gives us a beautiful theme and components for our frontend application. It works nicely with React. We use Ant Design for Vacation Tracker, and we like it, but Tailwind CSS is the most popular CSS framework currently, so we’ll use it for Knowlo.
Can CofounderGPT write React with Tailwind and TypeScript? Let’s ask!
I opened a ChatGPT, and started a new conversation with GPT-4 model. In the new conversation, ChatGPT does not know about our progress so far, but that’s fine because we do not need the full context to build the layout for the initial page.
Slobodan: Do you know how to write React (functional) components with Tailwind and TypeScript? If you know, say yes, and I’ll give you more info about what we need to build.
CofounderGPT: Yes, I know how to write React functional components with Tailwind and TypeScript. Please provide more information about the component you need help with, and I’ll be glad to assist you.
Excellent! Then I used the specification for the dashboard that Lav prepared and asked CofounderGPT to generate React code with Tailwind and TypeScript. A few seconds later, CofounderGPT started generating code for our dashboard page.
After a few follow-up messages, CofounderGPT created the application shell with the side menu and top navigation. However, by looking at the result, it’s becoming evident that we’ll need to hire the DesignerGPT as soon as possible.
Ok, what’s the alternative?
Tailwind CSS has a lot of excellent templates as part of their Tailwind UI. Tailwind UI costs $299 for lifetime access. We’re still in the budget and do not have DesignerGPT, so let’s see if Tailwind UI will work better.
I bought the access and spent another 20 minutes playing with it. The result seems better!
This is good enough for the first step. I’ll move to the architecture and continue with the frontend once the backend is working. You might ask why we want to finish the backend first. There’s no specific reason, but the backend part is more “unknown” at the moment because we do not have a strictly defined data structure. As we want to move fast, it’s better to work on the data structure and the actual data and then the UI for it.
Setting up the Folder Structure
Before working on the backend architecture, let’s spend some time planning the project and folder structure.
We have a few options. For example, we can keep each part of the application in a separate git repository. Using multiple git repositories is a very common scenario, and it works well for applications that do not share the same language (and teams) for frontend and backend applications. Another option is to keep the code in a monorepo. Monorepo is a single git repository that holds everything, including the frontend application, backend applications (often with microservices), configurations, etc. Using a monorepo works especially well when you are using the same language for both frontend and backend and when your team contains fullstack developers.
Both CofounderGPT and I can write some frontend and backend code, and we decided to use TypeScript for everything, so we’ll go with the monorepo. The project will have a folder structure similar to the structure in the following image.
Now that we have the folder structure let’s return to the backend architecture. We want to move fast, but we also want to make a decent project architecture in case Knowlo starts growing quickly. The first architecture of our other project, Vacation Tracker, took us from $0 to $300k ARR and was able to grow even more, but we decided to upgrade it a bit.
We use AWS’ serverless services for Vacation Tracker, which works exceptionally well for us. Our uptime is almost 100% because we use fully managed services only. In addition, the cost of our application was $0 for more than a year! And it’s anchored to ~1% of our MRR now. Not bad at all. Let’s do the same for Knowlo!
The Knowlo app will need to ingest a lot of data on the setup, and most of the interaction after that will be reading the data, except for a few scenarios, including creating new tooltips, upvoting/downvoting, or interacting with existing tooltips.
The “import data” flow seems the trickiest, so let’s start with it.
The easiest way for Knowlo to ingest the data from knowledge bases is via CSV exports. I am sure most knowledge bases can export the data in CSV format. In the future, we might be able to connect to various knowledge bases using API, but let’s keep it simple for the MVP.
The best thing about the data ingestion is that we don’t even care about the CSV export format as long as it separates articles in separate lines. Let’s assume that all knowledge bases will do that. If not, we’ll add a parser later.
So, the first step is to upload and store that CSV file somewhere. Luckily, AWS has an excellent service for file storage – Amazon Simple Storage Service (S3). S3 stores files in buckets. But we’ll also need an API in front of the S3 bucket. We can use Amazon API Gateway service for the API.
API Gateway can connect to S3 directly. But API Gateway has a timeout of 30 seconds, and some CSV files can be large, so we’ll split the upload part into two steps: first, we’ll get the upload URL that allows the client to upload a file directly to the S3 bucket, and then the client will send the actual file. The first step requires a piece of code that will contact S3 and create the upload URL (this URL is called a “pre-signed URL”). We’ll use a Lambda function to run that piece of code.
Finally, we need to allow only authenticated users to upload CSV files. As you can guess, there’s a managed service for that, too. We’ll use Amazon Cognito to check if the API request has a valid JWT token.
We’ll dive deep into all these specific services in one of the following articles, but the high-level architecture of this step can look similar to the following image.
Once the client receives the pre-signed URL, it can upload the file directly to Amazon S3 bucket.
After uploading the file to the S3 bucket, the client can send a file location and additional data to another API Gateway endpoint. This API endpoint triggers another Lambda function that stores the data in the database. We’ll use Amazon DynamoDB as a database because it’s a fully managed and auto-scalable NoSQL database in AWS that will cost us $0 if nobody is using our system. In addition to that, it has excellent integration with AWS Lambda. Once the data is saved, the API will let the client know.
One of the best features of DynamoDB is data streaming. When we save the data to the database, it can stream the data in the background to a Lambda function that will download the CSV file from the original S3 bucket, parse the file, and call the OpenAI API to create embeddings. This Lambda function will finally store the embeddings in another S3 bucket and update the DynamoDB with additional data.
Other flows of the app are relatively simple, so I’ll not explain them in detail. The client needs to send an HTTP request, and we’ll read or update the data in the DynamoDB table and optionally send an HTTP request to OpenAI API.
We purchased Tailwind UI.
Time spent today: 8h
Total time spent: 80h
Investment today: $299 (Tailwind UI)
Total investment: $663.54 USD
CofounderGPT and I still have a lot of work in front of us to finish the MVP. We’ll do our best to do it in 3 days of work. We’ll see if Lav can prepare the landing page and the initial pricing strategy while we work on the MVP.