|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | +<meta charset="UTF-8"> |
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | +<title>pubmed-watcher β Automated PubMed Paper Alerts</title> |
| 7 | +<meta name="description" content="Automated alerting for new PubMed papers. Delta detection β only alerts on unseen papers. Built for cron."> |
| 8 | +<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>π¬</text></svg>"> |
| 9 | +<style> |
| 10 | +*,*::before,*::after{margin:0;padding:0;box-sizing:border-box} |
| 11 | +:root{--bg:#06080c;--bg2:#0c1018;--bg3:#0f1520;--bg4:#141c28;--accent:#00e5bf;--accent-dim:#00e5bf60;--accent-glow:#00e5bf20;--text:#e2e8f0;--text2:#8892a4;--text3:#4a5568;--border:#1a2332;--red:#ff5f57;--yellow:#febc2e;--green:#28c840;--mono:'SF Mono','Fira Code','JetBrains Mono','Consolas',monospace;--sans:'Inter',-apple-system,BlinkMacSystemFont,system-ui,sans-serif} |
| 12 | +html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased} |
| 13 | +body{font-family:var(--sans);background:var(--bg);color:var(--text);line-height:1.6;overflow-x:hidden} |
| 14 | +::selection{background:var(--accent);color:var(--bg)} |
| 15 | +a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline} |
| 16 | +.container{max-width:960px;margin:0 auto;padding:0 clamp(1rem,4vw,2rem)} |
| 17 | +.topbar{padding:1rem 0;border-bottom:1px solid var(--border);position:sticky;top:0;z-index:100;background:rgba(6,8,12,.92);backdrop-filter:blur(16px)} |
| 18 | +.topbar-inner{display:flex;align-items:center;justify-content:space-between;max-width:960px;margin:0 auto;padding:0 clamp(1rem,4vw,2rem)} |
| 19 | +.topbar a{font-family:var(--mono);font-size:.8rem;color:var(--text2)}.topbar a:hover{color:var(--accent);text-decoration:none} |
| 20 | +.topbar .logo{font-size:1rem;font-weight:700;color:var(--accent)} |
| 21 | +.hero{padding:4rem 0 3rem;text-align:center} |
| 22 | +.hero h1{font-size:clamp(2rem,6vw,3.5rem);font-weight:800;letter-spacing:-.03em;margin-bottom:.5rem} |
| 23 | +.hero h1 span{background:linear-gradient(135deg,var(--accent),#00b4d8);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent} |
| 24 | +.hero .sub{font-family:var(--mono);font-size:.85rem;color:var(--text2);margin-bottom:1.5rem} |
| 25 | +.hero p{color:var(--text2);max-width:600px;margin:0 auto 2rem;font-size:.95rem} |
| 26 | +.badge{display:inline-block;font-family:var(--mono);font-size:.7rem;padding:.25rem .75rem;border:1px solid var(--border);border-radius:100px;color:var(--text3);margin-bottom:1rem} |
| 27 | +.section{padding:3rem 0}.section-title{font-family:var(--mono);font-size:.75rem;color:var(--accent);letter-spacing:.1em;text-transform:uppercase;margin-bottom:1.5rem} |
| 28 | +.terminal{background:var(--bg);border:1px solid var(--border);border-radius:10px;overflow:hidden;margin-bottom:2rem} |
| 29 | +.terminal-bar{display:flex;align-items:center;gap:.75rem;padding:.5rem .75rem;background:var(--bg4);border-bottom:1px solid var(--border)} |
| 30 | +.terminal-dots{display:flex;gap:5px}.terminal-dots i{width:8px;height:8px;border-radius:50%;display:block} |
| 31 | +.terminal-dots i:nth-child(1){background:var(--red)}.terminal-dots i:nth-child(2){background:var(--yellow)}.terminal-dots i:nth-child(3){background:var(--green)} |
| 32 | +.terminal-title{font-family:var(--mono);font-size:.7rem;color:var(--text3)} |
| 33 | +.terminal-body{padding:1rem;font-family:var(--mono);font-size:.72rem;line-height:1.6;color:var(--text2);overflow-x:auto;white-space:pre} |
| 34 | +.info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;margin-bottom:2rem} |
| 35 | +.info-card{background:var(--bg3);border:1px solid var(--border);border-radius:10px;padding:1.25rem} |
| 36 | +.info-card h4{font-family:var(--mono);font-size:.85rem;margin-bottom:.75rem} |
| 37 | +.info-card p,.info-card li{font-size:.82rem;color:var(--text2);line-height:1.6} |
| 38 | +.info-card ul{padding-left:1.25rem}.info-card li{margin-bottom:.25rem} |
| 39 | +.flow-steps{display:flex;gap:0;margin-bottom:2rem;flex-wrap:wrap} |
| 40 | +.flow-step{flex:1;min-width:150px;background:var(--bg3);border:1px solid var(--border);padding:1rem;text-align:center;position:relative} |
| 41 | +.flow-step:first-child{border-radius:8px 0 0 8px} |
| 42 | +.flow-step:last-child{border-radius:0 8px 8px 0} |
| 43 | +.flow-step .step-num{font-family:var(--mono);font-size:.65rem;color:var(--accent);margin-bottom:.25rem} |
| 44 | +.flow-step .step-icon{font-size:1.5rem;margin-bottom:.25rem} |
| 45 | +.flow-step .step-text{font-family:var(--mono);font-size:.7rem;color:var(--text2)} |
| 46 | +.flow-step::after{content:'β';position:absolute;right:-8px;top:50%;transform:translateY(-50%);color:var(--accent);font-family:var(--mono);z-index:1} |
| 47 | +.flow-step:last-child::after{content:''} |
| 48 | +.query-list{list-style:none;padding:0} |
| 49 | +.query-item{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;background:var(--bg3);border:1px solid var(--border);border-radius:6px;margin-bottom:.5rem;font-family:var(--mono);font-size:.8rem} |
| 50 | +.query-num{color:var(--accent);font-weight:700;width:24px} |
| 51 | +.query-text{color:var(--text2)} |
| 52 | +.footer{padding:2rem 0;border-top:1px solid var(--border);text-align:center;margin-top:2rem} |
| 53 | +.footer p{font-family:var(--mono);font-size:.7rem;color:var(--text3)} |
| 54 | +</style> |
| 55 | +</head> |
| 56 | +<body> |
| 57 | +<div class="topbar"><div class="topbar-inner"> |
| 58 | + <a href="https://qclawq.github.io" class="logo">β Q's Build Lab</a> |
| 59 | + <a href="https://github.com/QclawQ/pubmed-watcher" target="_blank">github β</a> |
| 60 | +</div></div> |
| 61 | + |
| 62 | +<div class="container"> |
| 63 | +<div class="hero"> |
| 64 | + <div class="badge">pure python Β· zero dependencies Β· 617 loc</div> |
| 65 | + <h1>π¬ <span>pubmed-watcher</span></h1> |
| 66 | + <div class="sub">Automated PubMed Paper Alerts</div> |
| 67 | + <p>Watch PubMed queries and get alerted only about <strong>new</strong> papers. Tracks seen PMIDs, supports cron scheduling, outputs to terminal, Markdown, or JSON.</p> |
| 68 | +</div> |
| 69 | + |
| 70 | +<div class="section"> |
| 71 | + <div class="section-title">// how it works</div> |
| 72 | + <div class="flow-steps"> |
| 73 | + <div class="flow-step"><div class="step-num">01</div><div class="step-icon">π</div><div class="step-text">Query PubMed E-utilities</div></div> |
| 74 | + <div class="flow-step"><div class="step-num">02</div><div class="step-icon">π</div><div class="step-text">Filter against seen.json</div></div> |
| 75 | + <div class="flow-step"><div class="step-num">03</div><div class="step-icon">π₯</div><div class="step-text">Fetch new paper details</div></div> |
| 76 | + <div class="flow-step"><div class="step-num">04</div><div class="step-icon">π</div><div class="step-text">Alert only NEW papers</div></div> |
| 77 | + </div> |
| 78 | +</div> |
| 79 | + |
| 80 | +<div class="section"> |
| 81 | + <div class="section-title">// default queries</div> |
| 82 | + <ul class="query-list"> |
| 83 | + <li class="query-item"><span class="query-num">[1]</span><span class="query-text">epigenetic reprogramming aging longevity</span></li> |
| 84 | + <li class="query-item"><span class="query-num">[2]</span><span class="query-text">immunosenescence aging immune system</span></li> |
| 85 | + <li class="query-item"><span class="query-num">[3]</span><span class="query-text">senolytics senescent cells therapy</span></li> |
| 86 | + <li class="query-item"><span class="query-num">[4]</span><span class="query-text">AI drug discovery clinical trial</span></li> |
| 87 | + <li class="query-item"><span class="query-num">[5]</span><span class="query-text">biological age clock methylation</span></li> |
| 88 | + </ul> |
| 89 | +</div> |
| 90 | + |
| 91 | +<div class="section"> |
| 92 | + <div class="section-title">// demo output</div> |
| 93 | + <div class="terminal"> |
| 94 | + <div class="terminal-bar"><span class="terminal-dots"><i></i><i></i><i></i></span><span class="terminal-title">$ python3 pubmed_watcher.py watch</span></div> |
| 95 | + <div class="terminal-body">π 12 new papers found across 5 queries (last 7 days) |
| 96 | + |
| 97 | +βββ π "epigenetic reprogramming aging longevity" β 3 new βββ |
| 98 | + |
| 99 | + π Epigenetic reprogramming reverses age-associated |
| 100 | + decline in neural stem cell function |
| 101 | + π€ Zhang W β¦ Bhatt DL |
| 102 | + π° Nature Aging β’ 2026 Feb |
| 103 | + π https://pubmed.ncbi.nlm.nih.gov/39847201/ |
| 104 | + |
| 105 | + π In vivo partial reprogramming extends lifespan |
| 106 | + in progeroid mice via cellular rejuvenation |
| 107 | + π€ Ocampo A β¦ Izpisua Belmonte JC |
| 108 | + π° Cell β’ 2026 Feb 10 |
| 109 | + π https://pubmed.ncbi.nlm.nih.gov/39847202/ |
| 110 | + |
| 111 | +βββ π "senolytics senescent cells therapy" β 4 new βββ |
| 112 | + |
| 113 | + π Dasatinib plus quercetin reduces senescent |
| 114 | + cell burden in human adipose tissue |
| 115 | + π€ Kirkland JL β¦ Tchkonia T |
| 116 | + π° Nature Medicine β’ 2026 Feb |
| 117 | + π https://pubmed.ncbi.nlm.nih.gov/39847203/ |
| 118 | + |
| 119 | +ββββββββββββββββββββββββββββββββββββββββββββββββββ |
| 120 | +π Total: 12 new | 4/5 queries had results</div> |
| 121 | + </div> |
| 122 | + |
| 123 | + <div class="terminal"> |
| 124 | + <div class="terminal-bar"><span class="terminal-dots"><i></i><i></i><i></i></span><span class="terminal-title">$ python3 pubmed_watcher.py history</span></div> |
| 125 | + <div class="terminal-body">π Alert History (last 5 runs) |
| 126 | + |
| 127 | + π 2026-02-17 08:00 UTC β 12 new papers (5 queries, 7d window) |
| 128 | + β’ epigenetic reprogramming aging longevity: 3 new |
| 129 | + β’ senolytics senescent cells therapy: 4 new |
| 130 | + β’ AI drug discovery clinical trial: 3 new |
| 131 | + β’ biological age clock methylation: 2 new |
| 132 | + π 2026-02-16 08:00 UTC β 8 new papers (5 queries, 7d window) |
| 133 | + β
2026-02-15 08:00 UTC β 0 new papers (5 queries, 7d window) |
| 134 | + π 2026-02-14 08:00 UTC β 5 new papers (5 queries, 7d window)</div> |
| 135 | + </div> |
| 136 | +</div> |
| 137 | + |
| 138 | +<div class="section"> |
| 139 | + <div class="section-title">// features</div> |
| 140 | + <div class="info-grid"> |
| 141 | + <div class="info-card"> |
| 142 | + <h4>π Delta Detection</h4> |
| 143 | + <p>Tracks every PMID in <code>seen.json</code>. You only get alerted once per paper, even across multiple queries. Perfect for daily cron jobs.</p> |
| 144 | + </div> |
| 145 | + <div class="info-card"> |
| 146 | + <h4>π€ Output Formats</h4> |
| 147 | + <ul> |
| 148 | + <li><code>--terminal</code> β Pretty CLI output</li> |
| 149 | + <li><code>--markdown</code> β Telegram-ready</li> |
| 150 | + <li><code>--json</code> β Machine-readable</li> |
| 151 | + </ul> |
| 152 | + </div> |
| 153 | + <div class="info-card"> |
| 154 | + <h4>β° Cron Ready</h4> |
| 155 | + <p style="font-family:var(--mono);font-size:.72rem">0 8 * * * python3 pubmed_watcher.py watch --markdown >> /tmp/alerts.md</p> |
| 156 | + <p style="margin-top:.5rem">Run daily, pipe to Telegram, Slack, or email.</p> |
| 157 | + </div> |
| 158 | + <div class="info-card"> |
| 159 | + <h4>π» Commands</h4> |
| 160 | + <ul> |
| 161 | + <li><code>watch</code> β Check all queries</li> |
| 162 | + <li><code>add "query"</code> β Add new query</li> |
| 163 | + <li><code>list</code> β Show queries</li> |
| 164 | + <li><code>remove <id></code> β Remove query</li> |
| 165 | + <li><code>history</code> β Past runs</li> |
| 166 | + <li><code>reset-seen</code> β Clear DB</li> |
| 167 | + </ul> |
| 168 | + </div> |
| 169 | + </div> |
| 170 | +</div> |
| 171 | +</div> |
| 172 | + |
| 173 | +<footer class="footer"><div class="container"> |
| 174 | + <p>pubmed-watcher Β· <a href="https://github.com/QclawQ/pubmed-watcher">source</a> Β· <a href="https://qclawq.github.io">Q's Build Lab</a> Β· NCBI E-utilities</p> |
| 175 | +</div></footer> |
| 176 | +</body> |
| 177 | +</html> |
0 commit comments