5 KiB
AGENTS.md
This file provides guidance for AI coding agents working in this repository.
Project Overview
Top 500 Albums analysis with data from Rolling Stone (2020) and Wikipedia (2023). Includes Python data processing scripts, an interactive web interface (vanilla HTML/CSS/JS), and album cover artwork from the iTunes API.
Build/Lint/Test Commands
No formal build system. All Python scripts use only the standard library.
# Run Python scripts directly
python scripts/download_all_covers.py
python scripts/compare_top500_albums.py
# Local dev server (required for CORS)
python -m http.server 8000
No tests or linting configured. Manual testing only - run scripts and verify output, open website and check functionality.
Code Style Guidelines
Python
#!/usr/bin/env python3
"""Module docstring explaining the script's purpose."""
import csv
import json
import os
import re
from typing import Dict, List, Optional, Tuple
# Constants: UPPER_SNAKE_CASE
MAX_RETRIES = 3
# Functions/variables: snake_case
def normalize_text(text: str) -> str:
"""Normalize text for comparison."""
pass
albums_2020 = {}
Key patterns:
- Always use shebang:
#!/usr/bin/env python3 - Include module-level docstring
- Standard library only - no external dependencies
- Type hints for function signatures
- Use
encoding='utf-8'andnewline=''for CSV operations
Error handling:
try:
with urllib.request.urlopen(url, timeout=15) as response:
data = json.loads(response.read().decode())
except Exception as e:
print(f"Error: {e}")
return None
JavaScript
// Global variables at top
let albumsData = [];
const itemsPerPage = 50;
// DOM refs cached on load
const albumsGrid = document.getElementById('albumsGrid');
// Initialize on DOMContentLoaded
document.addEventListener('DOMContentLoaded', function() {
loadData();
});
// Async/await for fetch
async function loadAlbumsData() {
try {
const response = await fetch('data.csv');
if (!response.ok) throw new Error('Failed');
// ...
} catch (err) {
console.error('Error:', err);
}
}
Key patterns:
- Variables/functions: camelCase
- Use
console.warn()for non-critical failures - Vanilla JS only - no frameworks
HTML/CSS
- Semantic HTML5 elements
- CSS custom properties for theming
- Responsive design with Grid/Flexbox
Accessibility Requirements
All UI changes must follow WCAG 2.1 AA guidelines:
Keyboard Navigation:
- All interactive elements must be keyboard accessible
- Use
tabindexappropriately (0 for focusable, -1 for programmatic focus) - Implement visible focus indicators (
:focus-visiblewithoutline) - Support skip links for main content
Screen Readers:
- Use semantic HTML (
<button>,<nav>,<main>,<article>) - Add ARIA labels for icon-only buttons:
aria-label="Share album" - Use
.sr-onlyclass for screen-reader-only text - Ensure proper heading hierarchy (
h1>h2>h3)
Color & Contrast:
- Minimum 4.5:1 contrast ratio for normal text
- Minimum 3:1 for large text and UI components
- Never use color alone to convey information
Motion & Animations:
- Respect
prefers-reduced-motionmedia query - Avoid layout shifts on hover (no
transform: translateY()on cards)
Focus Management:
- Trap focus in modals/dialogs
- Return focus to trigger element when closing overlays
Existing Patterns:
/* Screen reader only */
.sr-only { position: absolute; width: 1px; height: 1px; ... }
/* Focus indicators */
button:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }
/* Reduced motion */
@media (prefers-reduced-motion: reduce) { ... }
Project Structure
top500albums/
├── index.html, script.js, styles.css # Website
├── *.csv, *.json # Data files
├── covers/ # Album artwork (500 images)
└── scripts/ # Python utilities (36 scripts)
Data Files
| File | Notes |
|---|---|
rolling_stone_top_500_albums_2020.csv |
Title case columns, ranks in reverse order |
wikipedia_top_500_albums.csv |
Lowercase columns (rank, artist, album) |
top_500_albums_2023.csv |
Combined comparison file |
Key Patterns
CSV column naming:
- Rolling Stone/Combined: Title case (
Rank,Artist,Album) - Wikipedia: lowercase (
rank,artist,album)
Album matching: Uses difflib for fuzzy matching variations like "The Beatles" vs "Beatles"
API rate limiting: time.sleep(1.2) between requests
Common Tasks
New Python script:
- Create in
scripts/, add shebang + docstring - Standard library only
- Include
if __name__ == "__main__":block
Working with album data:
import csv
with open('top_500_albums_2023.csv', 'r', encoding='utf-8') as f:
for row in csv.DictReader(f):
rank, artist, album = int(row['Rank']), row['Artist'], row['Album']
status = row['Status'] # "New in 2023", "+10", "-5", "No change"