6. Testing the dashboard locally
A Flask app has two execution environments: Python on the server and JavaScript in the browser. Bugs land in either one, and the symptoms look similar. This page covers running the dev server, telling the two environments apart with browser DevTools, and the four Flask errors you will hit first.
Running the development server
With all components in place, start Flask's development server and access your dashboard. Make sure your virtual environment is activated and you're in the project directory:
# Method 1: run with Python (if app.py has if __name__ == '__main__')
python app.py
# Method 2: use Flask's built-in runner.
# macOS / Linux:
export FLASK_APP=app.py
# Windows PowerShell:
$env:FLASK_APP = "app.py"
# Windows cmd:
set FLASK_APP=app.py
flask run
# Method 3: enable debug mode (auto-reload on code changes).
# macOS / Linux:
export FLASK_DEBUG=1
# Windows PowerShell:
$env:FLASK_DEBUG = "1"
# Windows cmd:
set FLASK_DEBUG=1
flask run
Flask starts a development server on http://127.0.0.1:5000. Open this URL in your browser. You should see either the home dashboard (if you're already authenticated) or a redirect to the login route.
Development mode features:
- Auto-reload: Save any Python file, Flask restarts automatically. No need to manually stop and restart the server after each change.
- Detailed error pages: When something breaks, Flask shows the full stack trace with highlighted code lines and local variables. Never use this in production, it exposes internal code.
- Static file caching disabled: CSS and JavaScript changes appear immediately without hard-refreshing the browser.
If flask run exits with "Address already in use" or "port 5000 already in use," another process is bound to the port. Three usual culprits:
- Another Flask app already running (check for open terminals).
- On macOS, the AirPlay Receiver service binds to port 5000 by default. Disable it in System Settings → General → AirDrop & Handoff.
- A previous Flask process didn't shut down cleanly and is still holding the port.
Either kill the process using port 5000 (lsof -i :5000 on macOS/Linux, Get-NetTCPConnection -LocalPort 5000 on Windows PowerShell), or run Flask on a different port:
flask run --port 5001
# Or in app.py:
app.run(debug=True, port=5001)
Browser console: your frontend debugger
When building web applications, you work with two execution environments: Python (backend) and JavaScript (frontend). Python errors appear in your terminal. JavaScript errors appear in the browser console. Learning to use the browser console is essential for debugging frontend issues.
Opening DevTools:
- Windows/Linux: Press F12 or Ctrl+Shift+I
- Mac: Press Cmd+Option+I
- Alternative: Right-click anywhere on the page and select "Inspect"
The Console tab: Shows JavaScript errors, console.log() output, and lets you execute JavaScript commands interactively. If your chart doesn't render, check the Console first. You'll see errors like "chartData is undefined" or "Chart is not a constructor" that explain exactly what's wrong.
The Network tab: Shows all HTTP requests the page makes, loading CSS files, fetching JavaScript libraries from CDNs, making AJAX calls. If your CSS doesn't load, check Network for failed requests (red entries). Click a request to see details: status code, response headers, actual content returned.
The Elements tab: Lets you inspect and modify HTML/CSS live. Hover over elements to see their dimensions and margins. Edit CSS properties to test styling changes before updating your actual files. Find which CSS rules are overriding your styles.
Common debugging workflows:
- Chart doesn't render. Check Console for errors. Common issues: Chart.js not loaded (404 in Network tab), chartData undefined (Python didn't pass data correctly), syntax error in chart configuration. The error message tells you exactly which line failed.
- CSS not applying. Check Network tab, did dashboard.css load? If yes, inspect the element in Elements tab, see which CSS rules are active. Maybe another rule with higher specificity is overriding yours.
- Route returns wrong data. Add console.log(chartData) in your JavaScript. The Console shows exactly what data Python sent. If it's empty or malformed, the problem is in your Python route, not JavaScript.
The two-environment mental model
When debugging, always ask: "Is this a backend problem (Python) or a frontend problem (JavaScript)?" Backend problems show errors in the terminal. Frontend problems show errors in the browser console.
If you're not seeing errors in either place, the issue might be logical (code runs but does the wrong thing). Add print statements in Python and console.log statements in JavaScript to trace data flow.
Common Flask errors and solutions
Flask provides helpful error messages, but they're not always immediately clear to beginners. Here are the most common errors and their solutions:
TemplateNotFound: home.html
Flask can't find the template file. Check: (1) Is the file in the templates/ directory? (2) Is the filename spelled exactly as used in render_template()? (3) Did you restart Flask after creating the file?
Common mistake: Creating template/home.html (singular) instead of templates/home.html (plural).
404 Not Found: the requested URL was not found
Flask doesn't have a route matching the requested URL. Check: (1) Is the @app.route() decorator present? (2) Does the URL in your browser exactly match the route path? (3) Did you forget a trailing slash or add an extra one?
Flask treats /home and /home/ as different URLs by default. Use @app.route('/home', strict_slashes=False) to accept both.
500 Internal Server Error
Your Python code has an error. Check the terminal where Flask is running, you'll see the full stack trace there. Common causes: undefined variable, None object accessed, database connection failed, wrong number of function arguments.
Enable debug mode (app.run(debug=True)) to see detailed error pages in the browser instead of generic 500 messages.
Chart shows empty canvas (no errors)
Data reached JavaScript but isn't valid for Chart.js. Add console.log(chartData) before creating the chart. Check: (1) Are labels and data arrays? (2) Do they have the same length? (3) Are data values numbers, not strings? (4) Did |tojson convert the data correctly?
Static files return 404 (CSS/JS not loading)
Check: (1) Are static files in the static/ directory with correct subdirectories (static/css/, static/js/)? (2) Are you using url_for('static', filename='css/dashboard.css') instead of hardcoded paths? (3) Did you refresh after adding new static files?
Check the Network tab in DevTools to see the exact URL Flask is trying to load.
Session data disappears unexpectedly
Flask's default session lives in a cookie that's signed with app.secret_key. As long as the secret stays the same, sessions persist across server restarts (the cookie is on the browser, not in the Flask process). Two things really do invalidate sessions: rotating secret_key (every previously-signed cookie now fails verification, so every reader gets logged out), and the reader clearing cookies for the site. If you see "session disappeared after restart" symptoms, check your SECRET_KEY environment variable for drift -- a fresh fallback like secrets.token_hex(32) on each restart looks identical to "sessions don't persist."
The debug workflow
When something breaks: (1) Read the error message completely, don't just scan it. (2) Check the terminal for Python errors. (3) Check the browser console for JavaScript errors. (4) Check the Network tab for failed requests. (5) Add print() statements or console.log() to trace data flow. (6) Test one change at a time.
Most bugs are simple mistakes: typos, wrong indentation, forgotten imports. The error messages tell you exactly what's wrong if you read them carefully. Develop the habit of reading errors instead of immediately Googling them, you'll learn faster.
The home dashboard checklist
Before building the feature pages, verify the home dashboard works completely. Use this checklist to confirm every component functions correctly:
Home Dashboard verification checklist
Work through each item to confirm every component functions correctly:
- Flask server starts without errors, runs on port 5000.
- Navigation bar displays with all links (Home, Analytics, Playlists, Settings).
- Stat cards show correct values (Tracks tracked, Track turnover, Most-consistent artist).
- Discovery-rate chart renders with actual data, not an empty canvas.
- Chart is interactive (hover shows tooltips with exact values).
- Quick-action buttons navigate correctly (Analytics, Playlists pages, even if they're stubs for now).
- Page looks clean on mobile (test with DevTools device mode at 375px width).
- Stat cards reflow to a single column on mobile.
- No JavaScript errors in browser console (F12 → Console tab).
- OAuth login/logout flow works (can authenticate with Spotify, state parameter verifies).
- Dashboard reads real data from
music_time_machine.db(the SQLite file Chapter 16 wrote). - CSS styling loads correctly (Spotify-green accents, proper spacing).
If every item passes, your home dashboard is locally complete and ready for the feature pages. The patterns it locks in -- routes, templates, static files, session management, OAuth state, Chart.js handoff -- are the same patterns the rest of this chapter applies to Analytics, Playlist Manager, and Settings. Chapter 20 covers what changes when you take this app from flask run to a real production deployment (a proper WSGI server like gunicorn, debug=False, HTTPS, environment-specific secrets); none of those concerns are settled here.