Last Updated: 2026-03-08 Purpose: Comprehensive reference for developers and AI assistants working with this codebase
Related Documentation:
- Project Overview
- Technology Stack
- Directory Structure
- Data Flow Architecture
- GitHub Actions Workflows
- Python Scripts
- Dynamic Route System
- Component Architecture
- Data Management
- Configuration Files
- Development Workflow
- Deployment Process
Choose your path based on what you need:
🎯 Quick Reference → See CLAUDE.md for AI assistant quick start 📋 Quick Lookup → See Architecture Quick Reference for fast topic finder
Frontend Developer
- Start: Component Architecture
- Then: Dynamic Route System
- Reference: Data Management
Backend/Automation Engineer
- Start: GitHub Actions Workflows
- Then: Python Scripts
- Reference: Data Flow Architecture
Data Engineer/Content Manager
- Start: Data Management
- Then: Common Tasks
- Reference: Python Scripts
DevOps/Site Reliability
- Start: Deployment Process
- Then: Troubleshooting
- Reference: Configuration Files
New Developer (First Time)
AI Assistant (Full Context)
- Read entire document for comprehensive understanding
Purpose: High-level introduction to the project, its goals, and key features
When to use this section: First-time orientation, understanding project scope
Related Sections: Technology Stack • Development Workflow
This is a statically-generated academic portfolio website for B. L. Alterman, a Research Astrophysicist at NASA Goddard Space Flight Center. The site showcases research, publications, and professional experience with automated data pipelines that pull live citation metrics from NASA's Astrophysics Data System (ADS).
- Automated Data Pipeline: Weekly updates from NASA ADS API for publications and citations
- Dynamic Route System: Single React component generates all research subpages from JSON data
- Static Site Generation: Fast, secure deployment to GitHub Pages
- Modern Stack: Next.js 15 with App Router, TypeScript, Tailwind CSS
- Professional Design: Responsive, accessible, SEO-optimized
- Zero-Maintenance Content: Add research pages by editing JSON files only
Purpose: Complete reference of all technologies, frameworks, and dependencies used in the project
When to use this section: Understanding tech choices, checking versions, adding new dependencies
Related Sections: Configuration Files • Development Workflow
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 15.5.3 | React framework with App Router |
| React | 18.3.1 | UI library |
| TypeScript | 5 | Type safety |
| Tailwind CSS | 3.4.1 | Utility-first styling |
| Shadcn/ui | Latest | Component library (based on Radix UI) |
| KaTeX | 0.16.22 | LaTeX math rendering |
| Recharts | 2.15.1 | Data visualization |
| Lucide React | 0.475.0 | Icon library |
| Technology | Purpose |
|---|---|
| Python 3.10+ | Data fetching and processing scripts |
| GitHub Actions | CI/CD automation |
| NASA ADS API | Publications and citation data source |
| Poppler Utils | PDF to SVG conversion |
| Matplotlib | Citation plot generation |
- Package Manager: npm
- Build Tool: Turbopack (Next.js)
- Development Server: Port 9002
- Static Export:
output: 'export'for GitHub Pages compatibility
Purpose: Visual map of the entire project file and folder organization
When to use this section: Finding where files live, understanding project layout
Related Sections: Component Architecture • Data Management • Python Scripts
blalterman.github.io/
├── .github/
│ └── workflows/ # GitHub Actions automation
│ ├── update-ads-publications.yml
│ ├── update-ads-metrics.yml
│ ├── update_annual_citations.yml
│ ├── convert-pdfs.yml
│ └── deploy.yaml (implied)
│
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── page.tsx # Home page (/)
│ │ ├── layout.tsx # Root layout with metadata
│ │ ├── globals.css # Global Tailwind styles
│ │ ├── research/
│ │ │ ├── page.tsx # Research overview (/research)
│ │ │ ├── [slug]/page.tsx # Dynamic research topic pages
│ │ │ ├── figure/[paper_id]/[figure_id]/page.tsx # Figure detail pages
│ │ │ └── layout.tsx # Header + Contact wrapper
│ │ ├── publications/
│ │ │ ├── page.tsx # Publications list
│ │ │ ├── loading.tsx
│ │ │ └── layout.tsx
│ │ └── experience/
│ │ ├── page.tsx # Education & positions
│ │ └── layout.tsx
│ │
│ ├── components/ # React components
│ │ ├── ui/ # Shadcn/ui components (52 files)
│ │ ├── icons/ # Custom SVG icons
│ │ ├── header.tsx # Navigation header
│ │ ├── research-topic.tsx # Research topic page component
│ │ ├── about.tsx
│ │ ├── experience.tsx
│ │ ├── contact.tsx
│ │ └── mobile-nav.tsx
│ │
│ ├── lib/ # Utility functions
│ │ ├── data-loader.ts # JSON data loading
│ │ ├── publication-utils.ts # Publication filtering/sorting
│ │ ├── render-math.ts # LaTeX rendering
│ │ └── utils.ts # General utilities
│ │
│ ├── hooks/ # React hooks
│ │ └── use-toast.ts
│ │
│ └── types/ # TypeScript interfaces
│ └── publication.ts
│
├── public/ # Static assets
│ ├── Alterman-CV.pdf # AUTO: CV PDF (pushed by private CV repo)
│ ├── data/ # JSON data files
│ │ ├── ads_publications.json # AUTO: Publications from ADS
│ │ ├── ads_metrics.json # AUTO: Citation metrics
│ │ ├── citations_by_year.json # AUTO: Yearly citations
│ │ ├── publication_statistics.json # AUTO: Aggregated publication stats
│ │ ├── invited_metrics.json # AUTO: Invited talk statistics
│ │ ├── non_ads_publications.json # MANUAL: Non-ADS publications (merged at load time)
│ │ ├── invited_conferences.json # MANUAL: Invited conference presentations
│ │ ├── invited_presentations.json # MANUAL: Other invited presentations
│ │ ├── invited_public.json # MANUAL: Invited public/outreach talks
│ │ ├── figure-registry.json # MANUAL: Figure metadata registry
│ │ ├── research-topics/ # MANUAL: Per-topic research data
│ │ │ ├── proton-beams.json
│ │ │ ├── helium-abundance.json
│ │ │ ├── coulomb-collisions.json
│ │ │ └── ... # One file per research topic
│ │ ├── ben-page.json # MANUAL: Ben page structure & content
│ │ ├── publications-categories.json # MANUAL: Publication category definitions
│ │ ├── publications-page.json # MANUAL: Publications overview content
│ │ ├── experience-page.json # MANUAL: Experience overview content
│ │ ├── biography-homepage.json # MANUAL: Homepage biography content
│ │ ├── education.json # MANUAL: Education history
│ │ ├── positions.json # MANUAL: Professional positions
│ │ └── skills.json # MANUAL: Technical skills
│ │
│ ├── paper-figures/ # Research figures
│ │ ├── pdfs/ # Source PDF figures
│ │ └── svg/ # Auto-converted SVG figures
│ │
│ ├── plots/ # Generated visualizations
│ │ └── citations_by_year.svg # AUTO: Citation trend plot
│ │
│ ├── images/ # Static images
│ └── icons/ # Logo and icon assets
│
├── scripts/ # Python automation
│ ├── fetch_ads_publications_to_data_dir.py # Fetch publications
│ ├── fetch_ads_metrics_to_data_dir.py # Fetch metrics
│ ├── fetch_ads_citations_to_data_dir.py # Fetch citations data
│ ├── generate_citations_timeline.py # Generate citations plot
│ ├── generate_h_index_timeline.py # Generate h-index plot
│ ├── generate_publications_timeline.py # Generate publications timeline
│ ├── generate_publication_statistics.py # Aggregate publication stats
│ ├── generate_figure_registry_from_corpus.py # Generate figure registry (manual)
│ ├── merge_invited_conferences.py # Enrich pubs with invited flags
│ ├── compute_invited_metrics.py # Generate invited talk metrics
│ ├── add_non_ads_publication.py # Add non-ADS publications
│ ├── plot_config.py # Shared plot styling
│ ├── utils.py # Shared utilities
│ └── requirements.txt # Python dependencies
│
├── Configuration Files
│ ├── package.json # NPM dependencies & scripts
│ ├── tsconfig.json # TypeScript configuration
│ ├── next.config.ts # Next.js configuration
│ ├── tailwind.config.ts # Tailwind CSS configuration
│ ├── components.json # Shadcn/ui configuration
│ ├── postcss.config.mjs # PostCSS configuration
│ └── .eslintrc.json # ESLint configuration
│
├── Documentation
│ ├── README.md # Project overview
│ ├── CLAUDE.md # Claude Code instructions
│ ├── ARCHITECTURE.md # This file
│ ├── AGENTS.md # Agent documentation
│ └── NVM_SETUP.md # Node version management
│
└── Build Outputs
├── .next/ # Next.js build cache
├── out/ # Static export output
└── .git/ # Git repository
Purpose: Understand how data moves from NASA ADS API through scripts to the deployed site
When to use this section: Debugging data pipelines, understanding automation flow, adding new data sources
Related Sections: GitHub Actions Workflows • Python Scripts • Data Management
┌─────────────────────────────────────────────────────────────┐
│ NASA ADS API │
│ (Publications, Citations, Metrics) │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Publications │ │ Metrics │ │ Citations │
│ Fetcher │ │ Fetcher │ │ Fetcher │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ads_publica- │ │ ads_metrics │ │ citations_ │
│ tions.json │ │ .json │ │ by_year.json │
└──────┬───────┘ └──────────────┘ └──────┬───────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Citation Plot │
│ │ Generator │
│ └──────────────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ citations_by_ │
│ │ year.svg │
│ └──────────────────┘
│
│
▼
┌──────────────────────────────────────────────┐
│ │
│ Manual Data (Research Content) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ research-topics/ │ │ figure-registry │ │
│ │ *.json │ │ .json │ │
│ │ (Per-topic data) │ │ (Figure metadata)│ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ └──────────┬──────────┘ │
│ │ │
└──────────────────────┼───────────────────────┘
│
▼
┌─────────────────────┐
│ Next.js Static │
│ Site Generation │
│ (Dynamic Routes) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ GitHub Pages │
│ Deployment │
└─────────────────────┘
Automated Data (generated by GitHub Actions):
ads_publications.json- Publications from NASA ADS (overwritten weekly — non-ADS entries must NOT go here)ads_metrics.json- Citation metrics and h-indexcitations_by_year.json- Annual citation countspublication_statistics.json- Aggregated stats from all publication sourcesinvited_metrics.json- Invited talk statisticscitations_by_year.svg- Citation trend visualization
Manual Data (curated by maintainer):
non_ads_publications.json- Non-ADS publications (conferences without bibcodes, Zenodo white papers). Merged withads_publications.jsonat load time vialoadAllPublications()invited_conferences.json- Invited conference presentationsinvited_presentations.json- Other invited presentationsinvited_public.json- Public/outreach talks (merged into "Other Invited" in CV)research-topics/*.json- Per-topic research data (one file per topic)figure-registry.json- Figure metadata registry (generated by manual script)education.json&positions.json- Academic and professional historyskills.json- Technical skills data
Cross-Repo:
Alterman-CV.pdf- Compiled CV PDF, pushed topublic/by the private CV repo's GitHub Action. The CV generates its BibTeX from this website's JSON data, making the website the single source of truth for all publications.
Purpose: Complete reference for all automated CI/CD workflows
When to use this section: Debugging automation failures, understanding update schedules, modifying workflows
Related Sections: Data Flow Architecture • Python Scripts • Deployment Process
Quick Links:
File: .github/workflows/update-ads-publications.yml
Trigger: Weekly on Mondays at 04:00 UTC (or manual dispatch)
Purpose: Fetch latest publications from NASA ADS using ORCID
Process:
- Checkout repository
- Set up Python 3.10
- Install dependencies from
scripts/requirements.txt - Run
fetch_ads_publications_to_data_dir.py - Commit changes to main if any exist
Output: /public/data/ads_publications.json
Dependencies:
ADS_DEV_KEY(GitHub secret)ADS_ORCID(GitHub secret)
Data Format:
[
{
"bibcode": "2025ApJ...980...70R",
"title": "Publication title",
"authors": ["Lastname, F.", "..."],
"month": "Month name or empty",
"year": "YYYY-MM-DD",
"journal": "Publication venue",
"publication_type": "article|dataset|inproceedings|...",
"citations": 5,
"url": "https://dx.doi.org/... or https://scixplorer.org/abs/.../abstract"
}
]File: .github/workflows/update-ads-metrics.yml
Trigger: Weekly on Mondays at 03:00 UTC (or manual dispatch)
Purpose: Fetch citation metrics (h-index, total citations, etc.)
Process:
- Run
fetch_ads_metrics_to_data_dir.pywith ORCID argument - Make API request to NASA ADS metrics endpoint
- Commit updated metrics
Output: /public/data/ads_metrics.json
Used By: Publications page for displaying h-index and citation statistics
Data Format:
{
"indicators": { "h": 8 },
"basic stats": { "number of papers": 15 },
"citation stats": { "total number of citations": 42 },
"basic stats refereed": { "number of papers": 12 },
"citation stats refereed": { "total number of citations": 38 }
}File: .github/workflows/update_annual_citations.yml
Trigger: Weekly on Mondays at 00:00 UTC (or manual dispatch)
Purpose: Update yearly citation data and timeline visualizations
Process:
- Run
fetch_ads_citations_to_data_dir.py(data collection)- 7-day caching to avoid redundant API calls
- Fetch citation histogram per year from ADS
- Run
generate_citations_timeline.py(visualization)- Generate citations timeline plot
- Run
generate_h_index_timeline.py(visualization)- Generate h-index timeline plot
- Commit JSON data and all plots
Output:
/public/data/citations_by_year.json/public/plots/citations_by_year.svg/public/plots/citations_by_year.png/public/plots/h_index_timeline.svg/public/plots/h_index_timeline.png
Features:
- Rate limiting with Retry-After headers
- Timezone handling (Eastern Time)
- Separates refereed vs. non-refereed citations
Data Format:
{
"2024": {
"refereed to refereed": 5,
"refereed to nonrefereed": 1,
"nonrefereed to refereed": 0,
"nonrefereed to nonrefereed": 2
}
}File: .github/workflows/update_plots.yml
Trigger: workflow_run (executes after ADS workflows complete successfully) or manual dispatch
Purpose: Generate publication, h-index, and citation timeline visualizations after data updates
Process:
- Waits for completion of all 3 ADS data workflows (publications, metrics, citations)
- Runs
generate_publications_timeline.py- creates publication counts by year/category - Runs
generate_h_index_timeline.py- creates h-index growth visualization - Runs
generate_citations_timeline.py- creates citation trends visualization - Commits generated plots and data files
Outputs:
/public/data/publications_timeline.json/public/plots/publications_timeline.svgand.png/public/plots/h_index_timeline.svgand.png/public/plots/citations_by_year.svgand.png
Key Feature: Uses workflow_run trigger to ensure data dependencies are met before visualization generation
File: .github/workflows/convert-pdfs.yml
Trigger: On push to public/paper-figures/pdfs/ directory
Purpose: Auto-convert PDF figures to web-friendly SVG format
Process:
- Install
poppler-utilsfor PDF conversion - Use
pdftocairoto convert each PDF to SVG - Save to
/public/paper-figures/svg/ - Auto-commit SVG files
Benefit: Simplifies figure management - just upload PDFs and they're automatically converted
The 5 workflows are orchestrated with specific dependencies and trigger patterns to ensure data consistency and proper update sequencing.
┌─────────────────────────────────────────────────────────────────────────┐
│ WEEKLY SCHEDULED UPDATES │
│ (Every Monday, UTC) │
└─────────────────────────────────────────────────────────────────────────┘
TIME-BASED TRIGGERS (Parallel Execution):
══════════════════════════════════════════
00:00 UTC ┌──────────────────────────────────────┐
┌─────┤ update_annual_citations.yml │
│ │ → citations_by_year.json │
│ └──────────────────────────────────────┘
│
03:00 UTC ┌──────────────────────────────────────┐
├─────┤ update-ads-metrics.yml │
│ │ → ads_metrics.json │
│ └──────────────────────────────────────┘
│
04:00 UTC ┌──────────────────────────────────────┐
└─────┤ update-ads-publications.yml │
│ → ads_publications.json │
│ → invited_metrics.json │
│ → publication_statistics.json │
└──────────────────────────────────────┘
│
│ (after all 3 complete)
▼
┌──────────────────────────────────────┐
│ update_plots.yml │
│ TRIGGER: workflow_run (dependency) │
│ │
│ → publications_timeline.json/.svg │
│ → h_index_timeline.svg/.png │
│ → citations_by_year.svg/.png │
└──────────────────────────────────────┘
══════════════════════════════════════════
EVENT-BASED TRIGGERS (Independent):
══════════════════════════════════════════
On Push to ┌──────────────────────────────────────┐
paper-figures/pdfs/ │ convert-pdfs.yml │
└─────────────┤ → paper-figures/svg/*.svg │
└──────────────────────────────────────┘
══════════════════════════════════════════
TRIGGER SUMMARY:
══════════════════════════════════════════
• schedule (cron) ····· 3 workflows (00:00, 03:00, 04:00 UTC Mon)
• workflow_run ········ 1 workflow (plots - waits for data)
• push (path) ········· 1 workflow (PDFs)
• workflow_dispatch ··· All 5 (manual trigger available)
Key Design Decisions:
- Staggered Schedule: Citations (00:00) → Metrics (03:00) → Publications (04:00) prevents API rate limiting
- Dependent Workflow: Timeline plots wait for all 3 ADS workflows to complete before generating visualizations
- Independent Events: PDF conversion runs independently when figure PDFs are pushed
- Manual Overrides: All workflows support
workflow_dispatchfor on-demand execution
Purpose: Detailed reference for all automation scripts in
/scripts/directoryWhen to use this section: Adding new data fetching automation, understanding how figures are processed, debugging data pipeline issues
Related Sections: GitHub Actions Workflows • Data Management • Common Tasks
Quick Links:
All scripts are located in the /scripts/ directory and use shared utilities from utils.py.
Purpose: Consistent path management across all scripts
Functions:
get_repo_root() -> Path
# Returns repository root directory
# Uses Path(__file__).parent.parent
get_public_data_dir() -> Path
# Returns /public/data/ directory
get_public_plots_dir() -> Path
# Returns /public/plots/ directory
get_relative_path(absolute_path: Path) -> str
# Converts absolute paths to relative for displayBenefit: Scripts work correctly regardless of invocation directory
The automation scripts follow a clear separation of concerns pattern with three distinct layers:
Purpose: Retrieve raw data from external APIs and create atomic data files
Scripts:
fetch_ads_publications_to_data_dir.py→ads_publications.jsonfetch_ads_metrics_to_data_dir.py→ads_metrics.jsonfetch_ads_citations_to_data_dir.py→citations_by_year.json
Characteristics:
- Each script fetches from a single source (NASA ADS API)
- Outputs one primary JSON file
- No dependencies on other scripts' output
- Run independently on staggered schedule (Monday 00:00, 03:00, 04:00 UTC)
Purpose: Combine multiple data sources into comprehensive datasets
Master Aggregator: generate_publication_statistics.py
- Inputs (4 sources):
ads_metrics.json(Layer 1)ads_publications.json(Layer 1)invited_presentations.json(manual)invited_conferences.json(manual)
- Process:
- Merges bibliometric metrics with publication counts
- Computes invited talk statistics
- Generates comprehensive summary statistics
- Creates time-series data combining all sources
- Output:
publication_statistics.json
Other Enrichment Scripts:
merge_invited_conferences.py- Enrichesads_publications.jsonwith invited talk flagscompute_invited_metrics.py- Generatesinvited_metrics.jsonfrom publications
Characteristics:
- Read from multiple JSON sources
- Cross-reference data via keys (bibcode, slug, year)
- Produce enriched, combined datasets
- Run after Layer 1 completes
Purpose: Generate plots and timeline visualizations from data files
Scripts:
-
generate_publications_timeline.py- Inputs:
ads_publications.json+invited_presentations.json(optional) - Outputs:
publications_timeline.json,.svg,.pngplots
- Inputs:
-
generate_citations_timeline.py- Input:
citations_by_year.json(pre-aggregated) - Outputs:
citations_by_year.svg,.png
- Input:
-
generate_h_index_timeline.py- Input:
ads_metrics.json(pre-aggregated) - Outputs:
h_index_timeline.svg,.png
- Input:
Characteristics:
- Read from Layer 1 or Layer 2 outputs
- No API calls - visualization only
- Generate both JSON data and plot files (.svg/.png)
- Triggered by
workflow_runafter data updates complete
- Single Responsibility: Each script has one clear purpose (fetch OR aggregate OR visualize)
- Testability: Can test aggregation logic without API calls by using mock JSON files
- Resilience: API failures only affect Layer 1; Layers 2-3 can still run with cached data
- Flexibility: Can re-generate visualizations without re-fetching from APIs
- Clear Dependencies: Layer 2 depends on Layer 1; Layer 3 depends on Layers 1-2
- Parallel Execution: Layer 1 scripts run in parallel (staggered for rate limiting)
- Caching: Only Layer 1 implements caching (7-day for citations)
Monday 00:00-04:00 UTC (Layer 1 - Parallel):
├─ fetch_ads_citations → citations_by_year.json
├─ fetch_ads_metrics → ads_metrics.json
└─ fetch_ads_publications → ads_publications.json
│
├─ merge_invited_conferences → ads_publications.json (enriched)
├─ compute_invited_metrics → invited_metrics.json
└─ generate_publication_statistics → publication_statistics.json
│
└─ (Layer 3 - After all complete):
├─ generate_publications_timeline
├─ generate_citations_timeline
└─ generate_h_index_timeline
Purpose: Fetch publications from NASA ADS using ORCID
Input:
ADS_ORCIDenvironment variableADS_DEV_KEYenvironment variable
Process:
- Query NASA ADS using ORCID
- Fetch 2000 publications with fields: bibcode, title, author, pubdate, journal, doctype, citations, DOI
- Format author names: "Lastname, F. M."
- Highlight "Alterman" author with
<strong>tags - Generate URLs (DOI preferred, fallback to ADS link)
- Output structured JSON
Output: /public/data/ads_publications.json
API Endpoint: https://api.adsabs.harvard.edu/v1/search/query
Purpose: Fetch citation metrics from NASA ADS
Input:
- ORCID (command-line argument)
ADS_DEV_KEYenvironment variable
Process:
- Get all bibcodes for the ORCID
- Make POST request to NASA ADS metrics API
- Receive comprehensive metrics including h-index
- Save full metrics JSON
Output: /public/data/ads_metrics.json
API Endpoint: https://api.adsabs.harvard.edu/v1/metrics
Purpose: Fetch annual citation data from NASA ADS (data collection only)
Features:
- 7-day caching to prevent redundant API calls
- Rate limiting with Retry-After header handling
- Timezone handling (Eastern Time)
- Separation of concerns (data only, no visualization)
Process:
- Get all bibcodes for ORCID
- Query citation histogram by year from ADS
- Separate refereed vs. non-refereed citations
- Save JSON data only
Output:
/public/data/citations_by_year.json
API Endpoint: https://api.adsabs.harvard.edu/v1/metrics
Note: Run generate_citations_timeline.py afterward to create plots from this data.
Purpose: Generate citations timeline plot from cached data (visualization only)
Features:
- Reads from existing JSON data (no API calls)
- Matplotlib line plot visualization
- Centralized plot styling via
plot_config.py - Matches aesthetic of other timeline plots
Process:
- Load
/public/data/citations_by_year.json - Create styled line plots (refereed + non-refereed)
- Apply semi-transparent fill under lines
- Save SVG and PNG to public/plots/
Output:
/public/plots/citations_by_year.svg/public/plots/citations_by_year.png
Note: Must run fetch_ads_citations_to_data_dir.py first to ensure data is current.
Purpose: Generate figure-registry.json from a corpus of paper figure files
Process:
- Scan the figure corpus directory for paper figures
- Extract metadata (paper ID, figure ID, file paths)
- Generate registry entries with SVG paths and paper references
- Write
figure-registry.jsonto/public/data/
Output: /public/data/figure-registry.json
Usage:
python scripts/generate_figure_registry_from_corpus.pyNote: This script is run manually when new figures are added. There is no automated GitHub Actions workflow for figure registry generation.
Purpose: Fetch Creative Commons license information for figures
Process: Looks up DOI to find licensing info
Purpose: Add non-ADS publications (conferences without bibcodes, Zenodo white papers) to website data
Output: /public/data/non_ads_publications.json
Features:
- Interactive CLI prompts for publication metadata
--dry-runflag to preview without writing--from-bibtex <file>flag for batch import from .bib files- Deduplication check (match by title + year)
- Generates synthetic
NOADS-*bibcodes for entries without ADS identifiers
Usage:
# Interactive mode
python scripts/add_non_ads_publication.py
# Batch import from BibTeX
python scripts/add_non_ads_publication.py --from-bibtex path/to/file.bib
# Preview mode
python scripts/add_non_ads_publication.py --dry-runContext: Created during the CV integration project to migrate non-ADS conferences and Zenodo white papers from the CV's manual .bib files to the website's JSON data.
Purpose: Understand how single React components generate multiple static pages from JSON data
When to use this section: Adding new research/ben/publication pages, understanding page generation, modifying page templates
Related Sections: Data Management • Component Architecture • Common Tasks
The site uses Next.js App Router's dynamic routing with static generation to avoid duplicating React/TypeScript code for each research page.
Topic Pages: /src/app/research/[slug]/page.tsx
// Load all raw topic data from JSON files
function loadAllRawTopics(): RawResearchTopicData[] {
const topicsDir = path.join(process.cwd(), 'public/data/research-topics');
const files = fs.readdirSync(topicsDir).filter(f => f.endsWith('.json'));
return files.map(file => {
const content = fs.readFileSync(path.join(topicsDir, file), 'utf8');
return JSON.parse(content);
});
}
export async function generateStaticParams() {
const topics = loadAllRawTopics();
const published = filterPublishedProjects(topics);
return published.map(topic => ({ slug: topic.slug }));
}Figure Detail Pages: /src/app/research/figure/[paper_id]/[figure_id]/page.tsx
function loadFigureRegistry(): FigureRegistry {
const registryPath = path.join(process.cwd(), 'public/data/figure-registry.json');
return JSON.parse(fs.readFileSync(registryPath, 'utf8'));
}
export async function generateStaticParams() {
const registry = loadFigureRegistry();
return Object.values(registry).map((entry: FigureRegistryEntry) => ({
paper_id: entry.paper_id,
figure_id: entry.figure_id,
}));
}At Build Time:
generateStaticParams()reads allresearch-topics/*.jsonfiles- Filters to published topics, extracts slugs
- Next.js generates static HTML for each topic slug:
/out/research/proton-beams.html/out/research/helium-abundance.html/out/research/coulomb-collisions.html- etc.
- Separately, figure detail pages read
figure-registry.jsonand generate:/out/research/figure/Alterman_2018_ApJ_864_112/fig_1.html- etc.
At Runtime (Static Site):
- Each HTML file contains pre-rendered content
- No server-side processing needed
- Fast page loads
- DRY Principle: One template instead of 8+ duplicate files
- Data-Driven: Adding pages requires only JSON updates
- Consistent Styling: All pages guaranteed to have identical structure
- Easier Maintenance: Layout changes only need updating in one place
- Static Export Compatible: Generates individual HTML files for GitHub Pages
- Type Safety: TypeScript ensures data structure consistency
Behavior: Research topics on /research are organized by fundamental research questions
Implementation: /src/app/research/page.tsx
const researchQuestions: ResearchQuestion[] = [
{
question: 'Where does the solar wind come from?',
subtitle: 'Source Identification',
topics: ['sources-of-the-solar-wind', 'helium-abundance', 'heavy-ion-composition'],
},
// ... additional research questions
];Characteristics:
- Topics are grouped under parent research questions
- Each question has a subtitle and a list of topic slugs
- Only published topics are displayed (filtered at build time)
- Question sections with no published topics are hidden
Create a new JSON file at public/data/research-topics/<slug>.json:
{
"slug": "solar-energetic-particles",
"title": "Solar Energetic Particles",
"subtitle": "Brief subtitle for the topic",
"description": "Brief description for the overview card",
"primary_figure": {
"ref": "Paper_ID/fig_N"
},
"related_figures": [],
"related_topics": [],
"published": true,
"paper": {
"id": "Paper_ID",
"title": "Source paper title",
"doi": "https://doi.org/...",
"bibcode": "2024ApJ...960...70A",
"journal": "The Astrophysical Journal",
"year": 2024,
"license": {
"holder": "American Astronomical Society",
"year": 2024,
"type": "CC BY 4.0"
}
}
}Push to main:
git add public/data/research-topics/solar-energetic-particles.json
git commit -m "Add solar energetic particles research page"
git pushResult: Page automatically exists at /research/solar-energetic-particles
No React/TypeScript files need to be created!
Implemented: 2025-10-29 (Commit: ab8f371)
All three major page types (Research, Ben, Publications) now follow a consistent card-based overview + dynamic subpages pattern:
Overview Page (Card Grid) → Individual Subpages (Dynamic Routes)
This architecture provides:
- Consistent Navigation: Users experience identical interaction patterns across all sections
- Discoverability: Card grids with icons and descriptions help users explore content
- Scalability: Adding new pages requires only JSON updates
- Single Source of Truth: One template generates all subpages in each category
Pattern: Overview → Dynamic Research Topics → Figure Detail Pages
Overview Page: /src/app/research/page.tsx
- Displays research topics organized by fundamental questions
- Links to individual research topic pages
Dynamic Topic Pages: /src/app/research/[slug]/page.tsx
- Generates pages for each research topic
- Data sources:
research-topics/*.json,figure-registry.json - Renders primary figure, related figures, and topic content via
ResearchTopiccomponent
Figure Detail Pages: /src/app/research/figure/[paper_id]/[figure_id]/page.tsx
- Individual pages for each figure in the registry
- Data source:
figure-registry.json - Shows full-size figure with metadata and citation info
Layout: /src/app/research/layout.tsx
- Wraps all research pages (overview, topics, figures) with Header + Contact
URL Structure:
/research- Research overview/research/proton-beams- Individual topic/research/helium-abundance- Individual topic/research/figure/Alterman_2018_ApJ_864_112/fig_1- Figure detail- etc.
Pattern: Card Overview → Dynamic Ben Subpages
Overview Page: /src/app/ben/page.tsx
- Displays grid of thought leadership topic cards
- Each card shows icon, title, and excerpt
- Links to individual Ben subpages
Dynamic Subpages: /src/app/ben/[slug]/page.tsx
- Generates pages for each topic (Research Vision, Team Ethos, Mentorship Philosophy, Open Science)
- Data source:
ben-page.json(single file withsectionsarray)
URL Structure:
/ben- Card grid overview/ben/research-vision- Individual topic/ben/team-ethos- Individual topic/ben/mentorship-philosophy- Individual topic/ben/open-science- Individual topic
Data Schema (ben-page.json):
{
"heading": "About Ben",
"tagline": "How I ask big questions and who I ask them with",
"sections": [
{
"title": "Research Vision",
"slug": "research-vision",
"icon": "Telescope",
"excerpt": "1-2 sentence summary for card",
"paragraphs": ["Full content paragraph 1", "paragraph 2", ...],
"published": true
}
]
}Adding New Ben Page:
- Edit
public/data/ben-page.json - Add new section to
sectionsarray with slug, title, icon, excerpt, paragraphs - Set
published: true(orfalsefor drafts) - Push to main - page automatically exists at
/ben/[slug]
Pattern: Card Overview → Dynamic Category Pages
Overview Page: /src/app/publications/page.tsx
- Displays publication metrics dashboard
- Shows grid of publication category cards
- Each card shows count, icon, and description
- Links to individual category pages
Dynamic Subpages: /src/app/publications/[category]/page.tsx
- Generates pages for each publication category
- Data sources:
publications-categories.json,ads_publications.json - Includes interactive filtering UI (authorship, year, journal, invited/contributed)
URL Structure:
/publications- Metrics dashboard + category card grid/publications/refereed- Refereed articles table/publications/conferences- Conference publications table/publications/datasets- Dataset publications table- etc.
Data Schema (publications-categories.json):
{
"heading": "Publications",
"tagline": "Peer-reviewed research and data products",
"categories": [
{
"title": "Refereed Articles",
"slug": "refereed",
"icon": "BookOpen",
"description": "Peer-reviewed journal publications",
"publicationType": "article",
"showCitations": true,
"showFilters": true,
"journalLabel": "Journal",
"journalField": "journal"
}
]
}Configuration Options (per category):
showFilters: Enable/disable interactive filtering UIshowCitations: Show/hide citations columnshowJournal: Show/hide journal/venue columnshowLinks: Show/hide links columnjournalLabel: Custom column header (e.g., "Venue" vs "Journal")journalField: Which field to display ("journal"or"location")
Adding New Publications Category:
- Edit
public/data/publications-categories.json - Add new category to
categoriesarray - Specify
publicationTypeto filter publications - Configure display options (filters, citations, etc.)
- Push to main - page automatically exists at
/publications/[slug]
All three dynamic route systems support draft pages via the published field:
// In generateStaticParams():
const publishedItems = isDev ? allItems : allItems.filter(item => item.published !== false);Behavior:
- Development (
npm run dev): All pages accessible, includingpublished: false - Production (
npm run build): Only pages withpublished !== falseare generated
Use Case: Create and test new pages locally before making them public
- Consistency: Users navigate all major sections identically
- Discoverability: Card grids encourage exploration
- Maintainability: Same routing pattern across all dynamic page types
- Scalability: JSON-only updates to add pages
- Type Safety: TypeScript ensures schema consistency
- SEO: Each page generates individual HTML with proper metadata
Purpose: Complete reference for React components, page structure, and utility functions
When to use this section: Building new UI components, understanding page layouts, adding utilities
Related Sections: Dynamic Route System • Technology Stack • Configuration Files
/src/app/
├── page.tsx # Home page (/)
│ └── Components: Header, About, Contact
│
├── layout.tsx # Root layout
│ ├── Metadata (SEO, OpenGraph, Twitter)
│ ├── JSON-LD structured data for Person schema
│ ├── Global styles
│ └── Font loading (Inter from Google Fonts)
│
├── research/
│ ├── page.tsx # Research overview (/research)
│ │ └── Topic cards organized by research questions (from research-topics/*.json)
│ │
│ ├── [slug]/page.tsx # Dynamic research topic pages
│ │ ├── generateStaticParams() reads from research-topics/*.json
│ │ ├── Resolves figure refs against figure-registry.json
│ │ ├── ResearchTopic component with primary + related figures
│ │ └── Math rendering via LaTeX
│ │
│ ├── figure/[paper_id]/[figure_id]/page.tsx # Figure detail pages
│ │ ├── generateStaticParams() reads from figure-registry.json
│ │ └── Full-size figure display with metadata and citation
│ │
│ └── layout.tsx # Header + Contact wrapper for all research pages
│
├── publications/
│ ├── page.tsx # Publications overview page (/publications)
│ │ ├── Displays ads_metrics.json (h-index, citations)
│ │ ├── Loads publications-categories.json for card display
│ │ ├── Card grid layout for publication categories
│ │ ├── Conditional rendering (only shows categories with publications)
│ │ ├── Links to /publications/[category] subpages
│ │ └── Count badges on each card
│ │
│ ├── [category]/
│ │ └── page.tsx # Dynamic publication category pages
│ │ ├── generateStaticParams() from publications-categories.json
│ │ ├── Filters publications by publicationType
│ │ ├── Displays full publication table for category
│ │ ├── Conditional Citations column (showCitations flag)
│ │ └── Breadcrumb navigation
│ │
│ ├── loading.tsx # Loading state component
│ └── layout.tsx
│
├── experience/
│ ├── page.tsx # Education & positions (/experience)
│ │ └── Timeline view of education.json and positions.json
│ │
│ └── layout.tsx
│
├── ben/
│ ├── page.tsx # Ben overview page (/ben) - card grid
│ │ ├── Loads ben-page.json (heading, tagline, sections array)
│ │ ├── Filters published sections (environment-aware)
│ │ ├── Card grid layout (responsive 1/2/3 columns)
│ │ ├── Icon mapping with Lucide React (Telescope, Compass, HeartHandshake)
│ │ ├── Displays title, icon, excerpt on each card
│ │ └── Links to /ben/[slug] subpages
│ │
│ ├── [slug]/
│ │ └── page.tsx # Dynamic Ben subpages
│ │ ├── generateStaticParams() from ben-page.json
│ │ ├── Finds section by slug
│ │ ├── Renders title, icon, full paragraphs
│ │ ├── Environment-aware publishing (dev shows all, production filters)
│ │ └── Breadcrumb navigation
│ │
│ └── layout.tsx
│
└── globals.css # Global Tailwind styles
Shadcn/ui pre-built components (52 files) based on Radix UI primitives with Tailwind styling:
- Layout: Card, Separator, Tabs, Accordion
- Forms: Button, Input, Select, Checkbox, Radio Group, Form, Label
- Data Display: Table, Badge, Avatar, Tooltip, Popover
- Feedback: Toast, Dialog, Alert Dialog, Sheet, Drawer
- Navigation: Navigation Menu, Dropdown Menu, Context Menu, Menubar
- Overlays: Dialog, Sheet, Drawer, Popover, Hover Card
- Charts: Chart components with Recharts integration
header.tsx - Navigation Header
- Sticky, responsive (mobile/desktop)
- Main navigation links: Research, Publications, Experience, Contact
- Social media buttons:
- GitHub
- ORCID
- NASA ADS
- Google Scholar
- arXiv
- Mobile navigation menu
research-topic.tsx - Research Topic Page Component
- Renders a complete research topic page with primary figure, related figures, and content
- Resolves figure references against the figure registry
- Displays figure attribution (journal, DOI, license)
- Links to figure detail pages
- Responsive layout with constrained figure sizing and white backgrounds
experience.tsx - Professional Timeline
- Education and position cards
- Institution, dates, location info
- Chronological ordering (most recent first)
- Degree/position title display
about.tsx - About Section
- Professional bio and introduction
- Research interests
- Current affiliation
contact.tsx - Contact Information
- Footer section with contact details
- Email address
- Links to professional profiles
publication-filters.tsx - Interactive Publication Filtering System
- File: 429 lines of comprehensive client-side filtering UI
- Purpose: Advanced filtering for publication category pages with real-time updates
Features:
- Authorship Filter: Radio buttons (All / First Author / Co-author)
- Invited Filter: Radio buttons for conferences (All / Invited / Contributed)
- Journal Filter: Multi-select dropdown with search functionality
- Year Filter: Multi-select dropdown with search functionality
- Active Filter Badges: Displays current filters with individual remove buttons
- Filter Count Badge: Shows number of active filters on filter button
- Result Count: "Showing X of Y publications" live update
- Empty State: Displays message when no publications match filters
- Clear All: Single-click to reset all filters
Configuration (per category via publications-categories.json):
interface PublicationCategory {
showFilters?: boolean; // Enable/disable entire filtering UI (default: true)
showJournal?: boolean; // Show/hide journal/venue column (default: true)
journalLabel?: string; // Custom column header (default: "Journal")
journalField?: string; // Field to display: "journal" | "location" (default: "journal")
showLinks?: boolean; // Show/hide links column (default: true)
showCitations?: boolean; // Show/hide citations column
}Filter Logic:
- AND between filter types: Must match authorship AND year AND journal
- OR within filter type: Match ANY selected journal OR ANY selected year
- Environment-aware: Works with both client-side filtering and static generation
Example Usage:
<PublicationFilters
publications={filteredPubs}
categoryData={category}
labels={{ journal: "Venue" }} // Custom labels
/>UI Components Used:
- Popover for filter panel
- RadioGroup for single-select filters
- MultiSelect for journal/year filters
- Badge for active filter chips
- Button for Apply/Clear actions
Performance:
- Client-side filtering via
useMemohook - Re-renders only when filter state or publications change
- Efficient array filtering with early returns
Custom SVG icons for external services:
- ORCID Icon - Research identifier
- Google Scholar Icon - Academic profile
- NASA ADS Icon - Astrophysics database
- arXiv Icon - Preprint repository
- LinkedIn Icon - Professional network
- GitHub Icon - Code repository
- Firebase Icon - Backend services
export function loadJSONData<T>(fileName: string): T {
const filePath = path.join(process.cwd(), 'public', 'data', fileName);
const fileContents = fs.readFileSync(filePath, 'utf8');
return JSON.parse(fileContents) as T;
}Purpose: Load JSON data from /public/data/ at build time
Usage:
const metrics = loadJSONData<ADSMetrics>('ads_metrics.json');
const registry = loadJSONData<FigureRegistry>('figure-registry.json');Note: Works with synchronous file reading (server-side only)
sortPublicationsByDate(publications: Publication[]): Publication[]
filterPublicationsByType(publications: Publication[], type: string): Publication[]
getPublicationsByType(publications: Publication[], type: string): Publication[]
sortPublicationsByCitations(publications: Publication[]): Publication[]Purpose: Publication filtering, sorting, and display utilities
Usage Example:
const articles = getPublicationsByType(publications, 'article');
const sortedByDate = sortPublicationsByDate(articles);export function renderMath(text: string): string {
// Converts LaTeX expressions to HTML using KaTeX
// Processes $...$ (inline) and $$...$$ (display) math
}Purpose: Render LaTeX mathematical expressions in research content
Example Input:
The energy is given by $E = mc^2$, which shows:
$$E = \gamma m c^2$$
Example Output:
The energy is given by <span class="katex">...</span>, which shows:
<div class="katex-display">...</div>export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}Purpose: Merge Tailwind CSS class names with conflict resolution
export function filterPublishedProjects<T extends { published?: boolean }>(
projects: T[]
): T[]Purpose: Environment-aware filtering for research projects
Behavior:
- Development: Returns all projects (including unpublished) for testing
- Production: Returns only projects where
published !== false
Usage Example:
const topics = loadAllRawTopics(); // from research-topics/*.json
const publishedTopics = filterPublishedProjects(topics);
// Development: all topics | Production: only published topicsUsed By:
/src/app/research/page.tsx- Filter topics on research overview/src/app/research/[slug]/page.tsx- Filter static params generation
Purpose: Complete reference for all JSON data files and their schemas
When to use this section: Understanding data file formats, adding new data, debugging data issues, creating content
Related Sections: Data Flow Architecture • Python Scripts • Common Tasks
Automated Data Files (Generated by GitHub Actions):
- ads_publications.json - Publications from NASA ADS
- ads_metrics.json - Citation metrics
- citations_by_year.json - Annual citations
- publication_statistics.json - Aggregated publication stats
- invited_metrics.json - Invited talk statistics
Manual Data Files (Curated):
- non_ads_publications.json - Non-ADS publications (merged with ADS at load time)
- invited_conferences.json - Invited conference presentations
- invited_presentations.json - Other invited presentations
- invited_public.json - Invited public/outreach talks
- research-topics/*.json - Per-topic research data
- figure-registry.json - Figure metadata registry
- ben-page.json - Ben page structure
- publications-categories.json - Publication categories
- education.json - Academic credentials
- positions.json - Employment history
- skills.json - Technical skills
Updated: Weekly on Mondays at 04:00 UTC
Source: NASA ADS API via ORCID
Structure:
[
{
"bibcode": "2025ApJ...980...70R",
"title": "Paper title here",
"authors": [
"Lastname, F. M.",
"<strong>Alterman, B. L.</strong>",
"Another, A. B."
],
"month": "January",
"year": "2025-01-15",
"journal": "The Astrophysical Journal",
"publication_type": "article",
"citations": 5,
"url": "https://dx.doi.org/10.3847/..."
}
]Publication Types:
article- Journal articleseprint- Preprintsinproceedings- Conference papersdataset- Data publicationssoftware- Software releasesposter- Conference postersabstract- Conference abstracts
Used By:
- Publications page (/publications)
Updated: Weekly on Mondays at 03:00 UTC
Source: NASA ADS Metrics API
Structure:
{
"indicators": {
"h": 8,
"g": 12,
"i10": 7,
"tori": 5.2,
"riq": 42,
"m": 1.6
},
"basic stats": {
"number of papers": 15,
"normalized paper count": 12.5
},
"citation stats": {
"total number of citations": 42,
"number of citing papers": 35,
"average citations": 2.8,
"median citations": 2.0,
"normalized citations": 38.5
},
"basic stats refereed": {
"number of papers": 12,
"normalized paper count": 10.8
},
"citation stats refereed": {
"total number of citations": 38,
"number of citing papers": 32,
"average citations": 3.2
}
}Key Metrics:
- h-index: Number h where h papers have at least h citations
- g-index: Largest number g where top g papers have at least g² citations
- i10-index: Number of papers with at least 10 citations
Used By: Publications page (displayed as summary cards)
Updated: Weekly on Mondays at 00:00 UTC
Source: NASA ADS Metrics API
Structure:
{
"2019": {
"refereed to refereed": 2,
"refereed to nonrefereed": 1,
"nonrefereed to refereed": 0,
"nonrefereed to nonrefereed": 3
},
"2020": {
"refereed to refereed": 5,
"refereed to nonrefereed": 2,
"nonrefereed to refereed": 1,
"nonrefereed to nonrefereed": 4
}
}Citation Types:
- refereed to refereed: Peer-reviewed paper citing peer-reviewed paper
- refereed to nonrefereed: Peer-reviewed citing non-peer-reviewed
- nonrefereed to refereed: Non-peer-reviewed citing peer-reviewed
- nonrefereed to nonrefereed: Non-peer-reviewed citing non-peer-reviewed
Used By:
- SVG plot generation (citations_by_year.svg)
- Publications page (future implementation)
Updated: Weekly (generated after publications and metrics update)
Source: Generated by generate_publication_statistics.py
Purpose: Aggregated publication and presentation statistics from all sources
Inputs:
ads_publications.json+non_ads_publications.json(all publications)ads_metrics.json(h-index, citation stats)invited_presentations.json(invited talks)invited_conferences.json(invited conference presentations)
Used By: Publications page (summary statistics display)
Updated: Weekly (generated by compute_invited_metrics.py)
Source: Computed from ads_publications.json + invited talk data
Purpose: Statistics about invited presentations (counts by year, totals)
Used By: Publications page
Purpose: Publications not indexed in NASA ADS (non-ADS conferences, Zenodo white papers)
Type: Manual (curated via add_non_ads_publication.py)
Important: This file exists because the weekly ADS fetch completely overwrites ads_publications.json. Non-ADS entries stored here survive weekly updates. Both files are merged at load time via loadAllPublications() in src/lib/data-loader.ts.
Structure:
[
{
"bibcode": "NOADS-IAU-CME",
"title": "Charge-State Dependent Heating...",
"authors": ["Alterman, B. L."],
"month": "",
"year": "2024-05-00",
"journal": "IAU/CME",
"publication_type": "inproceedings",
"citations": 0,
"url": "",
"invited": false
}
]Key Fields:
- bibcode: Synthetic identifier with
NOADS-prefix (e.g.,NOADS-Arcetri-2022) - Same schema as
ads_publications.jsonentries for seamless merging
Used By:
- Publications pages (merged with ADS publications at load time)
- CV repo's BibTeX generation script (fetches from live site)
Purpose: Invited conference presentations
Type: Manual (curated)
Structure:
[
{
"title": "Collisions in an Expanding Solar Wind (Scene Setting Talk)",
"authors": ["Alterman, B. L."],
"year": "2017-07-00",
"month": "7",
"publication_type": "inproceedings",
"citations": 0,
"invited": true,
"booktitle": "SHINE Conference",
"journal": "SHINE Conference",
"keywords": "invited",
"url": ""
}
]Used By:
generate_publication_statistics.py(aggregation)merge_invited_conferences.py(enriches publications with invited flags)- CV repo's BibTeX generation
Purpose: Other invited presentations (seminars, colloquia, tutorials)
Type: Manual (curated)
Structure: Same schema as invited_conferences.json
Used By:
generate_publication_statistics.py(aggregation)generate_publications_timeline.py(timeline visualization)- CV repo's BibTeX generation
Purpose: Invited public/outreach talks (public lectures, science communication events)
Type: Manual (curated). Currently empty — placeholder for future entries.
Structure: Same schema as invited_conferences.json
CV Integration: Merged into "Other Invited Presentations" (keyword=invitedother) by the CV's generate_bibtex_from_website.py. Entries added here will automatically appear in the CV's "Other Invited Presentations" section on next build.
Used By:
- CV repo's BibTeX generation (merged with
invited_presentations.json)
Purpose: Per-topic research data files. Each research topic has its own JSON file in public/data/research-topics/.
Structure (per file):
{
"slug": "proton-beams",
"title": "Proton Beams",
"subtitle": "Brief subtitle for the topic",
"description": "Brief description for the overview card",
"primary_figure": {
"ref": "Alterman_2018_ApJ_864_112/fig_2"
},
"related_figures": [
{
"ref": "Alterman_2018_ApJ_864_112/fig_1",
"relevance": "Description of why this figure is relevant"
}
],
"related_topics": [],
"published": false,
"paper": {
"id": "Alterman_2018_ApJ_864_112",
"title": "Paper title",
"doi": "https://doi.org/...",
"bibcode": "2018ApJ...864..112A",
"journal": "The Astrophysical Journal",
"year": 2018,
"license": {
"holder": "American Astronomical Society",
"year": 2018,
"type": "CC BY 3.0"
}
}
}Fields:
- slug: URL-safe identifier (used in /research/[slug]), must match the filename
- title: Display title (used in headers)
- subtitle: Brief subtitle displayed below the title
- description: Brief summary (shown on research overview page)
- primary_figure.ref: Reference to figure in
figure-registry.json(format:paper_id/figure_id) - related_figures: Array of additional figures with relevance descriptions
- related_topics: Slugs of related research topics
- published: (optional, boolean) Whether page is visible in production. Defaults to
true. Set tofalseto hide page in production builds while keeping it visible in development - paper: Source publication metadata including DOI, bibcode, journal, and license
Used By:
- Research overview page (/research)
- Research topic pages (generateStaticParams)
Purpose: Central registry of all figures available for use on research pages. Maps figure references to file paths and metadata.
Structure:
{
"Alterman_2018_ApJ_864_112/fig_1": {
"paper_id": "Alterman_2018_ApJ_864_112",
"figure_id": "fig_1",
"svg_path": "/paper-figures/svg/Alterman_2018_ApJ_864_112_fig_1.svg",
"alt": "Description of the figure",
"caption": "Figure caption text"
}
}Key Format: paper_id/figure_id — used as the lookup key in topic files' primary_figure.ref and related_figures[].ref fields
Generated By: scripts/generate_figure_registry_from_corpus.py (run manually)
Used By:
- Research topic pages (resolve figure refs to file paths)
- Figure detail pages (generateStaticParams, display)
Purpose: Academic credentials
Structure:
[
{
"Institution": "University of Michigan",
"Department": "Applied Physics",
"Location": "Ann Arbor, MI",
"Dates": "2012 – 2019",
"Degree": "Doctor of Philosophy"
},
{
"Institution": "University of Michigan",
"Department": "Applied Physics",
"Location": "Ann Arbor, MI",
"Dates": "2012 – 2014",
"Degree": "Master of Science"
}
]Used By: Experience page (/experience)
Purpose: Professional employment history
Structure:
[
{
"Company": "NASA Goddard Space Flight Center",
"Position Title": "Research Astrophysicist",
"Dates": "2024 – Present",
"Location": "Greenbelt, MD"
},
{
"Company": "NASA Goddard Space Flight Center",
"Position Title": "Postdoctoral Research Associate",
"Dates": "2019 – 2024",
"Location": "Greenbelt, MD"
}
]Used By: Experience page (/experience)
Purpose: Technical skills and competencies
Structure:
{
"Programming Languages": ["Python", "JavaScript", "TypeScript", "IDL"],
"Frameworks & Tools": ["Next.js", "React", "Tailwind CSS", "Git"],
"Scientific Computing": ["NumPy", "SciPy", "Matplotlib", "Pandas"],
"Data Analysis": ["Statistical modeling", "Data visualization", "Machine learning"]
}Used By: Future resume/CV page
Purpose: Defines Ben page overview structure and subpage content
Type: Manual (curated)
Structure:
{
"heading": "About Ben",
"tagline": "How I ask big questions and who I ask them with.",
"sections": [
{
"title": "Research Vision",
"slug": "research-vision",
"icon": "Telescope",
"excerpt": "I study the Sun and solar wind to discover what it means for a Sun to create a habitable zone and to power life on Earth.",
"paragraphs": ["...", "..."],
"published": true
}
]
}Schema:
heading(string): Page titletagline(string): Page subtitlesections(array):title(string): Section titleslug(string): URL-safe identifier for subpage routeicon(string): Lucide React icon name (e.g., "Telescope", "Compass", "HeartHandshake")excerpt(string): Short description (~100 chars) for card preview on overview pageparagraphs(string[]): Full content paragraphs for subpagepublished(boolean, optional): Whether to show in production (defaults to true)
Used By:
- Ben overview page (
/src/app/ben/page.tsx) - Ben subpages (
/src/app/ben/[slug]/page.tsx)
Environment-Aware Publishing:
- Development mode: Shows all sections regardless of
publishedfield - Production mode: Only generates routes for sections with
published: true
Purpose: Defines publication categories for overview cards and subpage routing
Type: Manual (curated)
Structure:
{
"heading": "Publications",
"tagline": "Peer-reviewed research, datasets, and conference contributions",
"categories": [
{
"title": "Refereed Publications",
"slug": "refereed",
"icon": "BookOpen",
"description": "Peer-reviewed journal articles",
"publicationType": "article",
"showCitations": true
}
]
}Schema:
heading(string): Page titletagline(string): Page subtitlecategories(array):title(string): Display name for categoryslug(string): URL-safe identifier for subpage routeicon(string): Lucide React icon name (e.g., "BookOpen", "Database", "FileText")description(string): Short description for cardpublicationType(string | string[]): ADS publication type(s) to filter (article,dataset,inproceedings,abstract,techreport,eprint,phdthesis)showCitations(boolean): Whether to display citations column in table
Filter & Display Configuration (Optional):
showFilters(boolean): Enable/disable interactive filtering UI (default:true)showJournal(boolean): Show/hide journal/venue column (default:true)showLinks(boolean): Show/hide links column (default:true)journalLabel(string): Custom column header (default:"Journal")- Example:
"Venue"for conferences
- Example:
journalField(string): Field to display in column (default:"journal")- Options:
"journal"|"location" - Use
"location"for conferences to show venue instead of journal name
- Options:
Used By:
- Publications overview page (
/src/app/publications/page.tsx) - Publications category subpages (
/src/app/publications/[category]/page.tsx)
Conditional Rendering:
- Categories with zero publications are automatically hidden from overview cards
- Only generates static routes for categories that have publications
Publication Type Mapping:
article→ Refereed Publicationsdataset→ Datasetsinproceedings→ Conference Proceedingsabstract→ Conference Presentationstechreport→ White Paperseprint→ Pre-Printsphdthesis→ PhD Thesis
Purpose: Complete reference for all configuration files and their settings
When to use this section: Modifying build settings, updating dependencies, configuring tools
Related Sections: Technology Stack • Development Workflow • Deployment Process
Development Scripts:
{
"scripts": {
"dev": "next dev --turbopack -p 9002",
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit"
}
}Key Dependencies:
next@15.5.3- React frameworkreact@18.3.1- UI librarytypescript@5- Type safetytailwindcss@3.4.1- Stylingkatex@0.16.22- Math renderingrecharts@2.15.1- Chartslucide-react@0.475.0- Iconszod@3.24.2- Validationreact-hook-form- Forms
Development:
- Port: 9002
- Turbopack: Enabled for faster builds
- Hot Module Replacement: Automatic
Critical Configuration:
const isProd = process.env.NODE_ENV === 'production';
const baseUrl = 'https://blalterman.github.io';
const nextConfig: NextConfig = {
output: 'export', // Static site generation
assetPrefix: isProd ? baseUrl : '', // GitHub Pages URL prefix
basePath: '',
typescript: {
ignoreBuildErrors: true, // Allow build despite TS errors
},
eslint: {
ignoreDuringBuilds: true, // Allow build despite lint errors
},
images: {
unoptimized: true, // Required for static export
remotePatterns: [
{
protocol: 'https',
hostname: 'placehold.co',
},
],
},
trailingSlash: false,
};Why These Settings:
output: 'export'- Generates static HTML files (required for GitHub Pages)assetPrefix- Ensures assets load correctly on GitHub Pages subdomainignoreBuildErrors- Allows CI/CD to complete even with type issuesimages.unoptimized- Next.js Image Optimization requires server, disabled for static exporttrailingSlash: false- Cleaner URLs without trailing slashes
Key Settings:
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./src/*"]
}
}
}Path Aliases:
@/*maps to./src/*- Enables clean imports:
import { Header } from '@/components/header'
Theme Configuration:
export default {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
// ... 20+ semantic color tokens
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],
}Features:
- CSS variables for dynamic theming
- Dark mode support (class-based)
- Custom color system with 10+ semantic tokens
- Chart colors (5 variables)
- Sidebar component colors
- Animation utilities
Configuration:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}Usage:
# Add new component
npx shadcn@latest add button
# Component installed to: src/components/ui/button.tsxPurpose: Step-by-step guide for local development, testing, and building
When to use this section: Setting up dev environment, running tests, building for production
Related Sections: Configuration Files • Common Tasks • Troubleshooting
1. Install Dependencies:
npm install2. Start Development Server:
npm run dev
# Runs on http://localhost:9002 with Turbopack3. Make Changes:
- Edit React components in
/src/ - Update data files in
/public/data/ - Modify styles in
/src/app/globals.css - Hot Module Replacement updates automatically
4. Type Check:
npm run typecheck5. Lint:
npm run lint1. Install Python Dependencies:
pip install -r scripts/requirements.txt2. Test Data Fetching (requires ADS credentials):
export ADS_DEV_KEY="your-ads-api-key"
export ADS_ORCID="0000-0001-2345-6789"
# Fetch data from NASA ADS
python scripts/fetch_ads_publications_to_data_dir.py
python scripts/fetch_ads_metrics_to_data_dir.py
python scripts/fetch_ads_citations_to_data_dir.py
# Generate visualizations
python scripts/generate_citations_timeline.py
python scripts/generate_h_index_timeline.py3. Test Figure Registry Generation:
python scripts/generate_figure_registry_from_corpus.pyCreate a new topic file at public/data/research-topics/<slug>.json with the topic data structure (see research-topics/*.json for the full schema).
Note: By default, pages are published. To create a draft page visible only in development, add "published": false to the topic definition.
Commit and push:
git add public/data/research-topics/new-research-topic.json
git commit -m "Add new research topic"
git push- Upload PDF to
/public/paper-figures/pdfs/:
cp my-figure.pdf public/paper-figures/pdfs/
git add public/paper-figures/pdfs/my-figure.pdf
git commit -m "Add new research figure"
git push- Automatic Conversion:
- GitHub Actions workflow triggers on push
- PDF automatically converted to SVG
- SVG saved to
/public/paper-figures/svg/my-figure.svg
- Regenerate figure registry:
python scripts/generate_figure_registry_from_corpus.py
git add public/data/figure-registry.json
git commit -m "Regenerate figure registry"
git push- Reference the figure in a topic file using its registry key (e.g.,
Paper_ID/fig_N) in theprimary_figure.reforrelated_figures[].reffield.
Education:
Edit /public/data/education.json
Positions:
Edit /public/data/positions.json
Skills:
Edit /public/data/skills.json
Commit Changes:
git add public/data/education.json public/data/positions.json
git commit -m "Update professional information"
git push1. Build Static Site:
npm run build2. Output Location:
/out/
├── index.html
├── research/
│ ├── index.html
│ ├── proton-beams.html
│ ├── helium-abundance.html
│ ├── figure/
│ │ └── Alterman_2018_ApJ_864_112/
│ │ ├── fig_1.html
│ │ └── fig_2.html
│ └── ...
├── publications/
│ └── index.html
├── experience/
│ └── index.html
└── _next/
└── static/...
Note: Research topics are organized by research questions defined in the overview page component.
3. Test Locally:
npm run start
# Or serve the /out directory with any static serverPurpose: Understand automated and manual deployment to GitHub Pages
When to use this section: Deploying changes, debugging deployment issues, understanding CI/CD flow
Related Sections: GitHub Actions Workflows • Configuration Files • Troubleshooting
Trigger: Push to main branch
Process:
-
Data Workflows Run:
- Update ADS publications (if Monday 04:00 UTC)
- Update ADS metrics (if Monday 03:00 UTC)
- Update annual citations (if Monday 00:00 UTC)
- Generate figure data (if data files changed)
-
Build Workflow:
- Checkout repository
- Install Node.js dependencies
- Run
npm run build - Generate static site to
/out
-
Deploy to GitHub Pages:
- Push
/outcontents togh-pagesbranch - GitHub Pages serves from
gh-pagesbranch - Site available at: https://blalterman.github.io
- Push
Result: Site automatically updates with latest data and content
1. Build Locally:
npm run build2. Deploy to GitHub Pages:
# Install gh-pages package if not already installed
npm install -g gh-pages
# Deploy /out directory to gh-pages branch
gh-pages -d out3. Verify Deployment: Visit https://blalterman.github.io
┌─────────────────┐
│ Push to main │
└────────┬────────┘
│
▼
┌─────────────────────────────┐
│ GitHub Actions Triggered │
└────────┬────────────────────┘
│
├──→ Data Workflows (if scheduled)
│ ├─ Update publications
│ ├─ Update metrics
│ └─ Update citations
│
├──→ Figure Data Generation (if data changed)
│
└──→ Build Workflow
├─ npm install
├─ npm run build
└─ Generate /out
│
▼
┌────────────────┐
│ Deploy to │
│ gh-pages │
└────────┬───────┘
│
▼
┌────────────────┐
│ GitHub Pages │
│ Serves Site │
└────────────────┘
Purpose: Step-by-step guides for frequently performed operations
When to use this section: Adding content, updating information, performing routine maintenance
Related Sections: Data Management • Development Workflow • Troubleshooting
Note: Publications are automatically fetched from ADS. Manual addition only needed for non-ADS publications.
1. Edit ads_publications.json:
{
"bibcode": "custom-bibcode-2024",
"title": "Publication title",
"authors": ["Author, A.", "<strong>Alterman, B. L.</strong>"],
"month": "January",
"year": "2024-01-15",
"journal": "Journal Name",
"publication_type": "article",
"citations": 0,
"url": "https://doi.org/..."
}2. Commit and push:
git add public/data/ads_publications.json
git commit -m "Add manual publication entry"
git pushEdit /src/app/layout.tsx:
export const metadata: Metadata = {
title: 'B. L. Alterman | Research Astrophysicist',
description: 'Updated description here',
keywords: ['astrophysics', 'solar wind', 'heliophysics'],
openGraph: {
title: 'B. L. Alterman',
description: 'Updated description',
url: 'https://blalterman.github.io',
siteName: 'B. L. Alterman',
images: [
{
url: 'https://blalterman.github.io/images/og-image.png',
width: 1200,
height: 630,
},
],
locale: 'en_US',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'B. L. Alterman',
description: 'Updated description',
images: ['https://blalterman.github.io/images/og-image.png'],
},
};Edit /src/app/globals.css:
@layer base {
:root {
--background: 0 0% 100%; /* White */
--foreground: 0 0% 3.9%; /* Near black */
--primary: 0 0% 9%; /* Dark gray */
--primary-foreground: 0 0% 98%; /* Light gray */
/* ... update other color variables ... */
}
.dark {
--background: 0 0% 3.9%; /* Dark background */
--foreground: 0 0% 98%; /* Light text */
/* ... dark mode colors ... */
}
}1. Create Icon Component (if needed):
Create /src/components/icons/NewServiceIcon.tsx
2. Edit /src/components/header.tsx:
import { NewServiceIcon } from '@/components/icons/NewServiceIcon';
// In the social buttons section:
<Button variant="ghost" size="icon" asChild>
<a
href="https://newservice.com/username"
target="_blank"
rel="noopener noreferrer"
aria-label="New Service Profile"
>
<NewServiceIcon className="h-5 w-5" />
</a>
</Button>1. Check TypeScript Errors:
npm run typecheck2. Check ESLint Errors:
npm run lint3. Check Data Files:
# Validate JSON syntax
python -m json.tool public/data/figure-registry.json
python -m json.tool public/data/ads_publications.json4. Check Next.js Build Output:
npm run build
# Look for errors in terminal output5. Common Issues:
- Missing data files: Ensure all JSON files exist in
/public/data/ - Invalid JSON: Check for syntax errors in data files
- Image paths: Verify image paths are correct and files exist
- TypeScript errors: May be ignored in production build, but should be fixed
- Module not found: Run
npm installto ensure all dependencies are installed
Use the published field in each topic's JSON file to control research page visibility in production while keeping them accessible in development.
Hide a Research Page:
- Edit
/public/data/research-topics/<slug>.json:
{
"slug": "proton-beams",
"title": "Proton Beams",
"published": false
}- Rebuild:
npm run buildResult:
- Development (
npm run dev): Page visible, card appears - Production (
npm run build): Page not built, card hidden
Re-enable a Page:
Set "published": true or remove the field entirely (defaults to true).
Environment Behavior:
- Development: All pages visible (including unpublished) for testing
- Production: Only published pages built and displayed
Use Cases:
- Draft pages without figures or content
- Placeholder topics for future research
- Temporarily hide pages during updates
The Ben page (/ben) follows the data-driven architecture pattern - all content lives in JSON and is automatically rendered by the React component.
Current Sections:
- "Research Vision" (Telescope icon)
- "Team Ethos" (Compass icon)
If using Telescope or Compass icons (already imported):
1. Edit JSON file:
# Edit: public/data/ben-page.json2. Add new section to the sections array:
{
"heading": "Collaboration & Mentoring",
"icon": "Telescope",
"paragraphs": [
"First paragraph of your content...",
"Second paragraph of your content...",
"Additional paragraphs as needed..."
]
}3. Rebuild:
npm run build✅ Done! The component automatically generates a new card.
If you want a new icon from Lucide React:
1. Update the React component (src/app/ben/page.tsx):
a. Import the new icon:
import { Telescope, Compass, Users } from "lucide-react";
// ^^^^^ new iconb. Add to iconMap:
const iconMap = {
Telescope: Telescope,
Compass: Compass,
Users: Users, // new icon
};2. Edit JSON file (public/data/ben-page.json):
{
"heading": "Collaboration & Mentoring",
"icon": "Users",
"paragraphs": [
"Mentoring is central to how I build teams...",
"I believe in creating opportunities for growth..."
]
}3. Rebuild:
npm run buildBrowse all icons at: https://lucide.dev/icons/
Popular options for additional sections:
Users- Team/collaborationBookOpen- Learning/educationLightbulb- Ideas/innovationTarget- Goals/objectivesAward- AchievementsTrendingUp- Growth/progressGitBranch- Collaboration/workflowHeart- Values/cultureSparkles- Innovation/creativityRocket- Vision/ambition
File: /public/data/ben-page.json
{
"heading": "About Ben",
"tagline": "How I ask big questions and who I ask them with.",
"sections": [
{
"heading": "Section Title",
"icon": "IconName",
"paragraphs": [
"Paragraph 1...",
"Paragraph 2...",
"..."
]
}
]
}Key Points:
- ✅ Sections display in array order
- ✅ Icon names must match keys in
iconMap - ✅ Paragraphs array can have unlimited items
- ✅ All styling is automatic (Shadcn/ui Card components)
1. Development server:
npm run dev
# Visit http://localhost:9002/ben2. Type checking:
npm run typecheck3. Validate JSON:
python -m json.tool public/data/ben-page.jsonPurpose: Solutions for common problems and debugging strategies
When to use this section: Debugging issues, fixing errors, understanding failures
Related Sections: Development Workflow • GitHub Actions Workflows • Common Tasks
Check:
- GitHub Actions workflow runs: https://github.com/blalterman/blalterman.github.io/actions
- Workflow logs for errors
ADS_DEV_KEYandADS_ORCIDsecrets are set in repository settings- NASA ADS API is accessible (not rate-limited)
Manual Update:
export ADS_DEV_KEY="your-key"
export ADS_ORCID="your-orcid"
python scripts/fetch_ads_publications_to_data_dir.pyCheck:
- Topic file exists at
public/data/research-topics/<slug>.json - File contains valid JSON with correct
slugfield matching the filename publishedfield is not set tofalse(or running in development mode)- Site was rebuilt after JSON changes
- No typos in slug names (must match exactly)
Debug:
# List all topic slugs
ls public/data/research-topics/
# Validate a topic file
python -m json.tool public/data/research-topics/<slug>.jsonCheck:
- Figure SVG file exists in
/public/paper-figures/svg/ - Figure has an entry in
figure-registry.jsonwith correctsvg_path - Topic file's
primary_figure.reforrelated_figures[].refmatches a key in the registry - Registry was regenerated after adding new figures
Regenerate Figure Registry:
python scripts/generate_figure_registry_from_corpus.py
git add public/data/figure-registry.json
git commit -m "Regenerate figure registry"
git pushCommon Causes:
- Invalid JSON Syntax:
# Validate all JSON files
for file in public/data/*.json; do
echo "Checking $file"
python -m json.tool "$file" > /dev/null || echo "ERROR in $file"
done- Missing Dependencies:
rm -rf node_modules package-lock.json
npm install- Next.js Cache Issues:
rm -rf .next out
npm run build- TypeScript Errors:
npm run typecheck
# Fix errors or update next.config.ts to ignoreCheck:
- Workflow file syntax (YAML validation)
- Secrets are set correctly in repository settings
- Python dependencies are correct in
requirements.txt - Script paths are correct
- Permissions are set correctly for workflow
View Logs:
- Go to https://github.com/blalterman/blalterman.github.io/actions
- Click on failed workflow run
- Expand failed step to see error details
Purpose: Guidelines for maintaining code quality, consistency, and project health
When to use this section: Establishing conventions, reviewing code, maintaining standards
Related Sections: Development Workflow • Component Architecture
-
Use Path Aliases: Import with
@/prefix instead of relative paths// Good import { Header } from '@/components/header'; // Avoid import { Header } from '../../../components/header';
-
Separate Concerns: Keep data, logic, and UI separate
- Data:
/public/data/*.json - Logic:
/src/lib/*.ts - UI:
/src/components/*.tsx
- Data:
-
Type Everything: Use TypeScript interfaces for all data structures
// Good interface ResearchProject { title: string; slug: string; description: string; } // Avoid const project: any = {...};
-
Validate JSON: Always validate JSON files before committing
python -m json.tool file.json
-
Consistent Naming: Use kebab-case for slugs
proton-beams ✓ ProtonBeams ✗ proton_beams ✗ -
Backup Before Edits: Scripts create backups automatically, but keep manual backups too
-
Per-Topic Files: Each research topic gets its own JSON file in
research-topics/
-
Descriptive Commits: Use clear commit messages
# Good git commit -m "Add solar energetic particles research page" # Avoid git commit -m "Update files"
-
Atomic Commits: One logical change per commit
-
Test Before Push: Build locally before pushing
npm run build # Verify no errors git push
-
Optimize Images: Use SVG for figures when possible (done automatically by PDF converter)
-
Lazy Load: Next.js handles this automatically for App Router
-
Static Generation: Site is fully static - no server-side overhead
-
Minimize Data Files: Keep JSON files focused and minimal
This project is developed with assistance from AI tools. Follow these guidelines:
-
Human Review Required: All AI-generated code must be reviewed and approved by a human developer
-
Follow Conventions: Adhere to Next.js patterns, semantic HTML in React components, and maintain type safety
-
Prompt Analysis: For moderate-to-complex tasks, AI should proactively analyze prompts for clarity, missing context, and efficiency opportunities
-
Incremental Changes: Request small, verifiable changes instead of sweeping rewrites
-
Document AI Contributions: Use commit message prefixes (e.g.,
AI:) or co-author tags for AI-assisted work
📘 See AGENTS.md for complete AI development protocols:
- Prompt Improvement Protocol - When and how to analyze prompts
- Development Conventions - Code standards and review requirements
- Prompting Guidelines - Best practices for effective AI collaboration
- Agent Use Cases - Common AI-assisted tasks
Purpose: Planned features and potential improvements for future development
When to use this section: Planning new features, understanding roadmap, proposing improvements
-
Interactive Citation Graphs: Add interactive Recharts visualization for citations over time
-
Search Functionality: Add client-side search for publications
-
Dark Mode Toggle: Add user-selectable dark mode (currently class-based)
-
RSS Feed: Generate RSS feed for publications
-
Blog Section: Add research blog with markdown support
-
CV Download: Auto-generate PDF CV from data files
-
Publication Filters: Add more advanced filtering (by year, journal, topic)
-
Figure Lightbox: Add lightbox/modal for viewing figures in detail
-
Collaboration Network: Visualize co-author network
-
Research Timeline: Interactive timeline of research projects
Purpose: Links to external documentation, tools, and community resources
When to use this section: Learning about technologies, finding documentation, getting help
- ARCHITECTURE.md (this file) - Comprehensive technical reference for developers and AI assistants
- CLAUDE.md - AI assistant quick reference and startup guide
- AGENTS.md - AI development protocols, prompting guidelines, and best practices
- README.md - Project overview and user documentation
- NVM_SETUP.md - Node version management setup instructions
- Next.js: https://nextjs.org/docs
- React: https://react.dev/
- TypeScript: https://www.typescriptlang.org/docs/
- Tailwind CSS: https://tailwindcss.com/docs
- Shadcn/ui: https://ui.shadcn.com/
- NASA ADS / SciX API: https://scixplorer.org/help/api/
- Node Version Manager: https://github.com/nvm-sh/nvm
- GitHub Actions: https://docs.github.com/en/actions
- GitHub Pages: https://docs.github.com/en/pages
- Next.js Discord: https://nextjs.org/discord
- Tailwind Discord: https://tailwindcss.com/discord
- Shadcn/ui GitHub: https://github.com/shadcn/ui
Purpose: Track major changes and updates to this documentation
When to use this section: Understanding recent changes, tracking documentation evolution
- Updated research pages documentation to reflect migration from old system to figure registry architecture
- Removed references to deleted files:
research-projects.json,research-paragraphs.json,research-figures-with-captions.json,page-figure-mappings.json,figure-metadata.json,research-page.json - Removed references to deleted components:
research-figure.tsx,featured-research.tsx,research.tsx - Removed references to deleted scripts:
create_research_page.py,generate_figure_data.py,test_create_research_page.py - Removed
generate-figure-data.ymlworkflow documentation - Added documentation for new data sources:
research-topics/*.json,figure-registry.json - Added documentation for new route:
/research/figure/[paper_id]/[figure_id] - Added documentation for
research-topic.tsxcomponent andgenerate_figure_registry_from_corpus.pyscript
- Added documentation for CV integration (cross-repo GitHub Action, BibTeX generation from website JSON)
- Added
non_ads_publications.json,invited_conferences.json,invited_presentations.jsonto Data Management - Added
publication_statistics.json,invited_metrics.jsonto Automated Data Files - Added
add_non_ads_publication.pyscript documentation - Updated Directory Structure with missing data files, scripts, and
Alterman-CV.pdf - Updated Data Flow Architecture with non-ADS publications and CV integration flow
- Added "How to Use This Document" section with role-based reading paths
- Added visual separators (icons and horizontal rules) to all 18 major sections
- Added purpose blocks to all major sections explaining when to use each section
- Added "Jump to Top" navigation links throughout document (~15 locations)
- Created Architecture Quick Reference companion file for fast topic lookup
- Added navigation tips in CLAUDE.md for using ARCHITECTURE.md more effectively
- Improved document navigation and reduced cognitive load while keeping unified structure
- Added cross-references to AGENTS.md throughout document
- Added "AI Development" subsection in Best Practices
- Added "Project Documentation" section in Resources
- Updated header with related documentation links
- Improved documentation discoverability and navigation
- Initial architecture documentation created
- Comprehensive reference for developers and AI assistants
- Documented all workflows, scripts, and data structures
This project is open source. Research content and publications are subject to respective journal copyright policies.
For questions or issues, please open an issue on GitHub or contact the maintainer.