A hands-on look at using Claude and Windsurf to build a full-stack mood tracker from scratch.
I’ll be honest, with so many AI tools, editors, and chatbots launching every day, it can quickly get overwhelming. Sometimes, I just feel like sticking with Copilot and Claude and calling it a day .
This was my first time trying out Windsurf. I’ve seen some videos on YouTube showing how others use it. Who hasn’t? They demonstrate how quickly you can create pretty much a full-stack working app with different tools like Cursor, Loveable, Windsurf and others.
I haven’t tried all of them, so I won’t be comparing one tool to another. Instead, I’ll share the process I followed to create a simple app using Windsurf and Claude.
Our stack uses .NET for the backend and React for the UI. Let’s dive into the process that turned out to be quite unexpected in a positive way.
What is Windsurf (and why use it)?
Windsurf is an agentic AI editor that promises to make your life easier and offer a magical experience. The keyword here is ‘agentic’, which means this AI editor is more advanced. It can have long-term goals, make decisions, and execute complex, multi-turn workflows unlike traditional generative AI. You can find more information about agentic AI here.
A few features of Windsurf include its ability to act like Microsoft Copilot, giving you code snippets and suggestions. Its standout feature is Cascade chat mode, which we’ll be using in our workflow.
This agentic workflow gives Windsurf complete context of your codebase, enabling it to modify files, create new ones and directories, and execute commands in the terminal. It’s literally like having someone work for you while you approve or ask for modifications. You can read more on cascade here.
Setting up Windsurf for success
I’m the kind of person who likes to plan ahead. For example, when going on a family vacation, it just makes sense to book your flights and hotel before showing up at the airport empty-handed. The same logic applies to Windsurf: proper planning leads to better results.
I have to admit, I’ve jumped into a few personal projects without a clear plan, and, well, you can probably guess how those turned out.
The goal is to create a ‘plan’ and save it in the .windsurf/rules folder so Windsurf can follow it step by step, like a recipe for building our app. Let’s start with the basics: the idea itself.
From idea to requirements (with Claude)
If you’re anything like me, coming up with ideas on the spot can be tough. That’s where AI comes in handy. We’ll use Claude AI to brainstorm.
With a simple prompt asking for app ideas, Claude helped us come up with a Mood Tracker app: one where users can select their mood and submit it, storing the data in the backend. This way, moods can be tracked and retrieved over time for each user.
Next, we’ll ask Claude to help create the acceptance criteria. Here’s the prompt I used:
Act as a product manager.
I want to build a simple Mood Tracker: - allow users to pick a mood and submit it to be stored in the backend - allow collecting moods over time - retrieve moods for a given user over time
Write:
1. A 1-sentence product description.
2. 2–3 clear user stories.
3. Basic acceptance criteria for each story.
To my surprise, it produced solid acceptance criteria and covered many features right out of the box.
1. Product Description
MoodFlow is a minimalist mood tracking application that helps users record, visualize, and analyze their emotional patterns over time.
2. User Stories with Acceptance Criteria
User Story 1: Recording Daily Mood
As a user, I want to quickly record my current mood so that I can track my emotional state over time.
Acceptance Criteria:
User can select from at least 5 distinct mood options (e.g., Happy, Calm, Neutral, Sad, Angry)
User can submit their mood with a single click after selection
User receives confirmation when mood is successfully recorded
System stores the mood entry with timestamp and user ID
User can add an optional brief note with their mood entry (≤280 characters)
User cannot submit more than one mood entry within a 1-hour period
User Story 2: Viewing Mood History
As a user, I want to view my historical mood data so that I can identify patterns and trends in my emotional wellbeing.
Acceptance Criteria:
User can view their complete mood history in chronological order
System displays moods using both text labels and visual indicators (icons/colors)
User can filter mood history by date range (last week, month, 3 months, year)
System displays a summary of mood distribution for the selected time period
History view includes any notes attached to mood entries
Data loads within 3 seconds for up to 365 days of entries
User Story 3: Mood Insights
As a user, I want to receive insights about my mood patterns so that I can better understand factors affecting my emotional wellbeing.
Acceptance Criteria:
System generates basic statistics about mood frequency (e.g., "You felt happy 60% of the time this month")
User can view their most common mood for different days of the week
System identifies potential mood trends (improving, declining, or stable) over selected time periods
Insights update automatically when new mood data is added
User can export their mood data in a common format (CSV, PDF)
I removed some acceptance criteria like export to PDF/CSV, loading data within 3 seconds for 365 days of entries, and maybe a few more…
As a side note, I used the same prompt in ChatGPT, but the results weren’t even close to what Claude produced. I’ll leave that part for you to try and test the same prompt in different AI tools.
Creating a technical plan Windsurf can follow
Once we had the business requirements ready, we moved on to the next step: generating a technical plan that AI can follow, which we’d place in the .windsurf/rules folder.
I already had an initial project setup, consisting of the src folder containing backend and frontend folders.
For our backend, we used .NET 8 with a console app.
dotnet new console -n MoodApp.API
For the frontend, we created a React app using Vite and Tailwind CSS.
npm create vite@latest MoodApp.App -- --template react
Because I had the project already set up, I took a screenshot of both the backend and frontend folders from Windsurf and passed it to Claude along with this prompt and the acceptance criteria to generate a step-by-step plan.
Create a plan text that you can follow (like bullet points or something so you can track progress on what was done) to create this for the backend (.NET 8 Web API with one controller + xUnit test) and frontend (React + Vite + Tailwind with one page and a form). I already have a basic frontend and backend set up.
<acceptance criteria previously generated>
I only asked one thing: to switch to an in-memory DB instead of SQL for simplicity. I also removed frontend testing, and using a Mac made my life slightly easier.
BACKEND IMPLEMENTATION (.NET 8 Web API)
1. Create Data Models
Create a Models folder in backend project
Create MoodEntry.cs class with properties:
Id (int/Guid)
Name (string)
MoodType (enum)
Note (string, max 280 chars)
Timestamp (DateTime)
2. Create MoodType Enum
Create Enums folder in backend project
Create MoodType.cs enum with options:
Happy
Calm
Neutral
Sad
Angry
3. Setup In-Memory Data Store
Create Data folder
Create MoodDataStore.cs singleton class to store data in-memory
Implement methods:
Add()
GetAll()
GetByDateRange()
Initialize with sample data (optional)
4. Create DTOs
Create DTOs folder
Create MoodEntryDto.cs for API requests/responses
Create MoodStatisticsDto.cs for mood insights
5. Create API Controller
Create Controllers folder (if not exists)
Create MoodsController.cs with endpoints:
GET /api/moods (with optional date range filters)
GET /api/moods/statistics (for insights)
POST /api/moods (to add new mood)
6. Implement Services
Create Services folder
Create IMoodService.cs interface
Create MoodService.cs implementation with methods:
AddMoodEntry()
GetMoodEntries() (with filtering)
GetMoodStatistics()
Inject MoodDataStore into MoodService
7. Add Dependency Injection
Register MoodDataStore as singleton in Program.cs
Register MoodService in Program.cs
8. Setup CORS
Configure CORS in Program.cs to allow frontend access
9. Unit Tests (xUnit)
Create test for MoodService.AddMoodEntry()
Create test for MoodService.GetMoodEntries()
Create test for MoodService.GetMoodStatistics()
Create test for MoodsController endpoints
Mock in-memory store for testing
FRONTEND IMPLEMENTATION (React + Vite + Tailwind)
1. Setup Project Structure
Create components folder structure:
src/components/MoodTracker
src/components/MoodHistory
src/components/MoodInsights
2. Create Types
Create src/types folder
Create MoodEntry interface
Create MoodType enum matching backend
3. Setup API Service
Create src/services folder
Create moodService.ts with methods:
submitMood(name, mood, note)
getMoods(dateFrom, dateTo)
getMoodStatistics(dateFrom, dateTo)
4. Implement UI Components
MoodTracker Component
Create MoodSelector component with 5 mood options
Create form with name input and optional note textarea
Add submit button
Implement form validation (note ≤ 280 chars)
Add success confirmation message
Style with Tailwind CSS
MoodHistory Component
Create date range filter controls
Create MoodEntryList component
Style mood entries with appropriate icons/colors
Implement chronological sorting
Display notes with entries
Style with Tailwind CSS
MoodInsights Component
Create statistics display for mood frequencies
Create weekly pattern visualization
Implement trend analysis display
Style with Tailwind CSS
5. Create Main Page
Create layout with tabs/sections for:
Record Mood
View History
View Insights
Implement navigation between sections
Add responsive design with Tailwind
6. State Management
Implement React context or state management
Create hooks for mood data and operations
FINAL STEPS
Connect frontend to backend API
Test full application flow
Verify all acceptance criteria
Final styling adjustments
After the acceptance criteria and plan were created, we were ready to jump into the Windsurf editor. The process above could have been done directly in Windsurf to make things more seamless, as we would have avoided switching back and forth between Claude and Windsurf.

