A few months ago, I was mostly focused on strengthening my Python fundamentals.
Today, I have a working full-stack Business Intelligence platform called VISORA BI, built with Python, Pandas, FastAPI, React, Vite, REST APIs, automated testing, persistent datasets, reports, and AI-powered insights.
This post is about how I got from one point to the other.
Not just the final product.
The mistakes, architecture decisions, debugging, refactoring, testing, and learning process behind it.
The Starting Point: Strengthening My Python Foundation
Before starting VISORA BI, I wanted to make my Python foundation stronger.
I worked through the fundamentals instead of jumping directly into another large project.
The learning path covered:
- Variables
- Data types
- Conditions
- Loops
- Lists
- Tuples
- Sets
- Dictionaries
- Functions
- Input validation
- File handling
- JSON
At first, these looked like completely separate concepts.
But building small programs started showing me something important:
Programming becomes much easier when you stop thinking about individual syntax and start thinking about systems.
I moved from simple exercises to projects involving:
- Shopping/cart logic
- Student record management
- A mini banking system
- User and admin permissions
- Transactions
- JSON persistence
- Functions and modular code
One of the important lessons from the banking project was that architecture matters even in small programs.
Instead of putting everything inside one huge loop, I started separating responsibilities:
def main_menu():
...
def user_dashboard():
...
def admin_dashboard():
...
def check_balance():
...
def deposit_money():
...
def withdraw_money():
...
That way of thinking became extremely useful later when VISORA BI became much larger.
Moving From Python Learning to Data Analysis
After strengthening Python, I moved toward data-focused development.
I spent time revising Pandas and practicing data manipulation because I wanted to eventually work toward Machine Learning and AI engineering.
That raised a question:
If I can load a dataset and analyze it with Python, why not build an actual product around that?
And that was the beginning of VISORA BI.
The Idea Behind VISORA BI
The problem was simple.
A CSV file can contain valuable information, but a raw dataset doesn't immediately tell a business user:
- What does this data look like?
- How many rows and columns are there?
- Which columns are numeric?
- Which are categorical?
- Are there missing values?
- What are the important patterns?
- What should I actually pay attention to?
I wanted to build something that could take a dataset and turn it into a more understandable analytical workspace.
That became:
VISORA BI
A full-stack Business Intelligence platform for dataset analysis, analytics, AI-powered insights, and reporting.
From a Simple Idea to an Actual Architecture
The project gradually evolved into a proper full-stack architecture.
The final architecture looks roughly like this:
VISORA BI
|
+---------------+---------------+
| |
React + Vite FastAPI
Frontend Backend
| |
| REST API Layer
| |
| +------------+------------+
| | |
| Data Layer Report Layer
| | |
| Pandas Persistence
| |
+------------- Analytics -------------+
|
AI / Insights
The frontend communicates with the backend through REST APIs.
The backend handles:
- Dataset registration
- Dataset profiling
- Analysis
- Reports
- History
- Insights
Python and Pandas handle the actual analytical work.
Why I Chose FastAPI
I wanted the backend to be Python-based because Python was already becoming the center of my learning path.
FastAPI gave me a clean way to expose the analytical pipeline through APIs.
The application eventually had routes such as:
GET /api/v1/health
GET /api/v1/overview
GET /api/v1/datasets
POST /api/v1/datasets
GET /api/v1/datasets/{dataset_id}
DELETE /api/v1/datasets/{dataset_id}
POST /api/v1/datasets/{dataset_id}/analyze
GET /api/v1/reports
GET /api/v1/reports/current
GET /api/v1/reports/{dataset_id}/text
GET /api/v1/insights
POST /api/v1/history/clear
This was a major shift from writing standalone Python scripts.
Now I had to think about:
- API contracts
- Request/response structure
- IDs
- Persistence
- Frontend communication
- Error handling
- Application state
The Frontend
For the frontend, I used:
- React
- Vite
- JavaScript
- REST API integration
The goal wasn't just to make a page that looked good.
The frontend needed to represent an actual workflow.
The main areas became:
- Overview
- Datasets
- Analytics
- Insights
- Reports
- Settings
A user should be able to move through the application naturally:
Upload Dataset
↓
Dataset Registration
↓
Dataset Profiling
↓
Run Analysis
↓
Analytics
↓
AI Insights
↓
Reports
That complete workflow became one of the most important parts of the project.
Dataset Profiling
When a dataset is uploaded, VISORA BI performs structural analysis.
Instead of simply saying:
"Your file was uploaded."
the system starts understanding the dataset.
Things such as:
- Rows
- Columns
- Column types
- Numeric columns
- Categorical columns
- Missing values
- Dataset structure
are surfaced to the user.
This was one of the first places where Pandas became more than something I was learning from tutorials.
It became part of an actual application pipeline.
Analytics
After profiling, the user can run analysis on the dataset.
The analytics layer turns the raw data into a more useful analytical view.
This includes metrics and visual analysis based on the structure of the uploaded dataset.
The important part was making the analytics work with the uploaded dataset rather than relying on hardcoded demo data.
That sounds obvious.
But making that work consistently across:
Upload
↓
Backend
↓
Persistence
↓
Analysis
↓
Frontend
was one of the more important engineering challenges.
AI-Powered Insights
Another major part of VISORA BI is the insights layer.
Instead of stopping at charts and statistics, the platform attempts to turn analytical results into understandable summaries.
The idea is:
Raw Dataset
↓
Analytical Pipeline
↓
Structured Results
↓
Insight Generation
↓
Business Interpretation
The goal isn't simply:
"Add AI because the project needs AI."
The AI layer is connected to the analytical workflow.
The analysis provides the information.
The insight layer helps explain it.
Reports and Persistence
As the project grew, I realized that generating an analysis once wasn't enough.
A BI platform needs some concept of history and persistence.
So VISORA BI also developed:
- Dataset persistence
- Dataset history
- Persistent reports
- Current report handling
- Report lifecycle management
- Downloadable analysis
This was another point where the project started feeling less like a demo and more like an actual application.
One of the Biggest Lessons: Integration Is Harder Than Individual Features
Building individual features was one thing.
Making all of them work together was another.
For example:
React
↓
API Request
↓
FastAPI
↓
Dataset Storage
↓
Pandas Pipeline
↓
Analysis
↓
Report / Insights
↓
API Response
↓
React State
↓
UI
A problem anywhere in this chain could break the user experience.
That forced me to start thinking beyond individual files.
I had to think about the entire system.
Debugging the Real Problems
Not everything worked on the first attempt.
One example was the backend port.
At one point, port 8000 was already occupied by another Python process.
The result was confusing because the backend appeared to start incorrectly.
After investigating the running process and stopping the conflicting process, I started the project backend explicitly through the virtual environment:
python -m uvicorn api.main:app --reload --port 8000
That reminded me of something important:
When debugging a full-stack application, don't immediately assume the code is the problem.
Sometimes the problem is:
- Environment
- Process
- Port
- Proxy
- Dependency
- Configuration
- Browser state
Frontend and Backend Integration
Another important issue was making sure the frontend and backend agreed on the API base path.
The frontend eventually used:
const API_BASE = "/api/v1";
And the Vite development server was configured to proxy API requests to:
http://127.0.0.1:8000
This allowed the frontend to communicate with the FastAPI backend during development without hardcoding backend URLs throughout the application.
That small architectural decision made the application much cleaner.
Testing the Application as a User
One of the biggest changes in my thinking came when I stopped testing only individual functions.
I started testing the complete user journey.
Instead of:
Does upload work?
Does analysis work?
Does insights work?
Does delete work?
I wanted to know:
Can a real user actually go through the entire workflow?
So I created an automated end-to-end flow.
The test essentially follows:
Open Datasets
↓
Upload CSV
↓
Wait for Upload
↓
Open Dataset
↓
Verify Profiling
↓
Run Analysis
↓
Open Analytics
↓
Verify Uploaded Dataset
↓
Open Insights
↓
Verify Insights
↓
Delete Dataset
↓
Verify Workspace State
The 18/18 End-to-End Result
The final automated flow passed:
18/18 checks ✅
The validation included:
PASS datasets page renders dropzone
PASS upload reaches success phase
PASS upload opens dataset detail page
PASS dataset registered
PASS dataset profiled on ingest
PASS detail page shows data profile
PASS analyze action is clickable
PASS analysis routes to analytics
PASS analytics renders metrics
PASS analytics targets uploaded dataset
PASS unified snapshot updated
PASS insights renders summary
PASS insights reflects uploaded dataset
PASS delete confirmation dialog opens
PASS cancel keeps dataset
PASS confirm deletes dataset
PASS workspace snapshot restored
PASS no console/page errors during flow
This was one of the most satisfying moments of the project.
Not because 18/18 is a huge number.
But because it represented something more important:
The entire system was working together.
Smoke Testing
Alongside the end-to-end flow, I also ran route smoke testing.
The important routes were checked:
/overview
/datasets
/analytics
/insights
/reports
/settings
The result:
SMOKE PASSED: all routes rendered with no page errors.
That gave me confidence that fixing one part of the application hadn't silently broken another part.
What Changed in My Coding Style
VISORA BI also changed the way I approach programming.
Earlier, I was mostly thinking:
"How do I make this feature work?"
Now I think more about:
"How should this feature fit into the system?"
That difference is huge.
I started paying much more attention to:
- Separation of responsibilities
- API contracts
- Reusable functions
- State management
- Validation
- Error handling
- Testing
- Persistence
- User flows
The project pushed me away from just writing code and toward thinking more like a software engineer.
Git and Incremental Development
Another important part of the journey was learning to work with Git more seriously.
Instead of treating the project as one giant folder that changes randomly, I started using commits to represent meaningful milestones.
For example:
git status
git diff --check
git add .
git commit -m "Complete frontend integration and validation"
I also learned that checking a patch before applying it is much safer than blindly modifying the project.
git apply --check patch-file.patch
Then, only after validation:
git apply patch-file.patch
That small workflow saved a lot of potential trouble.
The Project Also Taught Me About Refactoring
As the application grew, some earlier decisions became outdated.
Files and modules changed.
The backend evolved.
The frontend evolved.
The analytical pipeline evolved.
Requirements changed.
Some things that were fine for an early prototype weren't ideal anymore.
That is probably one of the most realistic parts of software development I experienced:
Building software isn't a straight line.
You build something.
Then you understand the problem better.
Then you change the architecture.
Then you test again.
Then you break something else.
Then you fix that.
And eventually the system becomes better.
Building for a Hackathon
VISORA BI was also my first major project developed toward a hackathon submission.
I built and submitted it for Beginner's Paradise - FirstCommit on Devpost.
That gave the project an additional constraint.
I wasn't just experimenting anymore.
I had something that needed to become:
- Presentable
- Demonstrable
- Reliable
That changed the way I prioritized the work.
Instead of endlessly adding features, I started asking:
- Does this improve the user journey?
- Does this feature actually work end-to-end?
- Can I demonstrate it?
- Can I validate it?
- Is the architecture understandable?
- Can another developer run the project?
Those questions were more valuable than simply increasing the feature count.
The Final Technology Stack
The final project brought together several technologies I had been learning separately.
Frontend
- React
- Vite
- JavaScript
Backend
- Python
- FastAPI
- REST APIs
Data
- Pandas
- Analytical pipelines
Application
- Dataset persistence
- Reports
- Insights
- History
Testing
- Route smoke tests
- End-to-end browser flow
Development
- Git
- Virtual environments
- npm
What started as separate things I was learning became one connected system.
What I Learned From Building VISORA BI
1. Python Fundamentals Actually Matter
It is tempting to skip fundamentals when you're excited about AI and Machine Learning.
But the basic concepts show up everywhere.
Functions become API handlers.
Dictionaries become structured data.
Loops become processing logic.
File handling becomes persistence.
Error handling becomes application reliability.
The fundamentals don't disappear.
They become building blocks.
2. Pandas Becomes Much More Interesting When You Build Something With It
Learning:
df.head()
df.info()
df.describe()
df.isna()
is useful.
But using those concepts inside a real analytical workflow is completely different.
You start asking:
What does the user need to know from this dataset?
That question makes data analysis much more meaningful.
3. Full-Stack Development Is Mostly Communication
The frontend doesn't know what the backend is thinking.
The backend doesn't know what the frontend expects unless you define it.
The analytical pipeline doesn't know what the UI needs unless the data contract is clear.
Everything has to communicate.
Frontend
↕
API
↕
Backend
↕
Analytics
↕
Persistence
A large part of full-stack development is making those boundaries reliable.
4. Testing the User Journey Is Different From Testing Functions
A function can pass.
An API can pass.
A page can render.
And the actual application can still fail.
That's why end-to-end testing became so important for me.
The question changed from:
"Does this function work?"
to:
"Can the user actually complete the task?"
5. Building Something Is a Better Teacher Than Just Reading About It
I could have learned React separately.
FastAPI separately.
Pandas separately.
REST APIs separately.
Git separately.
Testing separately.
But combining them into one project forced me to understand how they interact.
That's where most of the learning happened.
What's Next?
VISORA BI is not finished.
There are still improvements I want to make.
The current version is a functioning foundation, not the final destination.
Future improvements can include things like:
- More advanced analytics
- Better visualizations
- More powerful AI insights
- Improved report generation
- Authentication
- Deployment
- Production-level infrastructure
- More comprehensive automated testing
But I'm deliberately not trying to build everything at once.
The current milestone is important:
I took an idea and turned it into a working full-stack BI platform.
From Beginner Exercises to a Real Application
Looking back, the journey feels quite different.
It started with small Python programs.
Then:
Python Fundamentals
↓
Mini Projects
↓
Functions + Data Structures
↓
File Handling + JSON
↓
Pandas
↓
Data Analysis
↓
VISORA BI
↓
FastAPI
↓
React + Vite
↓
REST APIs
↓
AI Insights
↓
Reports + Persistence
↓
Automated Testing
↓
End-to-End Validation
↓
Hackathon Submission
The biggest lesson wasn't a specific framework or library.
It was learning how to turn a problem into a system.
Final Thoughts
VISORA BI started as an idea around making data analysis easier.
It eventually became a project that taught me much more than data analysis.
It taught me about:
- Software architecture
- Backend development
- Frontend development
- APIs
- Data analysis
- AI integration
- Testing
- Debugging
- Git
- Persistence
- Product thinking
- Building software iteratively
There were plenty of moments where something didn't work.
There were patches to review.
There were bugs to debug.
There were APIs that didn't behave as expected.
There were frontend/backend integration issues.
There were architectural decisions that had to be revisited.
But that's probably the most valuable part of the experience.
Because the goal wasn't to write a perfect project on the first try.
The goal was to keep improving the project until it became something real.
And VISORA BI is now that:
An actual working Business Intelligence platform built from the ground up as part of my learning journey. 🚀
Try VISORA BI
GitHub:
https://github.com/bilal-dev-0x/Visora-BI
Hackathon:
https://firstcommit.devpost.com/
If you're also learning software development, my biggest advice would be:
Don't wait until you know everything before building something real.
Build it.
Break it.
Debug it.
Test it.
And learn what you need along the way.
That's exactly how VISORA BI came to life.
Top comments (1)
Checking that Analytics and Insights actually reflect the uploaded dataset, then verifying the workspace recovers after deletion, gives your 18-check flow useful coverage beyond pages merely rendering. Profiling missing values on ingest also gives you a foundation for deciding which conclusions the data can support. For the next iteration, I'd carry those data-quality caveats into the generated reports alongside the dataset version used for analysis. A business user needs to distinguish a trustworthy finding from a confident summary of incomplete data, especially once reports persist beyond the session that created them.