Back to all docs

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:

Why it matters:

Production access:

2. Memory Constraints Are Real (909 MB RAM)

The OOM kill is REAL:

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:

Already documented:

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:

Branch naming:

5. Testing Must Be Fast

Test design philosophy:

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:

See: /home/ubuntu/workplace/AhaiaApp/music/docs/webapp-testing-design-doc.md

6. PWA Configuration is Fragile

Critical files for PWA:

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:

For real audio testing:

8. The /yap Directory is a Knowledge Base

What's there:

Use it! These docs capture hard-won knowledge. Read relevant ones before starting work.

9. Port Numbers That Matter

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:

For full PWA testing:

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:

  1. This file - You're reading it ✓
  2. /docs/README.md - Project vision and structure
  3. /docs/architecture/system-overview.md - System design

Before Working on Features:

  1. /docs/webapp-testing-design-doc.md - Testing strategy
  2. /yap/dev-vs-prod-resources.md - Memory management
  3. Issue description on GitHub

Before Working on Infrastructure:

  1. /yap/understanding-swap-memory.md - If touching builds/memory
  2. /yap/pwa-ios-native-feel.md - If touching PWA
  3. Relevant ADRs in /docs/adr/ - If making architecture decisions

Quality Standards (Non-Negotiable)

Code Quality:

Git Quality:

PR Quality:


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:

  1. ✅ Tests run in < 10 seconds
  2. ✅ Build completes without OOM
  3. ✅ PR reviews are smooth (no "where's the docs?" comments)
  4. ✅ You catch issues before CI does
  5. ✅ Changes don't break PWA functionality
  6. ✅ Coverage doesn't drop

Red flags:


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:

Network:

File System:


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:

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:

  1. Pragmatism over Perfection - Ship it, iterate
  2. Document Lessons, Not Just Code - Future you will thank you
  3. Fast Feedback Loops - Test watch mode, quick builds, grep logs
  4. Git Discipline - Review before staging, always
  5. Question Everything - If it doesn't make sense, ask why
  6. Build Systems - Don't just solve problems, prevent them

This project values:


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:

  1. This file (you're here)
  2. /docs/ repo
  3. /yap/ directory
  4. GitHub issues
  5. Git history (git log)

Still stuck?


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