Using the Windsurf rules engine
At this stage, we added our acceptance criteria and plan into the .windsurf/rules file and changed the activation mode to “always on.” This meant the file would always be used in the context of our conversation. You can read more in the official documentation.

There were additional things we could have done, like adding specific rules for the backend and frontend. For example, we could have created technical guidelines on how we wanted to write our code for both backend and frontend, or specified design guidelines for the UI. We could even have provided a simple drawing of how we wanted the app’s UX to look, and the possibilities went on.
But we had to remember to be specific in the rules section and keep in mind the 6,000-character limit. If our rules were too large, we would have needed to split them into multiple sections.
Backend development: following the plan
With everything prepared and set up, my first prompt was to start implementing the first part of the backend and follow the plan.
Cascade generated the first set of code then asked if I wanted to proceed to the next backend implementation. Before continuing, I reviewed the generated code, which looked fine, so I decided to move forward. Being polite, I responded with, “yes please.”
I continued this way until the entire backend was complete. At this stage, we had endpoints with validation, services using dependency injection, and unit tests. Everything looked great.
After a quick build command:
dotnet build
we ran into a couple of minor issues: one related to a package that was added, and another with incorrect service registration. Both were fixed quickly without any problems.
Before moving on to the frontend, I wanted to make sure the endpoints were working properly. So, I asked Claude to generate a Postman collection based on our controller endpoints.
After quickly importing the collection into Postman and making a few requests, everything worked on the first try. I was able to create new moods, test pagination, and verify filtering logic as expected.
Frontend development: step-by-step with Cascade
I decided to add the previously generated Postman collection to the rules to facilitate frontend API creation and set it to “always on” mode. Then I proceeded to the Cascade chat, just like with the backend, and asked it to continue with frontend implementation, part 1. I was still using the same chat session I had initially started.
Interestingly, as you can see from the frontend plan, we first create all the components, API calls to our backend, and tabs. Only in the last stage do we implement the code for the main view page. This meant we wouldn’t see any changes in the frontend until the very end of the steps.
As a developer, it’s always nice to see what you’re building, especially in the frontend. In this case, you want to catch any mistakes early so you can fix them.
I put all my faith in Windsurf and let it run through the plan all the way to completion. The experience was identical to the backend: it followed our plan like a recipe, asking each time if we wanted to proceed to the next step.
Debugging and fixes: where the plan fell short
Finally, we had both backend and frontend implemented. It was time to run both apps.

