Note to the Next Agent Working on Ahaia Music
Date: November 2025 From: Claude (previous session) To: You (future agent or human developer)
Welcome! You're about to work on the Ahaia Music web app. This note contains the non-obvious things that will save you hours of debugging and confusion.
Critical Context You Won't Get From Issues
1. This is a Terminal-Only Development Environment
What this means:
- SSH to EC2 instance (no GUI)
- Vim/Claude Code for editing
- No browser DevTools during development
- Tests must run headless
- Screenshots get reviewed later on another machine
Why it matters:
- Don't assume you can "just open Chrome and see"
- All tests MUST be terminal-compatible
- Redirect large outputs to temp files (
npm test > /tmp/test.log) - Use
curlfor quick smoke tests
Production access:
- App runs on port 8000: http://35.160.208.215:8000
- You can test PWA from your phone/work machine
2. Memory Constraints Are Real (909 MB RAM)
The OOM kill is REAL:
- First build attempt failed with OOM killer
- Solution: 2GB swap space at
/swapfile(already configured) - Production mode (
100 MB) is fine, dev mode (250 MB) is tight
Before building:
# Verify swap is active
free -h
# Should show: Swap: 2.0Gi
# If swap is missing:
sudo swapon /swapfile
Build best practices:
# Redirect output to avoid memory overhead from logging
npm run build > build.log 2>&1
# Watch swap usage during build
watch -n 1 free -h # (in another tmux pane)
See: /home/ubuntu/yap/understanding-swap-memory.md for deep dive
3. There Are TWO Repos in This Workspace
/home/ubuntu/workplace/AhaiaApp/music/
├── docs/ # Central docs repo (ahaia-music/docs)
├── web/ # Web app repo (ahaia-music/web)
└── starter.md
When to use which:
- web repo: Code, component tests, web-specific README
- docs repo: Architecture, ADRs, testing strategy, org-wide patterns
Already documented:
/docs/webapp-testing-design-doc.md- Testing strategy (applies to all web apps)/docs/architecture/system-overview.md- System architecture
Don't duplicate docs across repos. If it applies broadly, put it in docs/.
4. Git Workflow Specifics
NEVER git add . - Sam will haunt you.
Always:
git status # Review changes
git add <specific files> # Only add relevant files
git status # Verify staged files
git commit -m "One line msg" # Sam prefers one-liners
Excluded from commits:
TASK.md(local task tracking)build.log,server.log(generated)/tmp/anything
Branch naming:
feature/- New featuresfix/- Bug fixesdocs/- Documentation only
5. Testing Must Be Fast
Test design philosophy:
- Unit tests: < 10 seconds (run constantly during dev)
- Integration tests: < 30 seconds (pre-commit)
- E2E tests: < 90 seconds (pre-deploy)
Output management:
# During development - redirect to temp
npm test > /tmp/test.log 2>&1 && echo "✓ Pass" || tail -20 /tmp/test.log
# Watch mode is your friend
npm run test:watch
Coverage expectations:
- Overall: 70%+
- Critical paths (audio, PWA): 90%+
- Don't test simple presentational components to death
See: /home/ubuntu/workplace/AhaiaApp/music/docs/webapp-testing-design-doc.md
6. PWA Configuration is Fragile
Critical files for PWA:
app/layout.tsx- metadata, viewport, iOS meta tagspublic/manifest.json- app manifest- Icons must be exact sizes (192x192, 512x512)
Testing PWA changes:
# Build first (PWA only works in production)
npm run build
npm start
# Test manifest
curl http://localhost:8000/manifest.json
# Test from phone
# iOS: Safari only (Chrome doesn't support PWA install on iOS)
# Android: Chrome shows auto-install prompt
Common gotcha: Dev mode doesn't fully reflect PWA behavior. Always test in production build.
7. Audio Testing Uses Mocks
Web Audio API is mocked in tests (see jest.setup.js):
global.AudioContext = jest.fn().mockImplementation(...)
What this means:
- You can't test actual sound in Jest
- Test behavior, not audio output
- Example: "Does mute button set gain to 0?" not "Does this sound good?"
For real audio testing:
- Manual testing in browser
- E2E tests verify controls work, not audio quality
8. The /yap Directory is a Knowledge Base
What's there:
dev-vs-prod-resources.md- Why dev mode uses more memoryunderstanding-swap-memory.md- Deep dive on swap/OOMpwa-ios-native-feel.md- PWA setup guidedesign-doc.md- Testing strategy from previous projectfeedback-pair-programming-session.md- Lessons from this session
Use it! These docs capture hard-won knowledge. Read relevant ones before starting work.
9. Port Numbers That Matter
- 3000 - Used by
/home/ubuntu/yap/server.js(Sam's blog) - 8000 - Ahaia Music production server (current)
- 5000 - Tried first, didn't work (security group)
If server won't start:
# Check what's using the port
ss -tlnp | grep 8000
# Kill if needed
fuser -k 8000/tcp
10. The Server Stays Running
Production server runs in background:
npm start > server.log 2>&1 &
Before starting a new one:
# Kill existing
ps aux | grep "next start" | grep -v grep | awk '{print $2}' | xargs kill
# Or use port-specific kill
fuser -k 8000/tcp
Check server health:
curl -I http://localhost:8000
tail -f server.log
Common Workflows
Starting Work on a New Feature
# 1. Pull latest from main
cd /home/ubuntu/workplace/AhaiaApp/music/web
git checkout main
git pull origin main
# 2. Check GitHub for your issue
gh issue view <number> --repo ahaia-music/web
# 3. Read relevant docs
# Check /docs/ for architecture
# Check /yap/ for lessons learned
# 4. Create branch
git checkout -b feature/your-feature
# 5. Start test watch mode (if writing code)
npm run test:watch # in tmux pane
# 6. Make changes
vim app/...
# 7. Verify tests pass
npm test > /tmp/test.log 2>&1 && echo "✓"
# 8. Build to verify
npm run build > /tmp/build.log 2>&1 && echo "✓"
# 9. Stage and commit
git status
git add <specific files>
git commit -m "Your one-line message"
# 10. Push and create PR
git push -u origin feature/your-feature
gh pr create --repo ahaia-music/web --base main
Running Tests Efficiently
# Quick iteration during development
npm run test:watch
# Pre-commit check
npm test > /tmp/test.log 2>&1 && \
npm run lint && \
npx tsc --noEmit && \
echo "✓ All checks pass"
# With coverage (before PR)
npm run test:coverage > /tmp/coverage.log 2>&1
grep "All files" /tmp/coverage.log
Debugging Memory Issues
# Check current memory
free -h
# Watch memory during operation
watch -n 1 free -h
# If OOM killed something
dmesg | grep -i "killed process"
# Check swap is active
swapon --show
# Activate swap if needed
sudo swapon /swapfile
Debugging Port Issues
# What's on port 8000?
ss -tlnp | grep 8000
# Kill everything on port
fuser -k 8000/tcp
# Verify it's free
ss -tlnp | grep 8000 # Should be empty
Gotchas That Will Bite You
1. TypeScript Compilation ≠ Tests Passing
Always run both:
npx tsc --noEmit # Type check
npm test # Runtime behavior
One can pass while the other fails.
2. Dev Server Port Conflicts
If you see EADDRINUSE: address already in use:
# Don't just restart - kill the old one first
fuser -k 8000/tcp
sleep 2
npm start
3. Build Success ≠ Production Works
Always verify production build:
npm run build
npm start
curl http://localhost:8000 # Should return HTML
Dev mode (npm run dev) is more forgiving than production.
4. Layout/Metadata Tests Are Weird
You can't test <html> and <body> tags directly with React Testing Library (they're rendered by Next.js at document level).
Test metadata exports instead:
import { metadata, viewport } from '@/app/layout';
expect(metadata.title).toBe('...');
expect(viewport.userScalable).toBe(false);
See __tests__/unit/app/layout.test.tsx for pattern.
5. PWA Only Works in Production + HTTPS
Local testing is limited:
- Manifest works: ✓
- Standalone mode: ✗ (needs HTTPS or localhost special case)
- Install prompt: ✗ (needs HTTPS)
For full PWA testing:
- Deploy to EC2 (already has IP)
- Test from phone on same network
- Or use ngrok/similar for HTTPS tunnel
6. Module Paths Use @/
Import like this:
import Component from '@/components/Component';
import { helper } from '@/lib/utils';
Not like this:
import Component from '../../components/Component'; // ❌
The @/ alias is configured in tsconfig.json and jest.config.js.
Documentation You Should Read
Before Starting ANY Work:
- This file - You're reading it ✓
/docs/README.md- Project vision and structure/docs/architecture/system-overview.md- System design
Before Working on Features:
/docs/webapp-testing-design-doc.md- Testing strategy/yap/dev-vs-prod-resources.md- Memory management- Issue description on GitHub
Before Working on Infrastructure:
/yap/understanding-swap-memory.md- If touching builds/memory/yap/pwa-ios-native-feel.md- If touching PWA- Relevant ADRs in
/docs/adr/- If making architecture decisions
Quality Standards (Non-Negotiable)
Code Quality:
- ✅ TypeScript compiles (
npx tsc --noEmit) - ✅ Linting passes (
npm run lint) - ✅ Tests pass (
npm test) - ✅ Production builds (
npm run build) - ✅ Coverage maintained (70%+ overall, 90%+ critical paths)
Git Quality:
- ✅ Review staged files before commit (
git status) - ✅ Only commit relevant files (no logs, no TASK.md)
- ✅ One-line commit messages
- ✅ PRs link to issues (
Closes #N)
PR Quality:
- ✅ Clear summary of changes
- ✅ Test results included
- ✅ Note any deviations from issue
- ✅ Screenshots for UI changes
When You Get Stuck
Resource Issues:
# OOM kills during build?
free -h # Check swap is active
sudo swapon /swapfile # Activate if needed
# Port conflicts?
fuser -k 8000/tcp # Kill and retry
Test Issues:
# Tests fail after changes?
npm test -- --no-cache # Clear Jest cache
# Weird module errors?
rm -rf node_modules .next
npm install
Build Issues:
# Build fails mysteriously?
rm -rf .next
npm run build
# Still fails?
grep -i error build.log # Check for actual error
Git Issues:
# Staged wrong files?
git reset HEAD <file> # Unstage specific file
git reset HEAD # Unstage everything
# Commit to wrong branch?
git reset --soft HEAD~1 # Undo commit, keep changes
git stash
git checkout correct-branch
git stash pop
Success Metrics
You'll know you're doing it right if:
- ✅ Tests run in < 10 seconds
- ✅ Build completes without OOM
- ✅ PR reviews are smooth (no "where's the docs?" comments)
- ✅ You catch issues before CI does
- ✅ Changes don't break PWA functionality
- ✅ Coverage doesn't drop
Red flags:
- ❌ Tests take > 30 seconds
- ❌ OOM kills during build (swap not active?)
- ❌ Committing log files
- ❌ Coverage drops below 70%
- ❌ PWA install breaks
Patterns to Follow
Component Structure:
// components/features/Player/AudioPlayer.tsx
export interface AudioPlayerProps {
songId: string;
}
export function AudioPlayer({ songId }: AudioPlayerProps) {
// Component logic
}
Test Structure:
// __tests__/unit/components/AudioPlayer.test.tsx
import { render, screen } from '@testing-library/react';
import { AudioPlayer } from '@/components/features/Player/AudioPlayer';
describe('AudioPlayer', () => {
it('renders with song ID', () => {
render(<AudioPlayer songId="123" />);
// assertions
});
});
Utility Structure:
// lib/utils/formatDuration.ts
export function formatDuration(seconds: number): string {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins}:${secs.toString().padStart(2, '0')}`;
}
Environment-Specific Notes
This EC2 Instance:
- OS: Ubuntu on AWS EC2
- RAM: 909 MB (tight!)
- Swap: 2 GB at
/swapfile(critical for builds) - Node: v20+ (check with
node --version) - Access: SSH only, no GUI
Network:
- Public IP: 35.160.208.215
- Open Ports: 8000 (web app), 3000 (yap blog)
- Security Group: AWS - only certain ports open
File System:
- Disk: 19 GB total, ~9 GB available
- Web Project: ~584 MB (mostly node_modules)
- Logs: Redirect to
/tmp/to avoid cluttering workspace
Communication Protocol
When Creating PRs:
## Summary
[Brief description]
## Changes
[Bullet list of what changed]
## Test Results
- Test Suites: X passed
- Coverage: Y%
## Note
[Any deviations from issue or important context]
Closes #N
When Commenting on Issues:
- Keep it concise (1-3 lines)
- Link to relevant docs if needed
- If you deviate from the plan, explain why
When Writing Commit Messages:
Add feature X
Not:
feat: Add feature X with Y and Z
- Details about Y
- More about Z
Co-authored-by: ...
Sam prefers one-liners. Save details for PRs.
Philosophy Notes
From working with Sam, I learned:
- Pragmatism over Perfection - Ship it, iterate
- Document Lessons, Not Just Code - Future you will thank you
- Fast Feedback Loops - Test watch mode, quick builds, grep logs
- Git Discipline - Review before staging, always
- Question Everything - If it doesn't make sense, ask why
- Build Systems - Don't just solve problems, prevent them
This project values:
- ✅ Working software over perfect architecture
- ✅ Documentation over tribal knowledge
- ✅ Fast iteration over exhaustive planning
- ✅ Learning over blame
Quick Reference Commands
# Development
npm run dev # Dev server (memory-heavy)
npm run test:watch # Test watch mode
npm run lint # ESLint
npx tsc --noEmit # Type check
# Pre-commit
npm test > /tmp/test.log 2>&1 && echo "✓"
npm run lint
npx tsc --noEmit
# Building
npm run build > /tmp/build.log 2>&1
npm start # Production server (port 8000)
# Debugging
free -h # Check memory/swap
ss -tlnp | grep 8000 # Check port usage
tail -f server.log # Watch server logs
dmesg | grep -i kill # Check OOM kills
# Git
git status # Always first
git add <files> # Never git add .
git commit -m "Message" # One-liner
gh pr create --repo ahaia-music/web
# Cleanup
fuser -k 8000/tcp # Kill port 8000
rm -rf .next # Clear build cache
rm /tmp/*.log # Clear temp logs
Final Thoughts
This is a well-architected project with good foundations. The testing setup is solid, the PWA config works, and the documentation is comprehensive.
The main "gotcha" is memory. Everything else is standard Next.js development.
Read the docs, use the patterns, redirect logs, and you'll be fine.
Good luck! And when you finish, consider adding your own learnings to this file or /yap/.
Questions? Check:
- This file (you're here)
/docs/repo/yap/directory- GitHub issues
- Git history (
git log)
Still stuck?
- Check swap is active:
free -h - Check port is free:
ss -tlnp | grep 8000 - Read error logs carefully (they're usually right)
Written by Claude after shipping 3 PRs with Sam in terminal-only SSH development on a resource-constrained EC2 instance. If we can do it, you can too.
Last Updated: November 2025