A story about getting back into frontend development after a year-long break, getting humbled by a currency picker, learning Zustand, using AI as a development partner, and eventually shipping something I was proud of.
It took me exactly one month to build a currency converter.
That sounds like a strangely long time for what is, on paper, a relatively straightforward frontend project. But this isn't really a story about how long it took to build a currency converter.
It's about what happened before I started building it.
Why this project mattered to me
Before starting this project, I had been away from development and studies for almost a year.
I was diagnosed with Tuberculosis, and the following year became mostly about treatment, recovery, and getting my health back. The illness didn't just affect me physically. By the time I was ready to return to studying and development, I also found that concentration, consistency, and mental energy were much harder than they used to be.
I tried coming back several times.
I'd study for a week or two, maybe start feeling like I was getting back into the rhythm, and then I'd have to step away again. Eventually, I realised that waiting until I felt completely βreadyβ wasn't getting me anywhere.
So instead of spending months preparing myself to start building again, I decided to build something.
That something became FX Checker.
Technically, it's a currency converter built as a Frontend Mentor project. For me, it became a stepping stone back into development.
The project
FX Checker is a dark-themed currency conversion application with:
- π± Real-time currency conversion
- π Searchable currency picker
- π Historical exchange-rate charts
- π Multi-currency comparison
- β Favorite currency pairs
- π§Ύ Conversion history
- π‘ Live market ticker
- πΎ Persistent favorites and logs
- βΏ Keyboard-accessible interactions
- π± Responsive layouts
The challenge provided the UI requirements and design, while I had to work out the application logic, state management, API integration, data transformation, and the parts of the behavior that weren't explicitly specified.
And, as I discovered fairly quickly, βwork out the application logicβ contains a suspicious amount of work.
Before writing the first line of code
I didn't immediately open my editor and start throwing React components at the screen.
First, I reviewed several peer solutions from the Frontend Mentor community.
I wanted to see:
- How other developers interpreted the requirements
- How they structured their projects
- Which technologies they used
- How they approached the different features
- How they solved problems that weren't explicitly specified in the challenge
This helped me understand the scope of the project before making architectural decisions myself.
I also used LM Arena to brainstorm the initial project structure, features, possible implementation approaches, and technology choices.
After that, I decided to keep the stack relatively lightweight:
React
Vite
JavaScript
Tailwind CSS
Zustand
I deliberately chose JavaScript instead of TypeScript for this project.
Not because I don't want to learn TypeScript. I do.
I simply wanted this project to focus on getting comfortable with frontend development again without introducing another layer of complexity while I was already trying to shake off a year of rust.
The tools
For the early stages of the project, I experimented with several AI-assisted development setups.
My initial development setup was:
Zed + Ollama + GPT-OSS
I also experimented with Google Antigravity + Gemini during the early development.
And yes, I was absolutely trying to squeeze every available free AI tool for everything it was worth. π
Later, I also used Amazon Q and ChatGPT for different parts of the project.
The important thing, though, was that I didn't want AI to simply generate the entire application for me.
I wanted to understand the decisions behind the code.
That distinction became increasingly important as the project became more complicated.
The currency picker humbled me
I started by building the live market ticker and then moved into the converter.
The converter itself seemed straightforward.
Then I reached the currency picker.
It looked innocent.
It was not innocent.
The requirement sounded simple enough:
Search currencies, display them in a dropdown, show flags, allow selection.
Simple, right?
Apparently not.
I tried multiple approaches, became increasingly unhappy with the results, and eventually got overwhelmed by the amount of UI and state logic involved.
So I took a break from the project. A few days later, I came back and approached the problem differently.
I explored the available shadcn/Base UI components and eventually designed a custom currency picker with help from Amazon Q.
One of the things I learned here was that sometimes the problem isn't actually difficult. The way I'm approaching it is.
Instead of thinking:
βI need to build this entire currency picker.β
I started thinking about smaller problems:
Breaking it down made the problem much more manageable.
Then Zustand entered the chat
The next thing that intimidated me was global state.
The application had shared data for things like:
- Currencies
- Converter state
- Exchange rates
- Favorites
- Comparison rates
- Historical rates
- Conversion logs
- Loading states
- Error states
At first, the idea of putting all of this into a store felt overwhelming.
I initially had to step away from the project again because there was simply too much new information to process at once.
When I returned, I decided to stop trying to understand the entire store at once.
I started constructing it around the actual features. Eventually, the store became one of the parts of the project I'm most proud of.
The general flow became something like:
And later, during refactoring, I split the store into feature-based slices:
- Currency
- Converter
- Favorites
- Compare
- History
- Log
This helped me understand something that I had previously found confusing:
State management isn't just about deciding where data lives. It's also about deciding who owns that data and who should be responsible for changing it.
Learning to keep moving
Once I had the store structure working, I deliberately stopped trying to attack the most intimidating feature first.
Instead, I worked on the parts that felt more manageable.
I started with:
- β Favorites
- π§Ύ Conversion log
- π Compare
This was a small but important change in how I approached the project.
Instead of asking:
βWhat's the most impressive thing I should build next?β
I started asking:
βWhat's the next problem I can reasonably solve?β
That made it much easier to maintain momentum.
Then came the History Tab π
The History tab was probably the feature that required the most reasoning.
It needed:
- Multiple date ranges
- Historical API data
- Open and last rates
- Absolute change
- Percentage change
- A time-series chart
- Different grouping for longer ranges
- Loading and error states
- Responsive chart behavior
- A custom tooltip
The data flow eventually looked roughly like this:
This was where I started thinking less about individual components and more about data flow.
I had to decide:
- What belongs in the store?
- What should be calculated in a helper?
- What should be derived from existing data?
- What should the component actually be responsible for?
That distinction became one of the biggest lessons from the project.
Refactoring what I had built
Once all the features were working, I stopped adding features. Instead, I went back through the code. The first version of the application worked, but:
βIt worksβ and βit's pleasant to maintainβ are not the same thing.
I started restructuring the History feature into smaller components:
HistoryTab
βββ HistoryStats
βββ DateRangePicker
βββ HistoryChart
βββ Tooltip
βββ HistoryTabSkeleton
I also refactored the Zustand store into feature-based slices.
Instead of one large store responsible for everything, each slice handled a particular part of the application's state. This made the code easier to reason about and also made the responsibilities of different parts of the store much clearer.
And then I broke the chart
Naturally.
Because no development story is complete without introducing a bug while trying to make the code better.
At one point, after refactoring the store, the chart completely disappeared.
The API was working.
The component was rendering.
Recharts was innocent.
The problem was a small mistake in one of my Zustand slices.
I had accidentally reversed the parameter order:
(get, set)
instead of:
(set, get)
One tiny mistake resulted in a very impressive amount of empty screen.
After finding the problem, I standardized the slices and continued.
The lesson was simple:
Refactoring isn't just about making code shorter or prettier. You have to preserve the behavior while changing the structure.
Accessibility was part of the process too
The challenge required hover and focus states, but while working through the UI I also started paying more attention to keyboard navigation.
This led me to think about things like:
- Which elements should be keyboard accessible?
- What should receive focus?
- How should focus states look?
- What happens when the user navigates through the tabs with
Tab? - How should custom interactive components behave?
I initially ran into some interesting focus-outline issues with the tabs and chart.
Fixing them made me realize how easy it is to think about accessibility only after the UI is finished.
It's much better to consider it while building the interaction itself.
AI was involved. A lot. π€
AI tools were used throughout this project, but I tried to use different tools for different purposes.
LM Arena
Used mainly during the planning stage for:
- Brainstorming
- Initial architecture ideas
- Feature planning
- Technology choices
- Exploring different implementation approaches
Zed + Ollama + GPT-OSS
Used during the early development stages to help build the initial application structure and features.
Google Antigravity + Gemini
Used as another development assistant during the early stages of the project.
Amazon Q
Used for:
- Debugging
- Building the custom currency picker
- Working through the initial Zustand store structure
ChatGPT
Used more heavily during the later stages for:
- Debugging
- Architectural discussions
- Feature logic
- Refactoring
- Reviewing implementation decisions
- Thinking through edge cases
- Performance considerations
One thing I deliberately tried to do was use AI more like a senior developer I could discuss problems with, rather than simply asking it to write the entire project.
When I was learning Zustand, for example, I often wanted an explanation of why a particular approach made sense before implementing it.
That made the process much more useful for me.
It also made one thing painfully obvious:
My prompting still needs work.
I want to get better at providing technical context, constraints, expected behavior, and terminology so that I can get more precise answers instead of making the AI play detective with half the evidence missing. π
What I actually learned
The obvious answer would be:
βI learned React, Zustand, Recharts, APIs...β
But that isn't really what stands out to me.
The bigger lesson was learning how to approach problems when I don't immediately know the answer.
I learned to:
- Break large problems into smaller ones
- Separate application logic from presentation
- Think about where state should live
- Distinguish API data from derived UI data
- Handle loading and error states deliberately
- Think about edge cases that aren't explicitly mentioned in requirements
- Refactor working code instead of being afraid to touch it
- Use browser DevTools more systematically
- Ask better technical questions when I need help
- Use AI as an assistant without completely outsourcing the thinking
I also became much more comfortable with Zustand and asynchronous data fetching. The store and data-fetching architecture is probably the part of the project I'm most proud of.
But there is another thing I gained from this project that isn't really technical.
Confidence.
After spending so long away from development, I wasn't sure how quickly I would be able to get back into building things.
There were several moments where I got overwhelmed and stepped away from the project.
But I came back.
Then I got stuck again.
Then I came back again.
Eventually, the project was finished.
Technically, it's a Frontend Mentor currency converter.
For me, it became a stepping stone back into development. It gave me confidence that I am capable of developing, learning, and most importantly, I had lost hope of even getting a job as a developer. Now, after completing this project, I can say I have got those skills, and I can work harder in honing them.
And that makes it considerably more important to me than its feature list would suggest.
What took a month?
After finishing the project, I checked the Git history.
My initial commit was:
July 9, 2026
And I finished roughly a month later. So yes.
I spent an entire month building a currency converter. π
But looking back at the process, I'm actually glad it took that long. It wasn't a month of nonstop coding.
It was more like:
And honestly, that feels much closer to real development than those tutorials where someone builds an entire SaaS application in 14 minutes and somehow remembers every API from memory.
What's next?
Now that I've regained some confidence and brushed up my frontend skills, there are a few things I want to focus on next.
π§ Strengthen React fundamentals
I want a deeper understanding of:
useEffectuseMemouseRef- Hooks
- Rendering and rerendering
- Component lifecycle concepts
- State and derived state
I don't want to simply know how to use a hook.
I want to understand why and when I should use it.
π Improve debugging
I want to become more comfortable debugging problems myself before asking an AI assistant to point out exactly where I've gone wrong.
That means getting better at using:
- Browser DevTools
- Network tab
- Console
- React DevTools
- Breakpoints
- Systematic debugging
π€ Get better at using AI
I don't want to use AI less.
I want to use it better.
I'd like to become better at using AI for:
- Brainstorming
- Exploring trade-offs
- Reviewing architecture
- Finding edge cases
- Code review
- Debugging
- Learning unfamiliar concepts
And I want to improve my prompts by providing better technical context, constraints, and terminology.
β±οΈ Build with more consistency
Taking breaks isn't inherently a bad thing.
But I want to get better at breaking overwhelming tasks into smaller pieces so that I can maintain momentum instead of disappearing from a project for several days whenever I hit a difficult problem.
Final thoughts
This wasn't the most complicated project I've ever imagined building.
It probably isn't even particularly complicated by professional frontend standards.
But I don't think projects need to be complicated to be meaningful.
This one reminded me that I can still sit down, learn something I don't understand, get stuck, debug it, refactor it, and eventually ship something.
That's what I wanted from this project.
And that's what I got.
One month. One currency converter. A ridiculous number of API requests. And hopefully, the beginning of getting back into development properly. π





Top comments (0)