
Lookbook Requirements & The Initial Setup: Part II
Nov 19, 2025
In Part I, we explored the basic overview of the Style Lookbook application, including where the idea came from and why RAG was a great candidate for hair salon clients. In case you missed it, check out the previous blog post. Today, we’ll dive into the requirements and the initial tech setup.
First, though, let’s take a step back and discuss some of the broader picture.
I’ve been using Kiro as my IDE for about a month and find it a great helper when creating requirements and tasks before writing a single line of code. Although I’m always eager to dive right in, taking a thoughtful approach early on prevents headaches — and major rewrites — later. With AI tools like Kiro, developers no longer need to manually write specs or requirements. This allowed me to focus creating the app features rather than worrying about folder structures, API patterns, or which fields to include. It gave me a running start.
For the Lookbook app, Kiro was perfect for creating the scaffolding for my app. I described specifically what I was looking to build and it provided well-defined information on what to use and the steps to take.
Kiro created the following documents:
- design.md
- requirements.md
- tasks.md
The design document went into detail about the application, sample Django models and fields, provided API endpoint paths, TypeScript interfaces, and testing requirements.
From there, the requirements document provided a more descriptive narrative of user requirements. It outlined 5 requirements — each with a User Story and Acceptance Criteria. See the image below for one example of how Requirements are defined.
Lastly, the tasks document provided a thorough plan for specific development tasks and a suggested completion order. It offered a great way to stay organized and feel a sense of accomplishment by checking tasks off as I finished them.
The Django Backend
With tasks.md in place, I could finally begin development. The first step was setting up the Django backend. It was easiest to define the models I needed and start getting that logic and the API endpoints connected before pursuing the frontend.
While I knew I needed to provide logic for Pinecone and OpenAI, I choose to first start with the foundational tech stack:
- Framework: Django 4.0+
- API: Django REST Framework
- Database: SQLite (dev) / MySQL (production)
- Tags: django-taggit
- CORS: django-cors-headers
To do (coming in part III):
- Vector DB: Pinecone
- AI: OpenAI (embeddings & chat)
Like any application, this allowed me call the generic API endpoint to get all of the styles on the frontend so I could begin making the proper connections before jumping into the AI portion.
As a side note, Kiro is happy to setup the apps and all of the code itself, if you choose. I decided to only prompt it when I was stuck. This application would have likely been completed sooner had I “vibe coded” the entire thing, but I prefer to understand the code and have some sense of control over the output. So, I like to think of Kiro as more of an assistant that I could collaborate with when needed.
The final structure for the Django backend is:
Next up: Next.js
After defining the basic setup for the backend, I chose to hold off on any of the AI integration and dive into my favorite part: the frontend.
I knew I wanted to use React, but was open to using either Tanstack Start or Next.js. Since I was most familiar with Next and wanted to keep most of my learning geared toward the AI integration, I chose to take the path of least resistance with Next.
I used the following for the frontend:
- Framework: Next.js 15 with App Router
- Language: TypeScript
- Styling: Tailwind CSS 4
- State Management: Zustand
- Data Fetching: TanStack Query (React Query)
- Icons: Font Awesome
- Image Lightbox: Yet Another React Lightbox
While most of the frontend tech was familiar to me, I added a lightweight and easily customizable third-party lightbox app to showcase different hairstyle views. I also installed Zustand for state management. Although I had not used Zustand in the past, it seemed like a great option for a smaller application and has been gaining popularity due to its simpler syntax than Redux.
The frontend is where I feel my creativity and user-centric approach really shines. As the app evolved, I added UI features like favorites and light/dark mode.
The final frontend structure is below:
With both the basic backend and frontend defined, we can move onto the AI integration. In Part III, we’ll explore the showstopper: the Pinecone and OpenAI integration!
If you’re interested in reviewing the code, feel to review the repos below: