{"id":40818563,"url":"https://github.com/thepushkarp/etymology-explorer","last_synced_at":"2026-01-21T21:44:10.291Z","repository":{"id":331326573,"uuid":"1125008284","full_name":"thepushkarp/etymology-explorer","owner":"thepushkarp","description":"Discover the roots and origins of words","archived":false,"fork":false,"pushed_at":"2026-01-17T15:29:55.000Z","size":382,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-18T01:13:05.022Z","etag":null,"topics":["claude","english","english-language","english-learning","etymology","word-origin","words"],"latest_commit_sha":null,"homepage":"http://etymology.thepushkarp.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thepushkarp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"thepushkarp","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://www.buymeacoffee.com/thepushkarp"}},"created_at":"2025-12-30T02:03:24.000Z","updated_at":"2026-01-17T15:29:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thepushkarp/etymology-explorer","commit_stats":null,"previous_names":["thepushkarp/etymology-explorer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thepushkarp/etymology-explorer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thepushkarp%2Fetymology-explorer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thepushkarp%2Fetymology-explorer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thepushkarp%2Fetymology-explorer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thepushkarp%2Fetymology-explorer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thepushkarp","download_url":"https://codeload.github.com/thepushkarp/etymology-explorer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thepushkarp%2Fetymology-explorer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28644149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T21:29:11.980Z","status":"ssl_error","status_checked_at":"2026-01-21T21:24:31.872Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","english","english-language","english-learning","etymology","word-origin","words"],"created_at":"2026-01-21T21:44:09.672Z","updated_at":"2026-01-21T21:44:10.286Z","avatar_url":"https://github.com/thepushkarp.png","language":"TypeScript","funding_links":["https://ko-fi.com/thepushkarp","https://www.buymeacoffee.com/thepushkarp"],"categories":[],"sub_categories":[],"readme":"# Etymology Explorer\n\nA beautiful, interactive web app that helps you discover the origins and roots of words. Perfect for vocabulary enthusiasts who want to understand words deeply through their etymological roots.\n\nTry it out at [etymology.thepushkarp.com](https://etymology.thepushkarp.com)\n\n## Features\n\n- **Etymology Lookup**: Search any word to discover its linguistic origins, root morphemes, and historical evolution\n- **Memorable Lore**: Each word comes with a 4-6 sentence narrative that makes the etymology stick\n- **Related Words**: Discover words that share the same roots\n- **Multiple LLM Providers**: Choose between Anthropic (Claude) or OpenRouter for flexibility\n- **Dynamic Model Selection**: Automatically fetches available models from Anthropic API\n- **Search History**: Track your vocabulary exploration with a persistent sidebar\n- **Surprise Me**: Discover random words to expand your vocabulary\n- **Structured Outputs**: Guaranteed valid JSON responses using constrained decoding\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 18+\n- An API key from either:\n  - [Anthropic](https://console.anthropic.com/settings/keys) (recommended)\n  - [OpenRouter](https://openrouter.ai/keys)\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/thepushkarp/etymology-explorer.git\ncd etymology-explorer\n\n# Install dependencies\nyarn install\n\n# Start the development server\nyarn dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) in your browser.\n\n### Configuration\n\n1. Click the **Settings** button (bottom-right corner)\n2. Choose your LLM provider:\n\n#### Anthropic (Default)\n\n- Paste your Anthropic API key\n- Select a model from the dropdown (auto-populated from API)\n- Default: Claude Haiku 4.5 (fast and cost-effective)\n\n#### OpenRouter\n\n- Toggle to \"OpenRouter\"\n- Enter a model ID (e.g., `anthropic/claude-3.5-sonnet`, `openai/gpt-4o`)\n- Paste your OpenRouter API key\n\nYour settings are stored locally in your browser and never sent to any server.\n\n## Tech Stack\n\n- **Framework**: [Next.js 16.1](https://nextjs.org/) with App Router\n- **UI**: [React 19.2](https://react.dev/) + [Tailwind CSS v4](https://tailwindcss.com/)\n- **LLM**: [Anthropic SDK](https://docs.anthropic.com/) with structured outputs\n- **Data Sources**: [Etymonline](https://www.etymonline.com/) + [Wiktionary](https://en.wiktionary.org/)\n- **Typography**: Libre Baskerville (serif)\n\n## Project Structure\n\n```\netymology-explorer/\n├── app/\n│   ├── api/\n│   │   ├── etymology/     # Main etymology synthesis endpoint\n│   │   ├── models/        # Fetch available Anthropic models\n│   │   ├── random-word/   # Random word selection\n│   │   └── suggestions/   # Typo correction suggestions\n│   ├── layout.tsx         # Root layout with fonts\n│   └── page.tsx           # Main page with search UI\n├── components/\n│   ├── AncestryTree.tsx   # Visual etymology graph\n│   ├── EtymologyCard.tsx  # Main result display\n│   ├── HistorySidebar.tsx # Search history panel\n│   ├── RootChip.tsx       # Expandable root morpheme\n│   ├── SearchBar.tsx      # Word input\n│   ├── SettingsModal.tsx  # LLM configuration\n│   └── SurpriseButton.tsx # Random word button\n├── lib/\n│   ├── research.ts        # Agentic multi-source research pipeline\n│   ├── claude.ts          # LLM synthesis with structured outputs\n│   ├── etymonline.ts      # Etymonline scraper\n│   ├── wiktionary.ts      # Wiktionary API client\n│   ├── spellcheck.ts      # Typo detection and suggestions\n│   ├── prompts.ts         # System prompts and schemas\n│   ├── types.ts           # TypeScript interfaces\n│   └── hooks/             # React hooks (localStorage, history)\n└── data/\n    └── gre-words.json     # Vocabulary word list\n```\n\n## API Endpoints\n\n| Endpoint           | Method | Description                      |\n| ------------------ | ------ | -------------------------------- |\n| `/api/etymology`   | POST   | Synthesize etymology for a word  |\n| `/api/models`      | POST   | Fetch available Anthropic models |\n| `/api/suggestions` | GET    | Get typo correction suggestions  |\n| `/api/random-word` | GET    | Get a random word                |\n\n## How It Works\n\n1. **Agentic Research**: When you search a word, an agentic pipeline conducts multi-phase research:\n   - Phase 1: Fetch main word data from Etymonline and Wiktionary in parallel\n   - Phase 2: Quick LLM call extracts root morphemes (e.g., \"telephone\" → [\"tele\", \"phone\"])\n   - Phase 3: Fetch etymology data for each identified root\n   - Phase 4: Gather related terms for additional context (depth-limited)\n2. **LLM Synthesis**: The aggregated research context is sent to your chosen LLM with a structured output schema\n3. **Guaranteed JSON**: Using constrained decoding, the LLM produces valid JSON matching the exact schema\n4. **Rich Display**: The etymology is rendered with expandable roots, ancestry graph, and source attribution\n\n### Architecture Diagram\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              BROWSER (Client)                               │\n│  ┌─────────────┐  ┌──────────────┐  ┌─────────────┐  ┌─────────────────┐   │\n│  │  SearchBar  │  │SettingsModal │  │HistorySidebar│  │  EtymologyCard  │   │\n│  └──────┬──────┘  └──────┬───────┘  └──────┬──────┘  └────────┬────────┘   │\n│         │                │                 │                   │            │\n│         │         localStorage             │                   │            │\n│         │      (API keys, history)         │                   │            │\n│         └────────────────┬─────────────────┴───────────────────┘            │\n└──────────────────────────┼──────────────────────────────────────────────────┘\n                           │ POST /api/etymology\n                           ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                           NEXT.JS SERVER                                    │\n│                                                                             │\n│  ┌───────────────────────────────────────────────────────────────────────┐  │\n│  │                    AGENTIC RESEARCH PIPELINE                          │  │\n│  │                                                                       │  │\n│  │   Phase 1                    Phase 2                 Phase 3-4        │  │\n│  │  ┌──────────┐               ┌───────┐              ┌──────────────┐   │  │\n│  │  │Etymonline│──┐            │Quick  │              │ Root + Related│   │  │\n│  │  │ Scraper  │  ├──────────▶ │LLM    │ ──────────▶  │ Term Fetches │   │  │\n│  │  └──────────┘  │  parallel  │Call   │  roots[]     │ (max 10)     │   │  │\n│  │  ┌──────────┐  │            └───────┘              └──────────────┘   │  │\n│  │  │Wiktionary│──┘                                                      │  │\n│  │  │  API     │                                                         │  │\n│  │  └──────────┘                                                         │  │\n│  └─────────────────────────────────────┬─────────────────────────────────┘  │\n│                                        │                                    │\n│                                        ▼ ResearchContext                    │\n│  ┌───────────────────────────────────────────────────────────────────────┐  │\n│  │                       LLM SYNTHESIS                                   │  │\n│  │                                                                       │  │\n│  │   ┌─────────────┐      ┌────────────────┐      ┌──────────────────┐   │  │\n│  │   │  Anthropic  │  OR  │   OpenRouter   │  ──▶ │ Structured JSON  │   │  │\n│  │   │    SDK      │      │     API        │      │ (EtymologyResult)│   │  │\n│  │   └─────────────┘      └────────────────┘      └──────────────────┘   │  │\n│  └───────────────────────────────────────────────────────────────────────┘  │\n└─────────────────────────────────────────────────────────────────────────────┘\n                           │\n                           ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                          EXTERNAL SERVICES                                  │\n│                                                                             │\n│   ┌────────────────┐  ┌────────────────┐  ┌────────────────────────────┐    │\n│   │  etymonline.com│  │ en.wiktionary  │  │  Anthropic / OpenRouter    │    │\n│   │  (HTML scrape) │  │ (MediaWiki API)│  │  (LLM with JSON schema)    │    │\n│   └────────────────┘  └────────────────┘  └────────────────────────────┘    │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n## Development\n\n```bash\n# Run development server\nyarn dev\n\n# Lint code\nyarn lint\n\n# Format code\nyarn format\n\n# Build for production\nyarn build\n```\n\n## Deployment\n\nDeploy easily on [Vercel](https://vercel.com):\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/thepushkarp/etymology-explorer)\n\n## License\n\nMIT\n\n## Acknowledgments\n\n- Etymology data from [Etymonline](https://www.etymonline.com/) and [Wiktionary](https://en.wiktionary.org/)\n- Powered by [Claude](https://www.anthropic.com/claude) from Anthropic\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthepushkarp%2Fetymology-explorer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthepushkarp%2Fetymology-explorer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthepushkarp%2Fetymology-explorer/lists"}