{"id":44456581,"url":"https://github.com/animyrch/pure-reactions","last_synced_at":"2026-02-12T17:36:55.388Z","repository":{"id":333751560,"uuid":"698962327","full_name":"animyrch/pure-reactions","owner":"animyrch","description":"Reaction video platform with open source code","archived":false,"fork":false,"pushed_at":"2026-02-03T22:32:41.000Z","size":2072,"stargazers_count":1,"open_issues_count":19,"forks_count":1,"subscribers_count":1,"default_branch":"prod","last_synced_at":"2026-02-04T08:47:22.854Z","etag":null,"topics":["creator-tools","mediaplayer","social-media","video-editing","video-player","video-streaming"],"latest_commit_sha":null,"homepage":"https://purereactions.com","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/animyrch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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":"2023-10-01T14:14:39.000Z","updated_at":"2026-02-01T02:33:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/animyrch/pure-reactions","commit_stats":null,"previous_names":["animyrch/pure-reactions"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/animyrch/pure-reactions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/animyrch%2Fpure-reactions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/animyrch%2Fpure-reactions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/animyrch%2Fpure-reactions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/animyrch%2Fpure-reactions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/animyrch","download_url":"https://codeload.github.com/animyrch/pure-reactions/tar.gz/refs/heads/prod","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/animyrch%2Fpure-reactions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29374182,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"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":["creator-tools","mediaplayer","social-media","video-editing","video-player","video-streaming"],"created_at":"2026-02-12T17:36:55.297Z","updated_at":"2026-02-12T17:36:55.373Z","avatar_url":"https://github.com/animyrch.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pure Reactions\n\nA platform for creating and sharing authentic reaction videos with synchronized playback.\n\n## Features\n\n- Record video reactions synchronized with original content\n- Twin player system with synchronized playback\n- Shared viewing sessions for real-time co-watching\n- Search and discover reactions\n- Progressive Web App (PWA) support\n- Dark mode with cinematic design\n\n## Getting Started\n\n### Prerequisites\n\n- **Node.js 20+** (see `.nvmrc`) - If you use `nvm`: `nvm install \u0026\u0026 nvm use`\n- Firebase account for backend services\n- Algolia account for search functionality\n- YouTube Data API key\n\n### Installation\n\n1. Clone the repository:\n   ```bash\n   git clone https://github.com/animyrch/pure-reactions.git\n   cd pure-reactions\n   ```\n\n2. Install dependencies:\n   ```bash\n   npm install\n   ```\n\n3. Set up environment variables:\n   ```bash\n   cp .env.example .env\n   ```\n   \n   Edit `.env` and fill in your configuration:\n   - Firebase configuration (collections, emulator settings)\n   - Algolia credentials (app ID, search API key, index name)\n   - YouTube API key\n\n4. Set up Firebase Admin SDK:\n   - Go to [Firebase Console](https://console.firebase.google.com/)\n   - Navigate to Project Settings → Service Accounts\n   - Click \"Generate New Private Key\"\n   - Save the JSON file in the root directory as `pure-reactions-firebase-adminsdk-[key-id].json`\n   - Set the path in your environment:\n     ```bash\n     export FIREBASE_SERVICE_ACCOUNT=\"./pure-reactions-firebase-adminsdk-[key-id].json\"\n     ```\n   - **Never commit this file to git** (it's automatically ignored)\n\n5. Start the development server:\n   ```bash\n   npm run dev\n   ```\n\n   The app will be available at `http://localhost:5173`\n\n## Development\n\n### Available Scripts\n\n- `npm run dev` - Start development server\n- `npm run build` - Build for production\n- `npm run preview` - Preview production build\n- `npm run lint` - Run ESLint\n- `npm run e2e` - Run end-to-end tests with Playwright\n\n### Database Scripts\n\nBefore running these scripts, ensure `FIREBASE_SERVICE_ACCOUNT` is set:\n\n- `npm run seed:firestore` - Seed Firestore with test data\n- `npm run seed:twin-fixtures` - Seed twin player test fixtures\n- `npm run migrate:delete-legacy-timelines` - Clean up legacy timeline data\n\n### Database Scripts\n\nBefore running these scripts, ensure `FIREBASE_SERVICE_ACCOUNT` is set:\n\n- `npm run seed:firestore` - Seed Firestore with test data\n- `npm run seed:twin-fixtures` - Seed twin player test fixtures\n- `npm run migrate:delete-legacy-timelines` - Clean up legacy timeline data\n\n### Algolia Search Scripts\n\nManage search indices and configuration:\n\n- `npm run algolia:status` - Check Algolia app and index status\n- `npm run algolia:index` - Dry-run index sync from Firestore (safe, no changes)\n- `npm run algolia:index:apply` - Apply index sync to Algolia\n\nSee [docs/ALGOLIA_OPERATIONS.md](docs/ALGOLIA_OPERATIONS.md) for detailed search operations guide.\n\n### Sitemap Generation\n\nGenerate and commit the static sitemap (`static/sitemap.xml`) from Firestore:\n\n```bash\nexport FIREBASE_SERVICE_ACCOUNT=\"./path/to/serviceAccount.json\"\nexport PUBLIC_BASE_URL=\"https://yourdomain.com\"\nnpm run generate-sitemap\n```\n\nThe script reads published reactions and uses stored `youtube.meta` fields (no YouTube API calls during generation).\n\n## Architecture\n\n### Core Technologies\n\n- **SvelteKit** - Application framework\n- **Firebase** - Authentication, Firestore, and Realtime Database\n- **Algolia** - Search functionality\n- **YouTube IFrame API** - Video playback\n- **Tailwind CSS** - Styling with cinematic design tokens\n- **Playwright** - End-to-end testing\n\n### Key Features\n\n- **Twin Player System**: Synchronized playback of original and reaction videos with timeline-based control\n- **Shared Sessions**: Real-time co-watching using Firebase Realtime Database\n- **Reaction Recording**: Backend flow for creating reaction videos with state tracking\n- **Search**: Provider-agnostic search with Algolia backend, optimized for cost and easy migration\n\n## Code Organization Guidelines\n\n1. **Keep files focused** — prefer small, single-responsibility modules. Composables should orchestrate state, lifecycle hooks, and side effects while remaining thin.\n2. **Extract pure helpers** — deterministic logic (e.g., rounding, map/array transforms, timeline normalization) belongs in `src/lib/helpers/` so it can be reused and tested independently.\n3. **Name by role** — use folders like `helpers`, `composables`, `components` to signal intent and import behavior: helpers for stateless utilities, composables for orchestrators, components for UI.\n4. **Document rationale** — when you split logic (like `useTwinPlayers` + `twinPlayersTimeline`), add a short comment or README entry explaining where related helpers live so future edits are easy to reason about.\n\n## Security\n\n- See [SECURITY.md](SECURITY.md) for security policies and vulnerability reporting\n- **Never commit credentials**: All sensitive keys should be in `.env` (which is gitignored)\n- Firebase client API keys in source code are safe (they identify your project, not authenticate)\n- Firebase Admin SDK credentials must always be kept secure and never committed\n\n## Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## Testing\n\n### End-to-End Tests\n\nRun Playwright tests:\n```bash\nnpm run e2e\n```\n\nSee [TEST_FEATURES.md](TEST_FEATURES.md) for supported query params and test/debug toggles.\n\n### Browser Testing Reference\n\nKey test fixtures for twin-player synchronization are in `tests/fixtures/reactions/`:\n- Basic Sync: `/reaction/1PaTrdCMKn6ay7nShHES`\n- Play Trigger: `/reaction/8O1sPJr6atB0K2CvyItV`\n- Volume Stability: `/reaction/Dw3UZ6PqZH37E5pbKmhZ`\n- Resume After Config Pause: `/reaction/BUOR5TM6yAHSClCCRvIp`\n\n## Deployment\n\nThis project is configured for Netlify deployment (see `netlify.toml` and `svelte.config.js`).\n\n### Environment Variables for Production\n\nEnsure these are set in your Netlify dashboard:\n- All `PUBLIC_*` variables from `.env.example`\n- `YOUTUBE_API_KEY` (server-side only)\n- Firebase Admin SDK credentials (if needed for server functions)\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## Test \u0026 Debug Features\n\nSee [TEST_FEATURES.md](TEST_FEATURES.md) for supported query params and test/debug toggles.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanimyrch%2Fpure-reactions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanimyrch%2Fpure-reactions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanimyrch%2Fpure-reactions/lists"}