{"id":37408106,"url":"https://github.com/chrisvogt/metrics","last_synced_at":"2026-01-16T05:52:36.164Z","repository":{"id":37697409,"uuid":"190331097","full_name":"chrisvogt/metrics","owner":"chrisvogt","description":"Syncs data from services like Spotify and Goodreads into Firestore for my personal site.","archived":false,"fork":false,"pushed_at":"2025-11-08T05:52:17.000Z","size":947,"stargazers_count":4,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-08T07:13:35.200Z","etag":null,"topics":["personal-api"],"latest_commit_sha":null,"homepage":"https://metrics.chrisvogt.me/","language":"JavaScript","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/chrisvogt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2019-06-05T05:25:59.000Z","updated_at":"2025-11-08T05:52:40.000Z","dependencies_parsed_at":"2024-09-15T09:57:14.768Z","dependency_job_id":"34b6aea0-b801-45b2-b0ca-4e1a27980d78","html_url":"https://github.com/chrisvogt/metrics","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/chrisvogt/metrics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisvogt%2Fmetrics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisvogt%2Fmetrics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisvogt%2Fmetrics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisvogt%2Fmetrics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisvogt","download_url":"https://codeload.github.com/chrisvogt/metrics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisvogt%2Fmetrics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28477468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T03:13:13.607Z","status":"ssl_error","status_checked_at":"2026-01-16T03:11:47.863Z","response_time":107,"last_error":"SSL_read: 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":["personal-api"],"created_at":"2026-01-16T05:52:35.468Z","updated_at":"2026-01-16T05:52:36.156Z","avatar_url":"https://github.com/chrisvogt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Social Metrics API\n\n\u003ch1 align='center'\u003e\n  Social Metrics API (\u003ca href='https://metrics.chrisvogt.me' title='metrics.chrisvogt.me'\u003emetrics.chrisvogt.me\u003c/a\u003e)\n\u003c/h1\u003e\n\n\u003cp align='center'\u003e\n  \u003ca href='https://github.com/chrisvogt/metrics/actions/workflows/ci.yml'\u003e\n    \u003cimg src='https://github.com/chrisvogt/metrics/actions/workflows/ci.yml/badge.svg?branch=main' alt='Continuous Integration badge' /\u003e\n  \u003c/a\u003e\n  \u003ca href='https://github.com/chrisvogt/metrics/actions/workflows/codeql.yml'\u003e\n    \u003cimg src='https://github.com/chrisvogt/metrics/actions/workflows/codeql.yml/badge.svg?branch=main' alt='CodeQL badge' /\u003e\n  \u003c/a\u003e\n  \u003ca href='https://codecov.io/gh/chrisvogt/metrics'\u003e\n    \u003cimg src='https://codecov.io/gh/chrisvogt/metrics/branch/main/graph/badge.svg?token=Hr0GpQiCu0' alt='Code coverage report badge.' /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nThis repository contains a Firebase-backed service I use to fetch and sync data for widgets on my personal website, [www.chrisvogt.me](https://www.chrisvogt.me).\n\n## Features\n\n- **Multi-Platform Data Sync**: Integrates with Spotify, Steam, Goodreads, Instagram, Discogs, and Flickr\n- **Firebase Authentication**: Secure user authentication with email/password, phone, and Google sign-in\n- **Session Management**: Secure session cookies with JWT token fallback\n- **Real-time Data**: Live data fetching and caching for widget content\n- **Local Development**: Full Firebase emulator support for development\n\n## How To Install\n\n### Prerequisites\n\n- Node.js (version specified in [.nvmrc](./.nvmrc))\n- Firebase CLI\n- Access to a Firebase project\n\n### Setup Steps\n\n1. **Clone the repository**\n   ```bash\n   git clone git@github.com:chrisvogt/metrics.git\n   cd metrics\n   ```\n\n2. **Install Firebase CLI and authenticate**\n   ```bash\n   npm install -g firebase-tools\n   firebase login\n   ```\n\n3. **Install dependencies**\n   ```bash\n   cd functions\n   npm install\n   ```\n\n4. **Set up environment variables**\n   ```bash\n   # Copy the template file\n   cp env.template .env\n   \n   # Edit .env with your actual values\n   # See Environment Variables section below\n   ```\n\n5. **Download Firebase configuration**\n   ```bash\n   # Download runtime config (includes secrets for sync jobs)\n   firebase functions:config:get \u003e .runtimeconfig.json\n   ```\n\n### Environment Variables\n\nFor local development, you'll need to set up environment variables. Copy the template file and fill in your values:\n\n```bash\n# In the /functions directory\ncp env.template .env\n# Edit .env with your actual Firebase configuration\n```\n\n**Important:** Never commit the `.env` file to version control. It contains sensitive information like API keys.\n\n#### Required Environment Variables\n\nThe following variables are required for the authentication system to work:\n\n- `CLIENT_API_KEY` - Your Firebase API key\n- `CLIENT_AUTH_DOMAIN` - Your Firebase auth domain (e.g., `your-project.firebaseapp.com`)\n- `CLIENT_PROJECT_ID` - Your Firebase project ID\n\n#### Optional Environment Variables\n\n- `NODE_ENV` - Set to `development` for local development\n- `GEMINI_API_KEY` - For AI-powered summaries (if using Gemini integration)\n\n### Firebase Configuration\n\nThe Firebase configuration is now served dynamically from the backend to prevent hardcoding sensitive values in the client. You can set these values using either method:\n\n#### Option 1: Local .env file (for development)\nSet these environment variables in your `functions/.env` file:\n\n- `CLIENT_API_KEY` - Your Firebase API key\n- `CLIENT_AUTH_DOMAIN` - Your Firebase auth domain\n- `CLIENT_PROJECT_ID` - Your Firebase project ID\n\n#### Option 2: Firebase Runtime Config (recommended for production)\nUse Firebase's runtime configuration system:\n\n```bash\nfirebase functions:config:set auth.client_api_key=\"your_api_key\"\nfirebase functions:config:set auth.client_auth_domain=\"your_project_id.firebaseapp.com\"\nfirebase functions:config:set auth.client_project_id=\"your_project_id\"\n```\n\nThen download the config: `firebase functions:config:get \u003e .runtimeconfig.json`\n\n## Development\n\n### Starting the Local Development Server\n\n```bash\n# Start Firebase emulators (Auth, Firestore, Functions, Hosting)\nfirebase emulators:start\n\n# Or start just the functions emulator\ncd functions\nnpm run serve\n```\n\nThe emulators will be available at:\n- **Emulator UI**: http://127.0.0.1:4000/\n- **Hosting**: http://127.0.0.1:8084\n- **Functions**: http://127.0.0.1:5001\n- **Auth**: http://127.0.0.1:9099\n- **Firestore**: http://127.0.0.1:8080\n\n### Authentication System\n\nThe application includes a comprehensive authentication system with:\n\n- **Email/Password Login**: Traditional email and password authentication\n- **Phone Authentication**: SMS-based verification with Firebase Phone Auth\n- **Google Sign-In**: OAuth authentication with Google accounts\n- **Session Management**: Secure HTTP-only cookies with JWT fallback\n- **Multi-tenant Support**: Ready for future multi-user expansion\n\n### API Endpoints\n\nThe following endpoints are available:\n\n| Widget | Description | Auth Required |\n|--------|-------------|---------------|\n| `/api/widgets/spotify` | GET Spotify widget content | No |\n| `/api/widgets/sync/spotify` | Trigger Spotify data sync | Yes |\n| `/api/widgets/steam` | GET Steam widget content | No |\n| `/api/widgets/sync/steam` | Trigger Steam data sync | Yes |\n| `/api/widgets/goodreads` | GET Goodreads widget content | No |\n| `/api/widgets/sync/goodreads` | Trigger Goodreads data sync | Yes |\n| `/api/widgets/instagram` | GET Instagram widget content | No |\n| `/api/widgets/sync/instagram` | Trigger Instagram data sync | Yes |\n| `/api/widgets/discogs` | GET Discogs widget content | No |\n| `/api/widgets/sync/discogs` | Trigger Discogs data sync | Yes |\n| `/api/widgets/flickr` | GET Flickr widget content | No |\n| `/api/widgets/sync/flickr` | Trigger Flickr data sync | Yes |\n\n### Authentication Endpoints\n\n- `/api/auth/session` - Create session cookies (POST)\n- `/api/firebase-config` - Get Firebase client configuration (GET)\n\n## Architecture\n\n### Frontend\n- **HTML/CSS/JavaScript**: Modern, responsive UI with authentication tabs\n- **Firebase SDK**: Client-side authentication and real-time updates\n- **Session Management**: Secure cookie-based sessions with fallback\n\n### Backend\n- **Firebase Functions**: Serverless backend with Express.js\n- **Firebase Auth**: User authentication and session management\n- **Firestore**: Data storage and caching\n- **External APIs**: Integration with various platform APIs\n\n### Security Features\n- **CORS Protection**: Configurable cross-origin resource sharing\n- **Rate Limiting**: Built-in request throttling\n- **Session Validation**: Secure session cookie validation\n- **Environment Isolation**: Separate configs for development/production\n\n## Testing\n\n```bash\n# Run all tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run tests with coverage\nnpm run test:coverage\n```\n\n## Deployment\n\n```bash\n# Deploy to Firebase\nfirebase deploy\n\n# Deploy only functions\nfirebase deploy --only functions\n\n# Deploy only hosting\nfirebase deploy --only hosting\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## Copyright \u0026 License\n\nCopyright © 2020-2025 [Chris Vogt](https://www.chrisvogt.me). Released under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisvogt%2Fmetrics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisvogt%2Fmetrics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisvogt%2Fmetrics/lists"}