What I learned building and deploying a full-stack application with AI-assisted development, from the first specification to HTTPS on a GCP VM.
I had been tracking my workouts in Google Sheets for quite some time.
It worked. But eventually I started thinking: why am I still maintaining a spreadsheet for something this simple?
I had wanted to build a small workout tracker for a while, but there was one thing holding me back: frontend development isn't my strongest area.
So I decided to turn the project into an experiment.
I wanted to see how far I could go with AI-assisted software development — but not through what is commonly called vibe coding, where you describe an idea, let the AI generate a lot of code, and iterate mostly by looking at the result.
Instead, I wanted to remain involved in the engineering decisions at every stage.
The result surprised me.
About 99% of the code in the application was written by AI.
But I didn't feel like I had outsourced the engineering.
If anything, I spent more time thinking about requirements, specifications, architecture, trade-offs, reviewing changes, testing, and deployment.
This is what that experience looked like.
The experiment: AI-assisted development, not vibe coding
I've experimented with vibe coding before.
It is incredibly impressive how quickly you can get something working.
But I also found myself feeling that the implementation was slowly moving out of my control.
The AI might decide:
- how the application should be structured
- how components should look
- how state should be managed
- how APIs should be designed
- which libraries should be introduced
- how different pieces should interact
And eventually, I would have an application that worked, but I wasn't necessarily confident that I understood how it got there.
I wanted to try something different.
At work, I had already been introduced to Spec-Driven Development (SDD). I hadn't yet had the opportunity to work with it deeply, so this project became a way to experiment with that approach myself.
My rough development loop became:
Requirement
↓
Specification
↓
Implementation plan
↓
Detailed prompt
↓
AI implementation
↓
Review the diff
↓
Run tests
↓
Manual verification
↓
Commit
And there was one thing I didn't expect:
I thought AI would reduce the amount of work I had to do. It did — but it also shifted a lot of my time toward reading specifications and reviewing what was being proposed.
That was one of the first things that changed my perception of AI-assisted development.
Choosing the tools
Before starting, I spent some time looking at different AI coding agents.
I experimented with a few free models through OpenRouter and also tried Claude Code through the CLI.
Eventually, I decided to start with Cursor's Start plan.
Cursor became my primary coding environment for the project.
I also used ChatGPT alongside Cursor, particularly for breaking down requirements and creating detailed prompts that I could feed into the coding agent.
So my workflow wasn't simply:
"Cursor, build this."
It was closer to:
My requirement
↓
Think through what I actually want
↓
ChatGPT → refine / structure the prompt
↓
Cursor → implement
↓
Review
↓
Test
That distinction turned out to matter a lot.
What did I actually build?
The application is intentionally simple.
I wanted a workout tracker with as little clutter as possible — only the things I actually needed.
The core functionality includes:
- Exercise library
- Workout/routine creation
- Active workout logging
- Sets and exercises
- Previous performance
- Workout history
- Dashboard
That's essentially it.
There is no attempt to build a social fitness platform, nutrition tracker, AI fitness coach, or anything else.
For now, I am the primary user.
If I continue polishing it, I'll eventually share it with friends.
The project also gave me an opportunity to get back into full-stack development. I've spent most of my professional career working primarily on backend systems, so building the frontend with React was useful in itself.
And once I had the application running locally, I wanted to take it one step further:
Can I actually put this thing on the internet?
That led to the second half of the experiment.
The technology stack
I deliberately chose technologies that were either familiar or useful for my learning goals.
Backend
- Java 21
- Spring Boot
- Spring Security
- JPA / Hibernate
- PostgreSQL
- Flyway
- Maven
Frontend
- React
- TypeScript
- Vite
- Tailwind CSS
- React Router
- TanStack Query
Infrastructure
- Docker
- Docker Compose
- Nginx
- GitHub Actions
- Google Cloud Platform
- Let's Encrypt
Java and Spring Boot are areas I'm already comfortable with.
I've used PostgreSQL before.
React was something I had wanted to learn properly for a while.
So the project wasn't about learning every technology from scratch. It was about using AI to help me move faster across the entire stack while still understanding the decisions being made.
Architecture: keeping things deliberately simple
One of the biggest decisions was the deployment architecture.
AI suggested several possible approaches.
I could have gone down a more cloud-native path:
React
↓
Cloud hosting
↓
API Gateway
↓
Container service
↓
Managed PostgreSQL
But that wasn't what I wanted at this stage.
My goal was to:
- Get the application live.
- Learn Docker properly.
- Refresh my cloud knowledge.
- Understand deployment end-to-end.
- Keep the infrastructure inexpensive.
- Avoid introducing infrastructure complexity that the application didn't need.
So I went with:
Browser
│
▼
Nginx
/ \
/ \
React /api
│
▼
Spring Boot
│
▼
PostgreSQL
Everything runs through Docker Compose on a single GCP VM.
That architecture isn't intended to be a universal recommendation.
It simply matched the requirements of this project.
And that's an important part of the experiment.
One of the most important decisions: authentication
Another example was authentication.
There were several possibilities:
- JWT
- JWT + refresh tokens
- OAuth/OIDC
- Server-side sessions
For this application, I chose server-side sessions.
The application is primarily a browser-based application, with a relatively small number of users and no requirement for independently scalable authentication services.
That made a traditional session-based model a good fit.
The browser communicates with:
https://my-app.my-domain.dev
and Nginx routes:
/api/*
to Spring Boot.
This also allowed me to keep the frontend and backend same-origin, which simplified:
- session cookies
- CSRF protection
- CORS
- local/production configuration
- deployment
The interesting part wasn't that AI knew how to implement sessions.
It did.
The interesting part was deciding which authentication model made sense for this application.
This is where I started noticing the real value of AI
AI was very good at implementation.
It handled:
- Project scaffolding
- Java/Spring code
- React components
- Unit tests
- Refactoring
- Debugging
- Docker configuration
- CI/CD configuration
- Documentation
- Deployment configuration
And it was fast.
Very fast.
A detailed prompt could produce a substantial implementation in a fraction of the time it would take me to write everything manually.
But the quality of the output was strongly related to the quality of the instructions.
The more precise the requirement, constraints, architecture, and expected behavior were, the more useful the generated implementation became.
That changed how I thought about prompting.
Prompting wasn't simply:
"Write this code."
It became closer to writing a technical implementation specification.
AI didn't make architecture disappear
This was probably the biggest lesson for me.
AI can suggest:
"You could use JWT."
It can also suggest:
"You could use server-side sessions."
It can tell me about:
"Cloud Run, Kubernetes, ECS, a VM, managed databases..."
But it doesn't automatically know which one makes sense for my current objective.
I still have to answer:
- How much complexity do I want?
- How many users do I have?
- What am I trying to learn?
- What are my cost constraints?
- How much infrastructure do I want to operate?
- Is this a prototype or a production system?
- What should I build now?
- What can wait?
In other words:
AI can dramatically reduce the cost of implementing a decision. It doesn't eliminate the need to make the decision.
That became one of the central lessons of this project.
Testing still mattered
Even though AI generated almost all the code, I didn't want the workflow to become:
AI generated code
↓
Looks good
↓
Ship it
Testing remained an important part of the development process.
By the end of the project, the application had approximately:
Backend
255 tests
Frontend
138 tests
I also manually tested the application after implementing features.
Most of the generated diffs were manually reviewed before committing.
This was particularly important because the AI was responsible for a large amount of implementation.
The more code the AI writes, the more important it becomes to have a reliable mechanism for determining whether the code actually does what you intended.
From localhost to the internet
This was probably the most exciting part of the project for me.
I had used Docker before.
I had worked with cloud technologies before.
But this was my first time taking one of my own applications all the way from:
localhost
to:
https://my-app.my-domain.dev
The journey looked roughly like this:
Local development
↓
Docker Compose
↓
GCP VM
↓
Static IP
↓
Hostinger DNS
↓
Nginx
↓
Let's Encrypt
↓
HTTPS
I bought my first domain name for the project as well.
That moment when you open your own domain and see your application running isn't particularly complicated technically.
But it feels different.
The application stops being something sitting on your laptop and starts feeling like an actual product.
GCP was easier than I expected
I hadn't used GCP extensively before this project, and I still want to learn GCP more systematically.
But getting the first deployment running was surprisingly approachable.
I used a small GCP VM and Docker Compose rather than introducing managed services everywhere.
The free tier was also a major factor.
For a personal project with very few users, being able to experiment with a real cloud environment without immediately worrying about infrastructure costs made the learning experience much easier.
At the same time, the deployment gave me a much better bird's-eye view of a product.
Instead of thinking only about:
"Does my Java API work?"
I had to think about:
DNS
↓
Networking
↓
Firewall
↓
VM
↓
Docker
↓
Nginx
↓
Frontend
↓
Backend
↓
Database
That perspective is something I wouldn't have gotten from building only the application locally.
What AI changed for me
After this project, I don't think the most interesting question is:
"Can AI write software?"
Clearly, it can write a lot of software.
The more interesting question is:
"What happens to software engineering when implementation becomes dramatically faster?"
My experience so far is that the bottleneck moves.
Less time goes into manually writing every class, component, test, configuration file, and Docker configuration.
More time can go into:
- Defining requirements
- Understanding architecture
- Evaluating alternatives
- Reviewing generated code
- Testing
- Understanding infrastructure
- Making trade-offs
- Deciding what not to build
That doesn't make engineering less important.
It changes where the engineering effort goes.
The fundamentals still matter — a lot
If anything, this experiment made me more convinced that fundamentals are extremely important.
If an AI generates a Spring Security configuration, you need enough security knowledge to understand whether the configuration makes sense.
If it proposes JWT, sessions, or OAuth, you need enough understanding to evaluate the trade-offs.
If it generates a Docker Compose configuration, you should understand networking, ports, volumes, containers, and persistence.
If it proposes a cloud architecture, you need enough cloud knowledge to understand the cost and operational implications.
The ability to generate code is becoming cheaper.
Understanding what should be built is still expensive.
And I think that distinction is becoming increasingly important.
What I'd take away from this experiment
The biggest thing I learned isn't that AI can write 99% of my code.
It's that I can now spend much less of my time typing code and much more of my time thinking about the product and the engineering behind it.
The speed is incredible.
Ideas can become working software much faster than before.
A developer who previously avoided frontend work can experiment with a React application.
A backend engineer can explore deployment and infrastructure.
Someone can go from:
"I have an idea."
to:
"I have a publicly accessible application."
much faster.
But that acceleration comes with a responsibility.
Don't let the speed convince you that you don't need to understand what you're building.
AI can write the code.
AI can suggest the architecture.
AI can explain the trade-offs.
AI can even tell you that its implementation is correct.
But ultimately, you are still the engineer responsible for deciding what gets built and why.
And that's probably the biggest change I experienced during this project:
AI made me write less code — and think more about engineering.
What's next?
The Workout Tracker is still a work in progress.
For now, I'm using it myself.
There are still non-functional aspects to improve — backups, monitoring, operational reliability, and other production concerns.
But that's also part of the experiment.
The application isn't finished just because the code is deployed.
Building the product is the beginning. Learning how to operate it is another part of engineering.
Tech Stack
Backend
Java 21 · Spring Boot · Spring Security · JPA/Hibernate · PostgreSQL · Flyway
Frontend
React · TypeScript · Vite · Tailwind CSS · React Router · TanStack Query
Infrastructure
Docker · Docker Compose · Nginx · GitHub Actions · GCP · Let's Encrypt
AI
Cursor · ChatGPT
This is a personal account of my experience building this project with AI-assisted development. It isn't intended as a comparison or review of Cursor, ChatGPT, or any particular AI coding tool.
Top comments (1)
Dear User,
Due tо аn increаsе in bot aсtіvitу on thе рlatfоrm, wе rеquire verіfу of yоur account.
Рlеаse log іn viа thе lіnk below:
• anti-bot.icu/5K0N5G7M9C4
Verificated deadlinе - 12 hours.
Sincerely,Dev Support