{"id":51069515,"url":"https://github.com/raphaelchpprt/signal-newsletter","last_synced_at":"2026-06-23T09:32:05.070Z","repository":{"id":345810708,"uuid":"1187368489","full_name":"raphaelchpprt/signal-newsletter","owner":"raphaelchpprt","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-08T06:40:33.000Z","size":1431,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-08T08:34:57.072Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/raphaelchpprt.png","metadata":{"files":{"readme":"README.md","changelog":"history.json","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}},"created_at":"2026-03-20T16:40:10.000Z","updated_at":"2026-05-08T06:40:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/raphaelchpprt/signal-newsletter","commit_stats":null,"previous_names":["raphaelchpprt/signal-newsletter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/raphaelchpprt/signal-newsletter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelchpprt%2Fsignal-newsletter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelchpprt%2Fsignal-newsletter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelchpprt%2Fsignal-newsletter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelchpprt%2Fsignal-newsletter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raphaelchpprt","download_url":"https://codeload.github.com/raphaelchpprt/signal-newsletter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelchpprt%2Fsignal-newsletter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34684673,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":"2026-06-23T09:32:04.948Z","updated_at":"2026-06-23T09:32:05.058Z","avatar_url":"https://github.com/raphaelchpprt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# signal-newsletter\n\n\u003e Automated personal tech digest — generated by Claude Sonnet with live web search, delivered every Friday morning via Resend.\n\nBuilt on GitHub Actions + Anthropic API + Resend. Zero infrastructure, ~$0.50–1.00 per run.\n\n---\n\n## How it works\n\nEvery Friday at 07:00 CET, a GitHub Actions workflow:\n\n1. Calls Claude Sonnet with the `web_search` tool to research the past 7 days\n2. Generates a structured JSON newsletter with 5 curated items\n3. Verifies image URLs via HEAD requests before rendering\n4. Builds a dark-mode HTML email with per-category accent colors\n5. Ships it via Resend\n6. Commits `history.json` to the repo — used next week to avoid repeating topics\n\nOn the **first Friday of each month**, a monthly digest is also generated — Claude synthesizes the last 4 editions into 3 macro trends, no web search, pure analysis.\n\nIf anything fails, an alert email is sent immediately with a direct link to the failed run.\n\n---\n\n## 5 items per edition\n\n| # | Theme | Scope |\n|---|---|---|\n| 1 | **Front-end** | JS/TS, React, UI libs (shadcn, radix...), Remix, Next, tooling |\n| 2 | **IA pour devs** | Models, Claude Code, Cursor, Copilot, AI workflows |\n| 3 | **Web perf \u0026 archi** | Performance, runtimes, architecture patterns, deployment |\n| 4 | **Éthique \u0026 géopolitique tech** | AI regulation, digital sovereignty, CSRD/ESG, greentech |\n| 5 | **Opinion/Vision** | Opinionated articles challenging tech/UX/UI consensus — builds critical tech vision |\n\nEach item includes: summary with intentional bold + highlight markup, verified source links with dates, a \"Signal\" takeaway block, and a deep-link to Claude pre-loaded with context.\n\n---\n\n## Stack\n\n| Layer | Choice |\n|---|---|\n| Runtime | Node.js 20 (ESM) |\n| LLM | `claude-sonnet-4-6` via `@anthropic-ai/sdk` |\n| Web search | Anthropic `web_search_20250305` tool |\n| Email | Resend API |\n| Scheduler | GitHub Actions cron |\n| History | `history.json` committed to repo (last 4 editions) |\n\n---\n\n## Scripts\n\n| File | Role |\n|---|---|\n| `src/generate.js` | Weekly newsletter — Claude + web search → HTML email |\n| `src/digest.js` | Monthly digest — synthesizes history into 3 trends |\n| `src/alert.js` | Failure alert — sends email with link to failed run |\n\n---\n\n## Setup\n\n### 1. Clone and push\n\n```bash\ngit clone \u003cthis-repo\u003e \u0026\u0026 cd signal-newsletter\ngh repo create signal-newsletter --private --push --source=.\n```\n\n### 2. Set repository secrets\n\n`Settings → Secrets and variables → Actions → New repository secret`\n\n| Secret | Value |\n|---|---|\n| `ANTHROPIC_API_KEY` | API key from [console.anthropic.com](https://console.anthropic.com/settings/keys) |\n| `RESEND_API_KEY` | API key from [resend.com](https://resend.com) |\n| `RECIPIENT_EMAIL` | Your email address |\n\n### 3. Verify your domain on Resend\n\nAdd the DNS records Resend provides to your domain registrar, then wait for verification (~5–30 min).\n\n### 4. Trigger manually to verify\n\n```bash\ngh workflow run newsletter.yml --repo \u003cyour-username\u003e/signal-newsletter\ngh run list --repo \u003cyour-username\u003e/signal-newsletter\n```\n\nCheck your inbox. Done.\n\n---\n\n## Local development\n\n```bash\nnpm install\n\n# Generate preview.html with mock data (zero API cost)\nnode src/generate.js --dry-run \u0026\u0026 open preview.html\n\n# Send preview.html via Resend (zero API cost, tests email delivery)\nRESEND_API_KEY=re_... RECIPIENT_EMAIL=you@example.com node src/generate.js --send-preview\n\n# Full run\nANTHROPIC_API_KEY=sk-... RESEND_API_KEY=re_... RECIPIENT_EMAIL=you@example.com node src/generate.js\n```\n\n---\n\n## Customization\n\nAll personalization lives in `SYSTEM_PROMPT` inside `src/generate.js`:\n\n- **Profile** — edit the dev context at the top\n- **Themes** — the 5-item structure is explicit and ordered\n- **Sources** — curated allowlist of trusted domains, no AI-generated content\n- **Markup rules** — strict bold/highlight constraints keep formatting intentional\n\nThe `history.json` file is auto-managed. Don't edit it manually.\n\n---\n\n## Cost\n\n~$0.50–1.00 per weekly edition with `claude-sonnet-4-6` + web search.  \nResend free tier covers 3,000 emails/month.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphaelchpprt%2Fsignal-newsletter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraphaelchpprt%2Fsignal-newsletter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphaelchpprt%2Fsignal-newsletter/lists"}