This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Explorar.dev is a Next.js 16 application for exploring and learning from arbitrary software source code with an interactive VS Code-like interface. It supports both curated repositories (pre-downloaded at build time) and arbitrary GitHub repositories (downloaded on-demand).
Key Architecture Decisions:
- Frontend: Static Next.js export with no server-side rendering
- No Backend: Pure frontend application, no authentication or user data collection
- Repository Modes:
- Curated Mode: Static repositories downloaded at build time, served from
/public/repos/ - Arbitrary Mode: User-selected GitHub repositories downloaded on-demand to IndexedDB
- Curated Mode: Static repositories downloaded at build time, served from
npm run dev # Start dev server (port 3000)Environment Variable Configuration:
.env.developmentβ Development defaults - loaded whenNODE_ENV=development.env.productionβ Production defaults - loaded whenNODE_ENV=production.env.localβ Personal overrides (gitignored) - HIGHEST PRIORITY, overrides both abovenpm run devautomatically uses.env.development(Next.js setsNODE_ENV=development)npm run buildautomatically uses.env.production(Next.js setsNODE_ENV=production)
# Development
npm run dev # Start dev server with Turbopack (runs predev script first)
npm run predev # Downloads Python/CPython repo for local testing
# Building & Deployment
npm run build # Build static export (runs prebuild script)
npm run prebuild # Downloads repositories based on --depth flag
npm run clean # Remove all generated artifacts
# Code Quality
npm run lint # Full gate: guide validation β tsc β eslint (cached) β prettier check β depcheck
npm run fix # Auto-fix: eslint --fix + prettier write + npm audit fix + tsc verify
# NOTE: fix is best-effort. Always run lint afterward to confirm clean state.
# Pre-commit hook runs lint-staged (eslint + prettier) on changed files automatically.
# Testing
npm test # Run all Playwright tests
npm run test:sanity # Basic functionality tests
npm run test:performance # Core Web Vitals tests
npm run test:seo # SEO validation
npm run test:quality # Accessibility checks (axe-core)
npm run test:score # Quality score calculation
npm run test:ui # Interactive test UI
npm run test:report # View HTML test report
# Testing Notes
# - Tests require the static build: npm run build
# - Tests automatically start an http.server on port 8000
# - Configure test target with: BASE_URL=http://localhost:3000 npm testUser β Route ([owner]/[repo]) β KernelExplorer (Main Container)
β
RepositoryContext (State Management)
β
ββββββ΄βββββ¬ββββββββββββββ¬βββββββββββββ
β β β β
FileTree CodeEditor GuidePanel DataStructuresView
β β β β
API Layer (github-api.ts)
β
βββ΄ββββββββββββββββββββββββββββββ
β β
Static (repo-static.ts) Dynamic (github-archive.ts)
β β
/public/repos/* IndexedDB (repo-storage.ts)
(Curated) (Downloaded)
UI Layer (src/components/):
KernelExplorer.tsx: Main container orchestrating all UI elementsFileTree.tsx: Hierarchical file navigationCodeEditorContainer.tsx: Tab management for open filesMonacoCodeEditor.tsx: Monaco editor wrapper with syntax highlightingGuidePanel.tsx: Learning guides with markdown parsingDataStructuresView.tsx: API/data structure browserActivityBar.tsx: Navigation sidebar (files, guides, data structures)TabBar.tsx: Open file tabsStatusBar.tsx: Bottom status informationGitHubRateLimitWrapper.tsx: Rate limit warnings
State Management (src/contexts/):
RepositoryContext.tsx: Repository selection, branch management, download stateGitHubRateLimitContext.tsx: Rate limit tracking
Storage & Data Layer (src/lib/):
repo-storage.ts: IndexedDB wrapper - primary storage for downloaded reposgithub-archive.ts: GitHub API integration - downloads tree structure, lazy-loads filesrepo-static.ts: Static file reader - serves pre-built curated reposgithub-api.ts: File fetching, tree building, API dispatch (routes to static or dynamic)github-cache.ts: Caching layer with exponential backoffgithub-retry.ts: Retry logic and circuit breaker pattern
Build & Platform (src/lib/):
project-guides.tsx: Configuration for curated repos (paths, guides)monaco-workers.ts: Monaco editor web worker setupmonaco-config.ts: Editor theme and language configurationplatform/: Platform abstraction (web vs. other environments)
Curated (Static):
- Repositories pre-downloaded at build time via
scripts/download-repos.ts - Files live in
/public/repos/[owner]/[repo]/[branch]/ - Configuration in
src/lib/project-guides.tsx - No API calls needed after build
- Full offline support
- Examples: Python/CPython, Linux Kernel, LLVM, glibc
Arbitrary (Dynamic):
- User enters any GitHub repository URL
- Tree structure downloaded to IndexedDB via
github-archive.ts - File contents lazy-loaded on-demand
- Requires GitHub API access (unauthenticated)
- Rate limits apply (60 req/hr)
- Uses retry logic with exponential backoff
IndexedDB (repo-storage.ts):
files: Cached file contentsmetadata: Repository metadata (branches, sizes)directories: Directory listings for lazy loadingtreeStructure: Complete tree structure for a branch- Version: 4 (auto-migrates on schema changes)
- Stores both curated and arbitrary repos for offline access
localStorage:
- Open tabs (EditorTab[])
- Scroll positions per file
- UI state (expanded folders, active panel)
Files aren't pre-downloaded. Only the tree structure is fetched. Files load when user opens them or navigates directories. This keeps memory/storage usage low.
hasTreeStructure(): Check if tree is cacheddownloadDirectoryContents(): Download directory's immediate children onlyfetchFileContent(): Fetch single file on-demand
github-api.ts dispatches calls to either static or dynamic sources:
// buildFileTree() checks isCuratedRepo() first
// If curated: calls getTreeStructureFromStatic()
// If arbitrary: calls downloadBranch() β IndexedDBDuring bulk downloads, metadata updates are debounced (1000ms) to prevent IndexedDB transaction conflicts. See metadataUpdateQueue in repo-storage.ts.
Markdown guides for curated repos are loaded via guide-loader.tsx which parses frontmatter (YAML) and markdown to create chapter-based learning paths.
- Update
src/lib/project-guides.tsxwith repo config - Add download script or manually place files in
public/repos/[owner]/[repo]/[branch]/ - Add markdown guides in
src/lib/guides/[repo-name].md - Build:
npm run build
Check which source is being used:
import { getRepositoryMode } from '@/lib/repo-static';
const mode = getRepositoryMode(owner, repo); // 'curated' or 'arbitrary'In browser DevTools:
- Application β IndexedDB β explorar-repo-storage
- Check
files,metadata,treeStructurestores
- Unauthenticated: 60 requests/hour
- Rate limit is tracked via
GitHubRateLimitContext - When exceeded,
RateLimitScreen.tsxis shown
For routing/UI changes:
npm run dev
# Open http://localhost:3000/python/cpythonFor build/static export changes:
npm run build
npm run test:sanity- Strict mode enabled in
tsconfig.json - All components are
'use client'(client-side rendering) - Frontend types:
src/types/index.ts(FileNode, EditorTab, GitHubApiResponse) - Path aliases:
@/*βsrc/*(frontend code)
- Static export to
out/directory - No server-side rendering (SSR)
- Works with any static host (Netlify, Vercel, S3, etc.)
- Curated repos must be in
out/repos/after build
NEXT_PUBLIC_SITE_URL: Site URL for metadata (default:https://explorar.dev)NEXT_PUBLIC_GUIDES_API_URL: API URL for AI-generated guides (optional)NEXT_PUBLIC_GUIDES_API_KEY: API key for guides service (optional)
| File | Purpose |
|---|---|
src/app/[owner]/[repo]/page.tsx |
Dynamic route renderer |
src/components/KernelExplorer.tsx |
Main UI orchestrator |
src/contexts/RepositoryContext.tsx |
State management |
src/lib/github-api.ts |
API dispatch & tree building |
src/lib/github-archive.ts |
GitHub download logic |
src/lib/repo-storage.ts |
IndexedDB interface |
src/lib/repo-static.ts |
Static file serving |
src/lib/project-guides.tsx |
Curated repo config |
next.config.ts |
Build config (static export, Monaco setup) |
playwright.config.ts |
Test configuration |
CLAUDE.md |
Project documentation (this file) |