{"id":20080077,"url":"https://github.com/garyo/travel-time-applet","last_synced_at":"2026-03-03T22:32:27.976Z","repository":{"id":259975965,"uuid":"879959596","full_name":"garyo/travel-time-applet","owner":"garyo","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-13T17:05:51.000Z","size":191,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-12T01:36:08.058Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garyo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2024-10-28T21:23:25.000Z","updated_at":"2025-09-13T17:05:55.000Z","dependencies_parsed_at":"2024-10-28T22:37:29.219Z","dependency_job_id":null,"html_url":"https://github.com/garyo/travel-time-applet","commit_stats":null,"previous_names":["garyo/travel-time-applet"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/garyo/travel-time-applet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyo%2Ftravel-time-applet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyo%2Ftravel-time-applet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyo%2Ftravel-time-applet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyo%2Ftravel-time-applet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garyo","download_url":"https://codeload.github.com/garyo/travel-time-applet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyo%2Ftravel-time-applet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30064329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T18:21:05.932Z","status":"ssl_error","status_checked_at":"2026-03-03T18:20:59.341Z","response_time":61,"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":[],"created_at":"2024-11-13T15:25:57.551Z","updated_at":"2026-03-03T22:32:27.930Z","avatar_url":"https://github.com/garyo.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Travel Time Applet\n\nA full-stack travel time calculator that provides MBTA transit times and driving directions between locations in the Boston area.\n\n## Features\n\n- 🚇 **MBTA Transit Times**: Real-time predictions for subway/bus routes\n- 🚗 **Driving Directions**: Google Maps driving time and distance\n- 🚶 **Walking Times**: Walking time to nearest transit stations\n- ⚡ **Caching**: Intelligent caching for improved performance\n- 🔒 **Security**: Input validation, rate limiting, XSS prevention\n- 📱 **Responsive**: Clean, mobile-friendly interface\n\n## Quick Start\n\n```bash\n# Install dependencies\nbun install\n\n# Start local development (worker + HTML server)\nbun run start-local\n\n# Open http://localhost:3000 in your browser\n```\n\n## Development\n\n### Commands\n\n```bash\n# Backend development\nbun run dev                # Start Cloudflare Worker dev server (port 8787)\n\n# Frontend + Backend development\nbun run start-local        # Start both worker and HTML dev server\n                          # Worker: localhost:8787, HTML: localhost:3000\n\n# Testing\nbun run test:api           # Test APIs against local worker\nbun run test:api:prod      # Test APIs against production\n\n# Deployment\nbun run deploy            # Deploy worker to Cloudflare\n```\n\n### Development Workflow\n\n1. **Local Development**:\n   ```bash\n   bun run start-local     # Starts everything\n   ```\n   - Worker runs on `localhost:8787`\n   - HTML dev server on `localhost:3000` (with automatic API URL rewriting)\n   - Make changes to `travel-time-worker/worker.js`\n   - Refresh browser to see changes\n\n2. **API Testing**:\n   ```bash\n   bun run test:api        # Comprehensive API test suite\n   ```\n\n3. **Deploy**:\n   ```bash\n   bun run deploy         # Ship to production\n   ```\n\n## Project Structure\n\n```\ntravel-time-applet/\n├── package.json              # Root package with workspace management\n├── README.md                 # This file\n├── public/\n│   └── index.html           # Frontend HTML application\n└── travel-time-worker/      # Cloudflare Worker backend\n    ├── package.json         # Worker-specific dependencies\n    ├── worker.js           # Main worker code\n    ├── wrangler.toml       # Cloudflare configuration\n    ├── scripts/            # Development and testing scripts\n    └── README.md           # Worker-specific documentation\n```\n\n## Architecture\n\n- **Frontend**: Static HTML with vanilla JavaScript\n- **Backend**: Cloudflare Worker (serverless)\n- **APIs**: MBTA API, Google Maps API\n- **Deployment**: Cloudflare Workers platform\n- **Local Development**: Wrangler dev server + custom HTML proxy\n\n## API Endpoints\n\n- `GET /mbta?origin={address}\u0026destination={address}` - MBTA transit times\n- `GET /driving?origin={address}\u0026destination={address}` - Driving directions\n\n## Testing\n\nComprehensive test suite with:\n- ✅ Valid API requests (MBTA \u0026 driving)\n- ✅ Input validation and error handling\n- ✅ Security (XSS prevention, rate limiting)\n- ✅ Performance monitoring\n- ✅ Cache functionality\n\n```bash\n# Run all API tests\nbun run test:api\n\n# Test specific implementations\nbun run test:api:local:fetch  # Fetch-based tests\nbun run test:api:local:curl   # cURL-based tests\nbun run test:api:prod         # Production tests\n```\n\n## Configuration\n\n### Required Environment Variables\n\nCreate `travel-time-worker/.dev.vars`:\n```bash\nGOOGLE_API_KEY=your_google_maps_api_key_here\n```\n\n### Google Maps API Setup\n\n1. Get API key from [Google Cloud Console](https://console.cloud.google.com/)\n2. Enable these APIs:\n   - Maps JavaScript API\n   - Directions API\n   - Distance Matrix API\n3. Set up billing (required for production usage)\n\n## Security Features\n\n- **Input Validation**: Address format validation with security patterns\n- **Rate Limiting**: 60 requests/minute per IP\n- **XSS Prevention**: Input sanitization and content security\n- **API Key Protection**: Server-side only, never exposed to client\n- **CORS**: Configured for secure cross-origin requests\n\n## Performance\n\n- **Intelligent Caching**: 4-minute TTL for API responses\n- **Request Deduplication**: Prevents duplicate concurrent requests\n- **Cloudflare Edge**: Global CDN with minimal latency\n- **Lightweight**: Vanilla JS frontend, no framework overhead\n\n## License\n\nMIT - see [LICENSE](LICENSE) file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryo%2Ftravel-time-applet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaryo%2Ftravel-time-applet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryo%2Ftravel-time-applet/lists"}