Part 2: Wellness Tracker - Journal + PWA
Deploy your wellness tracker as a mobile PWA.
Introduction
30 Second Summary
You built a wellness tracker that works great on your laptop. But your best intentions happen on the go, and right now there is no way to open it on your phone like a real app.
In this project, you will add a reflective journal to your wellness tracker, make it responsive for mobile screens, and deploy it as a Progressive Web App you can install on your phone's home screen.
What You'll Build
You open your phone, tap the Wellness Tracker icon, write what went well today and what could be better, then scroll through past reflections displayed as dated cards.
By the end of this project, you'll have:
- A Journal tab with "What went well?" and "Even better if?" text areas, a save button that stores entries in localStorage, and a card-based dashboard showing past reflections sorted newest-first.
- A fully responsive layout that adapts from desktop to mobile with touch-friendly buttons, flexible widths, and readable text on any screen size.
- A live PWA deployed to GitHub Pages that you install on your phone's home screen and use offline with no app store required.
- Secret Mission: Add search and date filtering to find journal entries quickly as your collection grows.
Are there any prerequisites?
Yes. This project continues directly from "Daily Wellness Tracker with Claude Code" Part 1. You need the wellness-tracker project folder on your Desktop with index.html, style.css, app.js, CLAUDE.md, and the .claude/skills/check-app/ folder already in place.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters. Naming the goal upfront gives both you and Claude Code clear direction from the start.
Reopen Your Project and Update CLAUDE.md
Claude Code has no memory between sessions. Every time you start a new conversation, it starts fresh with zero context about what you've built or what you're planning to build next.
That's where CLAUDE.md comes in. By updating this conventions file with your Part 2 goals (the journal feature, PWA setup, and responsive layout), you give Claude a clear brief before it writes a single line of code.
In this step, get ready to:
- Reopen your wellness-tracker project and confirm Part 1 still works.
- Update CLAUDE.md with journal, PWA, and responsive layout conventions.
- Verify Claude reads and understands the new conventions.
Reopen your project and confirm Part 1 works
Before adding anything new, you need to make sure your Part 1 code still runs correctly. A quick check now saves debugging time later.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Cursor and press Enter to open it.
- Click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop and select the wellness-tracker folder, then click Open.
You should see your Part 1 files in the Explorer sidebar: index.html, style.css, app.js, CLAUDE.md, and the .claude folder.
- Open the terminal in Cursor by pressing Ctrl+` (backtick key, top-left of keyboard).
- Start a Claude Code session by running:
claude
- Once Claude Code starts, run the /check-app skill by typing:
/check-app
Claude runs through the verification checks from Part 1. You should see it confirm that your HTML, CSS, and JavaScript files are consistent and the app's two tabs (Log Entry and Dashboard) work correctly.
Seeing errors from /check-app?
If Claude reports mismatches or missing files, your Part 1 code may have been modified since you finished that project. Re-download or restore the Part 1 files before continuing.
If the claude command itself is not found, your Claude Code installation may need to be refreshed. Help me troubleshoot why the claude command is not found in my terminal.
Update CLAUDE.md with new feature conventions
Your CLAUDE.md currently describes the Part 1 app: two tabs, wellness logging, and the localStorage setup. You need to tell Claude about the three new features you're adding in Part 2.
- In the Cursor Explorer sidebar, click CLAUDE.md to open it in the editor.
- Scroll to the bottom of the file and add the following new section below your existing conventions:
## New Features (Part 2)
### Journal Tab
- Third navigation tab alongside Log Entry and Dashboard
- Two labelled text areas: "What went well?" and "Even better if?"
- Save button stores entries to localStorage under key 'wellness-tracker-journal'
- Card-based display of past entries sorted newest-first with date headers
### Progressive Web App (PWA)
- manifest.json with name, short_name, icons (192px and 512px), start_url, display: standalone
- service-worker.js with cache-first strategy caching index.html, style.css, app.js, and manifest.json
- Service worker registered in app.js
- Manifest link tag added in index.html head
### Responsive Mobile Layout
- Mobile-first CSS with viewport meta tag
- Touch-friendly buttons (minimum 44px tap targets)
- Flexible widths for all inputs and cards
- Three-tab navigation: Log Entry, Dashboard, Journal
What does this addition do?
Each section gives Claude Code a clear specification for one feature. The Journal section defines the UI elements and storage key. The PWA section lists the exact files and configuration Claude needs to generate. The responsive section sets measurable targets like 44px tap targets.
Without these conventions, Claude would guess at implementation details. With them, it follows your exact design decisions.
- Now add an updated file structure section below the responsive layout section:
## File Structure (Updated for Part 2)
- index.html (three-tab layout with manifest link and viewport meta)
- style.css (responsive mobile-first styles)
- app.js (wellness logging, journal, service worker registration)
- manifest.json (PWA configuration)
- service-worker.js (offline caching with cache-first strategy)
- CLAUDE.md (project conventions)
- .claude/skills/check-app/SKILL.md (verification skill)
Why list the file structure?
Claude Code uses the file structure section to know which files to create and where to put new code. Listing manifest.json and service-worker.js here tells Claude these are top-level files alongside your existing ones.
- Save CLAUDE.md with Cmd+S (macOS) or Ctrl+S (Windows).
Verify Claude reads the updated conventions
The real test is whether Claude Code actually picks up your new conventions. If it does, every feature you ask it to build from this point forward will follow your specifications.
- In your terminal, exit the current Claude Code session by typing:
/exit
- Start a fresh Claude Code session so it reads the updated CLAUDE.md:
claude
Before you ask Claude anything, think about this: what do you expect Claude to mention when you ask about your project conventions? It should reference the new features alongside the original Part 1 conventions.
- Type the following message into your Claude Code session:
What are my project conventions?
Claude should mention the journal feature (with 'What went well?' and 'Even better if?' sections), the PWA requirements (manifest.json and service-worker.js), and three-tab navigation alongside your original Part 1 conventions.
Claude not mentioning the new features?
Make sure you saved CLAUDE.md before starting the new session. Claude reads conventions from disk when a session begins.
Check that your additions are inside CLAUDE.md in the wellness-tracker folder root, not in a subfolder or a different file.
Help me figure out why Claude Code is not reading my updated CLAUDE.md conventions.
Your conventions file is ready and Claude knows the plan. Next up, you'll put these conventions to work by asking Claude to build the Journal tab from scratch.
Build the Journal Tab
Your CLAUDE.md is loaded and Claude Code knows what you are building next. The app currently has two tabs for logging and viewing wellness data, but there is nowhere to write daily reflections.
In this step, you will add a Journal tab where you can capture what went well each day and what could be even better. Claude Code will build the tab, the save logic, and a card-based display of past entries.
In this step, get ready to:
- Plan and build the Journal tab with two reflection text areas and a Save button.
- Verify journal entries save to localStorage and display as dated cards.
- Test the card dashboard with multiple sample entries.
Plan the journal tab with Claude Code
Claude Code works best when you describe the end result before it starts writing code. Plan mode lets Claude think through the approach and show you the strategy before any files change.
- In your Claude Code session, enter plan mode with this prompt:
/plan Add a Journal tab to the wellness tracker. It needs:
- A third navigation button labelled "Journal" alongside Log Entry and Dashboard
- Two labelled text areas: "What went well?" and "Even better if?"
- A Save button that stores entries to localStorage under the key 'wellness-tracker-journal'
- Each entry stored as an object with date, wentWell, and evenBetter fields
- A card-based display below the form showing past entries sorted newest-first
- Each card shows the date as a header and both reflection sections
- A green confirmation message when an entry is saved successfully
What does this prompt do?
The /plan command tells Claude Code to analyse the request and propose a strategy without editing any files yet.
You will see Claude outline which files it plans to change (index.html, style.css, app.js) and the order of changes. Review the plan to make sure it matches what you described.
- Read through Claude's plan.
- Confirm it mentions a third navigation tab, two text areas, localStorage storage under wellness-tracker-journal, and a card-based display sorted newest-first.
- Accept the plan to let Claude start building.
If the plan is missing something
You can reply with corrections before accepting. For example, if it does not mention the green confirmation message on save, tell Claude to add that before proceeding.
Test your first journal entry
Once Claude finishes building, you need to confirm the journal actually works end to end.
- Open index.html in your browser (right-click the file in Cursor's Explorer sidebar and select Open in Default Browser, or use Live Server if you have it).
- Click the Journal tab in the navigation.
- Type Finished the project setup on time in the What went well? text area.
- Type Start earlier next time in the Even better if? text area.
- Click Save.
You should see a green confirmation message appear, and a card below the form showing today's date with both sections of your entry.
No Journal tab showing up?
- Make sure Claude finished building. Look for the message in your terminal that says the changes are complete.
- Hard-refresh your browser with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to clear the cache.
- Check that index.html now has three navigation buttons. If it only has two, ask Claude Code to re-read CLAUDE.md and try again.
Why isn't my Journal tab appearing after Claude built it?
- Refresh the page to confirm your entry persists after reload. The card with your test entry should still appear below the form.
Where is the data stored?
Journal entries live in your browser's localStorage under the key wellness-tracker-journal. This is separate from the wellness log data (wellness-tracker-entries), so the two features never overwrite each other.
Verify the card dashboard with sample data
One card looks fine, but you need to make sure multiple entries stack correctly with the newest on top. Instead of manually adding entries one by one, ask Claude Code to add temporary test data.
- In your Claude Code session, ask Claude to add a temporary test data function:
Add a temporary function called loadTestJournalData() that inserts 3-4 sample journal entries with different dates into localStorage, then call it once so I can see how the card dashboard looks with multiple entries. I'll remove this function after testing.
Why use a test data function?
Manually typing entries one at a time is slow and gives you identical dates. A test function lets Claude insert entries across multiple dates so you can verify the newest-first sorting and the card layout with realistic data.
- Refresh your browser after Claude adds the test data.
- Click the Journal tab and check the card dashboard.
Before you look at the order, what do you expect? The newest date should be at the top if the sorting is correct.
You should see 3-4 cards stacked vertically, each with a date header and both reflection sections visible.
Cards not in the right order?
- If the oldest entry is at the top, ask Claude Code to fix the sorting to newest-first.
- If you see your manual test entry but not the sample data, hard-refresh with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows).
Why are my journal cards showing in the wrong order?
- Once everything looks correct, ask Claude Code to remove the test data function and clear the sample entries:
Remove the loadTestJournalData() function and its call. Also clear the test entries from localStorage so the journal starts fresh.
- Refresh the browser one more time.
- Click the Journal tab. The card area should be empty now.
- Run /check-app in your Claude Code session to confirm everything is consistent across your files.
What does /check-app verify?
The /check-app skill you created in Part 1 checks that class names, IDs, and function references match between index.html, style.css, and app.js. It catches mismatches that would silently break features.
Your journal tab is working. Next up, you will make the whole app look good on a phone screen.
Go Mobile with Responsive CSS
Your journal feature works perfectly on your laptop. You can save entries, scroll through past reflections, and switch between all three tabs without a hitch.
But what happens when you open this app on a phone? In this step, you'll shrink the browser to phone width, discover that the layout breaks, and use Claude Code to apply mobile-first responsive CSS that makes the app usable on any screen size.
In this step, get ready to:
- Spot layout issues by testing the app in mobile emulation.
- Fix responsive problems with Claude Code's help.
- Confirm code consistency by running /check-app.
See the current layout break on mobile
The app looks great in a full-width browser window. Before you resize it, take a guess: what do you think will happen to the navigation tabs and text areas when the screen is only 375px wide?
- In Google Chrome with your app open, press Cmd+Option+I (macOS) or Ctrl+Shift+I (Windows) to open Chrome DevTools.
- Press Cmd+Shift+M (macOS) or Ctrl+Shift+M (Windows) to toggle the device toolbar.
- Select iPhone 14 from the device dropdown at the top of the viewport.
The layout breaks. Text areas overflow past the screen edge, navigation tabs are cramped together, and buttons are far too small to comfortably tap with a finger.
Why does this happen?
Without responsive constraints, CSS uses fixed or content-based widths that work fine at 1200px. On a 375px screen, those same widths overflow or shrink elements into unusable sizes.
This is exactly the problem we need to solve before the app can work on a real phone.
- Switch back to your Claude Code session and ask Claude to fix the responsive layout by sending this message:
The app looks broken at 375px mobile width in DevTools. Fix the responsive layout with mobile-first CSS:
- Add a viewport meta tag to index.html if it's missing
- Use flexible widths (percentages, max-width) instead of fixed pixel sizes
- Make navigation tabs use flexbox with equal spacing
- Set minimum 44px height on all buttons and inputs for tap targets
- Make text areas 100% width
- Ensure cards stack cleanly with no horizontal overflow
- Use readable font sizes on small screens
What will Claude do?
Claude will add a <meta name="viewport" content="width=device-width, initial-scale=1.0"> tag to index.html and update style.css with flexible widths, flexbox navigation, and media queries for smaller screens.
Allow Claude to make the edits when it asks for permission.
Verify the responsive layout in DevTools
Claude has made the changes. Time to see if the layout is actually fixed at mobile width.
- Switch back to Chrome with DevTools still open in device emulation mode.
- Refresh the page.
- Confirm iPhone 14 is still selected in the device dropdown.
- Check each of these against what you see on screen:
- Navigation tabs are evenly spaced across the full width and large enough to tap.
- Text areas fill the screen width without overflowing.
- All buttons and inputs are at least 44px tall (the minimum recommended tap target size for mobile).
- Journal cards stack cleanly with readable text.
- No horizontal scrollbar appears at the bottom of the viewport.
Something still looks off?
If a specific element is still too small or overflowing, tell Claude Code exactly what you see. For example: "The Save button is still too short, make it at least 44px tall" or "The text areas still overflow on the right side."
Claude responds best to specific visual descriptions of the problem rather than general requests.
Help me debug my responsive layout in Chrome DevTools mobile emulation.
Run /check-app to confirm consistency
Responsive CSS changes can sometimes rename or restructure class names. Before moving on, confirm your CSS and JavaScript still agree on the class names they share.
What do you expect /check-app to report? If Claude kept the same class names and just changed their properties, everything should pass.
- In your Claude Code session, run the check skill:
/check-app
You should see confirmation that CSS class names in style.css still match the class names referenced in app.js. No mismatches means your responsive updates are structurally sound.
Seeing class name mismatches?
If /check-app reports a mismatch, Claude may have renamed a class during the responsive refactor. Tell Claude: "The /check-app skill found a class name mismatch. Fix it so style.css and app.js use the same class names."
Help me fix a CSS class name mismatch between style.css and app.js.
Your app now works on any screen size. Navigation tabs are tappable, text areas fit the viewport, and nothing overflows. Next up, you'll turn this into a real installable app that lives on your phone's home screen.
Convert to PWA and Deploy to GitHub Pages
Your wellness tracker looks great on a phone-sized screen in DevTools. There is one problem: it only exists as a local file on your laptop.
To use it on your actual phone, you need two things. First, the app needs to become a Progressive Web App (PWA) so it can be installed to your home screen and work offline. Second, it needs to be hosted online so your phone can reach it.
In this step, get ready to:
- Add a web app manifest and service worker to make the app installable and offline-capable.
- Deploy the app to GitHub Pages so it has a public URL.
- Install the PWA on your phone and verify it works without internet.
Add PWA support with Claude Code
A PWA needs two core files. A manifest.json tells the browser your app's name, icons, and how it should display when installed. A service-worker.js caches your files so the app loads even without internet.
- In your Claude Code session, switch to plan mode by typing:
/plan
- Describe the PWA requirements to Claude by typing this prompt:
Add PWA support to the wellness tracker. Create:
1. manifest.json with name "Wellness Tracker", short_name "Wellness", icons (192px and 512px), start_url, display set to "standalone", background_color, and theme_color
2. service-worker.js with a cache-first strategy that caches index.html, style.css, app.js, and manifest.json on install, and serves from cache on fetch with network fallback
3. Register the service worker in app.js
4. Add <link rel="manifest" href="manifest.json"> to the head of index.html
What does this prompt tell Claude to build?
The manifest makes the app installable. Setting display to standalone means the app launches in its own window without a browser address bar, just like a native app.
The service worker intercepts every network request. On the first visit it caches your files. On subsequent visits (including offline), it serves those cached files instantly.
- Review Claude's plan. It should mention creating two new files and editing two existing files.
- Accept the plan and let Claude build the changes.
- After Claude finishes, open index.html in Google Chrome by double-clicking the file or refreshing if it is already open.
- Open Chrome DevTools with Cmd+Option+I (macOS) or Ctrl+Shift+I (Windows).
- Click the Application tab in DevTools.
- Click Manifest in the left sidebar. You should see your app's name ("Wellness Tracker") and the display mode ("standalone") listed.
- Click Service Workers in the left sidebar. You should see a service worker registered and activated with status "activated and is running".
Manifest or service worker not showing?
Make sure you opened the file via Chrome (not from an file:// URL if using Live Server). Service workers require either HTTPS or localhost. If you see an error, try opening the file through a local server.
Check that index.html contains <link rel="manifest" href="manifest.json"> in its <head> section. If it is missing, ask Claude to add it.
help me debug my service worker not registering in Chrome DevTools
Create a GitHub repository and deploy
The app needs a public URL. GitHub Pages hosts static sites for free directly from a GitHub repository. You will push your code to GitHub and use a GitHub Actions workflow to deploy it automatically on every push.
- Open GitHub in your browser and create a new public repository named wellness-tracker.
- Do not initialize the repository with a README, .gitignore, or license (your local project already has files).
- After creating the repository, copy the HTTPS remote URL shown on the quick setup page.
- Back in Claude Code, ask Claude to add the deployment files and connect to your remote by typing:
Add GitHub Pages deployment:
1. Create a .nojekyll file (empty) in the project root
2. Create .github/workflows/deploy.yml that deploys to GitHub Pages on push to main
3. Add the remote origin and push everything to main
Why a .nojekyll file?
GitHub Pages defaults to processing files with Jekyll, which can interfere with certain file names and paths. An empty .nojekyll file disables this processing so your static files are served exactly as-is.
- Claude will ask for your remote URL. Paste the HTTPS URL you copied from GitHub.
- Claude may prompt you to authenticate with GitHub. Follow the on-screen instructions to sign in.
- Before the workflow can deploy, you need to configure GitHub Pages to use GitHub Actions as its source. In your browser, navigate to your new repository on GitHub.
- Click Settings in the repository's top navigation bar.
- In the left sidebar under "Code and automation", click Pages.
- Under "Build and deployment", find the Source dropdown and select GitHub Actions.
What does this setting do?
By default, GitHub Pages tries to build from a branch. Selecting "GitHub Actions" tells GitHub to deploy your site using the workflow file at .github/workflows/deploy.yml instead. This workflow uploads your files as a Pages artifact and deploys them automatically on every push to main.
- If Claude has already pushed, click the Actions tab in your repository to check the workflow status. If the workflow failed because the source was not set yet, click the failed run and select Re-run all jobs.
- Wait for the workflow run to show a green checkmark. This usually takes about 30-60 seconds.
Before you open the URL, what do you think you will see when you visit the live site? Will it look different from your local version?
- Open your published site by visiting https://your GitHub username.github.io/wellness-tracker/ in your browser.
- You should see your wellness tracker app with all three tabs (Log Entry, Dashboard, Journal) working exactly as they do locally.
Seeing a 404 page?
The workflow may still be running. Wait a minute and refresh. Check the Actions tab for a green checkmark.
If the workflow passed but you still see 404, confirm you set the Pages source to GitHub Actions (not a branch) in Settings > Pages.
help me fix my GitHub Pages deployment showing a 404 error
Install on your phone and verify offline
The app is live online. Now you will install it on your phone as a standalone app and prove it works without internet.
- On your phone, open your browser (Safari on iPhone, Chrome on Android).
- Navigate to your GitHub Pages URL: https://your GitHub username.github.io/wellness-tracker/.
How to install a PWA on your phone
On iPhone (Safari): tap the Share button (the square with an upward arrow at the bottom of the screen), then tap Add to Home Screen. Confirm the name and tap Add.
On Android (Chrome): tap the three-dot menu in the top right, then tap Add to Home screen or Install app. Confirm and tap Add.
- After adding to your home screen, close the browser completely.
- Tap the Wellness Tracker icon on your home screen. The app should open in its own window with no browser address bar visible. This is standalone mode.
Now for the real test. Do you think the app will still load if you cut off all internet access?
- Enable airplane mode on your phone (swipe down to access the control center and tap the airplane icon).
- Close the app from your home screen, then reopen it by tapping the icon again.
- The app loads from the service worker's cache. You should see the full interface with all three tabs. Try navigating between tabs to confirm everything still responds.
- Disable airplane mode when you are done testing.
App not launching in standalone mode?
Make sure your manifest.json has "display": "standalone" set. On iPhone, only the standalone display mode creates a true home screen web app. Other modes fall back to opening in the browser.
If the app does not load offline, the service worker may not have cached all files on the first visit. Open the app while connected to the internet, wait a few seconds for the cache to populate, then try airplane mode again.
help me debug why my PWA is not working offline after installing to my phone home screen
Secret mission
Add Search and Date Filtering to Journal Entries
Your journal works great with a few entries. But after weeks of daily use, you'll have dozens of cards to scroll through. Can you add real-time search and date filtering so you can find any reflection instantly?
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs on GitHub Pages (free for public repositories) and localStorage (free, local to your browser), so there are no ongoing costs.
Resources you used:
- GitHub Pages hosting (free for public repositories, no ongoing charges).
- GitHub repository (free, public).
- localStorage data in your browser (no cost, persists until cleared).
- Project folder on your Desktop.
Keep everything running
No action needed. Choose this if you want your PWA to stay live and accessible from your phone.
- GitHub Pages serves your site for free with no limits for personal projects.
- Your PWA will remain accessible at your GitHub Pages URL indefinitely.
- Your localStorage data stays on each device independently and costs nothing.
Pause - I'll come back to this later
No action needed. GitHub Pages has no "running" state to pause.
- The site stays live at your GitHub Pages URL at no cost.
- Your localStorage data stays on each device independently.
- You can reopen the wellness-tracker folder in Cursor whenever you want to continue building.
Delete - I don't want to use this again
Remove all project resources and start fresh. Follow each step below to fully clean up.
- Delete the GitHub repository to remove the live site. Go to your repository on GitHub, click Settings, scroll to Danger Zone, and click Delete this repository. Confirm the deletion when prompted.
- Delete the local project folder. On macOS/Linux, run:
rm -rf ~/Desktop/wellness-tracker
On Windows, run:
rmdir /s /q ~\Desktop\wellness-tracker
- Clear localStorage on your laptop. Open your GitHub Pages URL in Chrome, press Cmd+Option+J (macOS) or Ctrl+Shift+J (Windows) to open the Console, then run these commands one at a time:
localStorage.removeItem('wellness-tracker-entries')
localStorage.removeItem('wellness-tracker-journal')
- Clear localStorage on your phone. Open your browser settings, find the site data or storage section, and clear data for your GitHub Pages domain.
- Remove the PWA from your phone's home screen by long-pressing the icon and selecting Remove or Delete.
That's a Wrap!
That's a Wrap!
Nice work! You just turned a local HTML file into a fully installable mobile app that lives on your phone's home screen and works offline.
Here's what you accomplished:
- Built a reflective journal feature with "What went well?" and "Even better if?" sections that saves to localStorage and displays entries as a scannable card-based dashboard.
- Made the entire wellness tracker responsive with mobile-first CSS, proper touch targets, and flexible layouts that work on any screen size.
- Converted a local HTML file into a Progressive Web App with a manifest, service worker, and offline caching, then deployed it to GitHub Pages using GitHub Actions and installed it on your phone's home screen.
- Secret Mission: Added real-time search and date range filtering to find journal entries quickly as the collection grows.
Ready to quiz yourself?