Capital Quest India
From Localhost to Production: Deploying React + json-server on Vercel & Render

Objective: Personal Growth π―
π§βπ» Source Code
π Live on
Project Overview
I recently built a fun learning project β a quiz game to test knowledge of Indian states and their capitals. But instead of just focusing on UI, I wanted to practice:
useReducer for complex state
API integration
Backend with json-server
Deployment (Vercel + Render)
Performance optimizations
Development Journey
Phase 1: Project Setup & Structure
Initialized React project with Vite
Set up component structure:
src/ βββ components/ β βββ FinishScreen.jsx β βββ Questions.jsx β βββ Main.jsx β βββ Progress.jsx | βββ Quiz.jsx β βββ StartScreen.jsx β βββ Header.jsx βββ main.jsx βββ index.css
Phase 2: Core Quiz Logic Implementation
Question Generation: Built logic to randomly select states and generate capital options
Answer Validation: Implemented correct/incorrect answer checking
Progress Tracking: Added question counter and navigation
Option Randomisation: Ensured capital options are shuffled each time
// Initial simple state const [currentQuestion, setCurrentQuestion] = useState(0); const [score, setScore] = useState(0); // Evolved to useReducer for better state management π const [state, dispatch] = useReducer(quizReducer, initialState);
Phase 3: useReducer Integration
Defined all possible actions (dataReceived, dataFailed, start, nextQuestion, restart, finish, newAnswer)
Created a centralised reducer function
Replaced multiple useState calls with a single useReducer
Phase 4: Scoring & Persistence
Current score calculation
High score tracking
localStorage integration for high score persistence (code below)
function fetchLocalStorage() { const stored = localStorage.getItem("capitalQuestHighScore"); const retrivedHighScore = JSON.parse(stored); return retrivedHighScore; }
Phase 5: UI/UX Enhancement
Created a responsive design for mobile devices
Styled components with CSS Flexbox/Grid

Phase 6: Testing & Refinement
Tested quiz flow from start to finish
Verified score calculations
Checked localStorage persistence across sessions
Tested on multiple devices and screen sizes
Fixed edge cases (last question, restart functionality)
Challenges & Solutions
Challenge 1: Complex State Management
Problem: Managing multiple interdependent state variables (current question index, score, etc) became difficult with multiple useState hooks. State updates were scattered across components, making debugging challenging.
Solution:
Migrated to
useReducerfor centralised state managementCreated a single source of truth with predictable state updates
//1. InitialState object for convenience
const initialState = {
questions: [],
options: [],
status: "loading",
index: 0,
points: 0,
answer: null,
highScore: 0
};
//2. Destructuring as I need to use this data often
const [{ questions, status, index, answer, points, highScore }, dispatch] =
useReducer(reducer, initialState);
//3. Reducer function
function reducer(state, action) {
switch (action.type) {
case "start":
return {
...state,
highScore: fetchLocalStorage(),
status: "active",
};
case "nextQuestion":
return {
...state,
answer: null,
index: state.index + 1,
};
//and it goes on for other 'actions'
}
}
Challenge 2: Randomising Answer Options
Problem: Correct answer appeared in the same position, making the quiz predictable.
Solution: Created an algorithm to select 3 random incorrect capitals, combine with the correct answer
Challenge 3: High Score Persistence
Problem: High scores reset when the page refreshes.
Solution: Implemented localStorage with useEffect hooks to load high score on mount and save when exceeded. Added error handling for localStorage access issues.
useEffect(function () {
const storedHs = Number(fetchLocalStorage() || 0);
if(storedHs < highScore) localStorage.setItem("capitalQuestHighScore", JSON.stringify(highScore));
},[highScore]);

Challenge 5: Quiz Flow Edge Cases
Problem: Bugs with the last question, restart functionality, and allowing progression without answer selection.
Solution: Added conditional logic for last question detection, comprehensive restart quiz action, and disabled next button until answer is selected.
π Deployment Strategy
Frontend(Vercel) + Backend (Render)
I used json-server to mock APIs.
{
"questions": [
{ "state": "Assam", "capital": "Dispur" },
{ "state": "Bihar", "capital": "Patna" }
]
}
Create Web Service
Start command:
json-server db.json --host 0.0.0.0 --port 10000
Benefits Realized
Predictability: All state changes go through the reducer, making it easy to trace bugs
Testability: Reducer is a pure function, easy to unit test
Maintainability: Adding new states or actions is straightforward
Debugging: Redux DevTools can be used with useReducer for time-travel debugging
Acknowledgments
Educational Resources
Jonas Schmedtmann - Comprehensive React tutorials that provided the foundation for this project
Chris Coyier - Flexbox guide that provided clear visual examples and practical applications
Development Tools
React, Vite
Vercel & Render
VS Code
Chrome DevTools
ChatGPT - AI assistance for resolving specific styling and structural challenges