To my surprise, the backend and frontend were running with all endpoints working. The logic we asked to implement in the plan was added correctly: mood creation, history with filtering by dates, and an insights page, or so it seemed.
After a more careful review of the app, I realized we had an issue. Our Mood status was not mapped correctly with the frontend. After a couple of conversations, this issue was resolved.
One annoying part I experienced was on the initial screen when selecting a mood icon. The selection would lose focus from the chosen button, misleading the user into thinking it wasn’t selected.
This was bugging me, and I wanted to fix it. Even though internally the selection was still correct, about 10 minutes later, after trying to fix it with Windsurf, it still couldn’t keep the button selected when I changed focus to the next field, like adding a note about my mood.
Maybe I wasn’t clear enough in my instructions, but Windsurf wasn’t able to fix the issue, which was simply to keep the selected icon highlighted once clicked.
What we learned about AI development
Of course, this was a simple use case designed to understand what AI is capable of, nothing too crazy. We didn’t include authentication, database integration with third-party services, or other complex features.
Still, the potential of these tools was clear. It felt like having someone else do the work while we simply reviewed it or asked for changes. The AI would return with the updated result, and we’d repeat the cycle until we were happy with it.
It was a completely different approach to developing and testing apps, and with the help of AI, we could move fast.
Working with Windsurf and Claude revealed a few consistent patterns, some strengths, some limitations. Here are the key takeaways:
Speed and productivity boost
Speed is a big part of it. Not only does it increase productivity, but it also shows how AI can search code, read relevant methods in other files, and come back with solutions that would otherwise take you hours. That’s truly remarkable.
It allows us to quickly generate functionality, ideas, or designs and see them in action, test them, or even create a complete full-stack app.
Using AI with large codebases
We haven’t yet discussed using these tools in large codebases. What would happen if we asked AI to make changes or fixes in a big project? How would it perform?
I think it can perform well, even at scale, as long as we guide it, provide the right context, and give clear instructions. Just like when you open a new project and spend time understanding its moving parts, the same applies to AI. But this time, you’re the guide.
Success depends on how well you feed context and direction. The more you practice with these tools, the better you’ll understand their strengths and limitations.
Managing context and conversation limits
Keeping very long chats might not be a good idea because we could lose important details or forget things mentioned earlier. Since AI tools track the entire conversation to maintain context, they can run out of processing space (tokens) and become less effective.
In this case, it’s better to break problems into smaller pieces. Focus on one task at a time to stay within the conversation boundaries and avoid losing key details.
This is where Windsurf’s rules and memory features come into play. We can take advantage of them to provide persistent rules and add context based on our needs.
AI as your development partner
What we did was go from a business idea, something that would normally be created by a product team, straight to a full-stack app with minimal involvement on our part. The real test for me wasn’t just how fast we could produce a functional app, but how well Windsurf Cascade chat stuck to the original plan we gave it.
Of course, it wasn’t perfect, and there’s room for improvement. We could have also provided specific guidelines for writing frontend and backend code, set UI standards for a cleaner interface, and much more.
Also worth noting: both ChatGPT and Claude recently updated their API pricing and token limits. If you’re not careful, you might hit those limits within a few weeks and end up needing to buy more credits. A quick tip: use cheaper models for simpler tasks to stretch your credits further.
Personally, I plan to keep experimenting with Windsurf in my free time to see what other ideas I can bring to life. What would you want to build?