├── requirements.txt ├── submit-to-datasette-cloud.sh ├── scrape.js ├── README.md ├── .github └── workflows │ └── scrape.yml ├── datasette-io.json └── simonwillison-net.json /requirements.txt: -------------------------------------------------------------------------------- 1 | shot-scraper 2 | csv-diff>=1.2 -------------------------------------------------------------------------------- /submit-to-datasette-cloud.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | export SIMONWILLISON_ROWS=$( 5 | jq -n --argjson rows "$(cat simonwillison-net.json)" \ 6 | '{ "rows": $rows, "replace": true }' 7 | ) 8 | export DATASETTE_ROWS=$( 9 | jq -n --argjson rows "$(cat datasette-io.json)" \ 10 | '{ "rows": $rows, "replace": true }' 11 | ) 12 | curl -X POST \ 13 | https://simon.datasette.cloud/data/hacker_news_posts/-/insert \ 14 | -H "Content-Type: application/json" \ 15 | -H "Authorization: Bearer $DS_TOKEN" \ 16 | -d "$SIMONWILLISON_ROWS" 17 | curl -X POST \ 18 | https://simon.datasette.cloud/data/hacker_news_posts/-/insert \ 19 | -H "Content-Type: application/json" \ 20 | -H "Authorization: Bearer $DS_TOKEN" \ 21 | -d "$DATASETTE_ROWS" 22 | -------------------------------------------------------------------------------- /scrape.js: -------------------------------------------------------------------------------- 1 | () => { 2 | var items = Array.from(document.querySelectorAll('.athing'), el => { 3 | const title = el.querySelector('.titleline a').innerText; 4 | const points = parseInt(el.nextSibling.querySelector('.score').innerText); 5 | const url = el.querySelector('.titleline a').href; 6 | const dt = el.nextSibling.querySelector('.age').title.split(' ')[0]; 7 | const submitter = el.nextSibling.querySelector('.hnuser').innerText; 8 | const commentsUrl = el.nextSibling.querySelector('.age a').href; 9 | const id = commentsUrl.split('?id=')[1]; 10 | // Only posts with comments have a comments link 11 | const commentsLink = Array.from( 12 | el.nextSibling.querySelectorAll('a') 13 | ).filter(el => el && el.innerText.includes('comment'))[0]; 14 | let numComments = 0; 15 | if (commentsLink) { 16 | numComments = parseInt(commentsLink.innerText.split()[0]); 17 | } 18 | return {id, title, url, dt, points, submitter, commentsUrl, numComments}; 19 | }); 20 | if (!items.length) { 21 | throw 'No items found'; 22 | } 23 | return items; 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scrape-hacker-news-by-domain 2 | 3 | Scrape HN to track links from specific domains 4 | 5 | See [Scraping web pages from the command-line with shot-scraper](https://simonwillison.net/2022/Mar/14/scraping-web-pages-shot-scraper/) for details of how this works. 6 | 7 | Recently scraped data from this repo is also published to this Datasette table: 8 | 9 | https://simon.datasette.cloud/data/hacker_news_posts?_sort_desc=dt 10 | 11 | More about how that works in [Datasette’s new JSON write API: The first alpha of Datasette 1.0](https://simonwillison.net/2022/Dec/2/datasette-write-api/). 12 | 13 | ## Analysis with git-history 14 | 15 | To analyze data over time from the commit logs, run [git-history](https://github.com/simonw/git-history) like this: 16 | ```bash 17 | uvx git-history file --repo https://github.com/simonw/scrape-hacker-news-by-domain \ 18 | hacker-news.db simonwillison-net.json --id id 19 | ``` 20 | Then open in [Datasette](https://datasette.io/): 21 | ```bash 22 | uvx datasette data.db 23 | ``` 24 | This is an interesting starting point: 25 | 26 | http://127.0.0.1:8001/data/item?_facet=submitter&_facet_date=dt&dt__gte=2025&_sort_desc=dt 27 | 28 | This one helps filter for rows where a column was changed beyond the first version: 29 | 30 | /data/item_changed?_facet=column&_where=item_version+not+in+(select+_id+from+item_version+where+_version+%3D+1) 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/scrape.yml: -------------------------------------------------------------------------------- 1 | name: Scrape Hacker News 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | schedule: 7 | - cron: '17 * * * *' 8 | 9 | jobs: 10 | shot-scraper: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Set up Python 3.12 15 | uses: actions/setup-python@v5 16 | with: 17 | python-version: "3.12" 18 | cache: "pip" 19 | - name: Cache Playwright browsers 20 | uses: actions/cache@v4 21 | with: 22 | path: ~/.cache/ms-playwright/ 23 | key: ${{ runner.os }}-browsers 24 | - name: Install dependencies 25 | run: | 26 | pip install -r requirements.txt 27 | - name: Install Playwright dependencies 28 | run: | 29 | shot-scraper install 30 | - name: Scrape 31 | run: | 32 | shot-scraper javascript \ 33 | "https://news.ycombinator.com/from?site=simonwillison.net" \ 34 | -i scrape.js -o simonwillison-net-new.json 35 | sleep 5 36 | shot-scraper javascript \ 37 | "https://news.ycombinator.com/from?site=datasette.io" \ 38 | -i scrape.js -o datasette-io-new.json 39 | - name: Generate commit message 40 | run: | 41 | echo "$(date -u)" > /tmp/commit.txt 42 | echo "" >> /tmp/commit.txt 43 | csv-diff simonwillison-net.json simonwillison-net-new.json --key id --format json \ 44 | --extra title '{title}' \ 45 | --extra latest 'https://news.ycombinator.com/latest?id={id}' \ 46 | --extra item 'https://news.ycombinator.com/item?id={id}' >> /tmp/commit.txt 47 | echo "" >> /tmp/commit.txt 48 | csv-diff datasette-io.json datasette-io-new.json --key id --format json \ 49 | --extra title '{title}' \ 50 | --extra latest 'https://news.ycombinator.com/latest?id={id}' \ 51 | --extra item 'https://news.ycombinator.com/item?id={id}' >> /tmp/commit.txt 52 | - name: Update data 53 | run: | 54 | mv simonwillison-net-new.json simonwillison-net.json 55 | mv datasette-io-new.json datasette-io.json 56 | - name: Submit fresh data to my Datasette Cloud space 57 | env: 58 | DS_TOKEN: ${{ secrets.SIMON_DS_WRITE_TOKEN }} 59 | run: | 60 | ./submit-to-datasette-cloud.sh 61 | - name: Commit and push 62 | run: |- 63 | git config user.name "Automated" 64 | git config user.email "actions@users.noreply.github.com" 65 | git add -A 66 | git commit -F /tmp/commit.txt || exit 0 67 | git pull --rebase 68 | git push 69 | -------------------------------------------------------------------------------- /datasette-io.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "45612672", 4 | "title": "Office MCP Registry on Datasette", 5 | "url": "https://lite.datasette.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Frosmur%2Fofficial-mcp-registry-database%2Fmain%2Fofficial_mcp_registry.db#/official_mcp_registry/servers", 6 | "dt": "2025-10-17T02:01:56", 7 | "points": 1, 8 | "submitter": "dcreater", 9 | "commentsUrl": "https://news.ycombinator.com/item?id=45612672", 10 | "numComments": 0 11 | }, 12 | { 13 | "id": "42707592", 14 | "title": "LLM \u2013 A CLI utility and Python library for interacting with LLMs", 15 | "url": "https://llm.datasette.io/en/stable/index.html", 16 | "dt": "2025-01-15T05:18:25", 17 | "points": 1, 18 | "submitter": "tzury", 19 | "commentsUrl": "https://news.ycombinator.com/item?id=42707592", 20 | "numComments": 0 21 | }, 22 | { 23 | "id": "42236321", 24 | "title": "SQLite-utils: a tool for manipulating SQLite databases", 25 | "url": "https://sqlite-utils.datasette.io/en/stable/", 26 | "dt": "2024-11-25T13:56:43", 27 | "points": 9, 28 | "submitter": "mpbart", 29 | "commentsUrl": "https://news.ycombinator.com/item?id=42236321", 30 | "numComments": 0 31 | }, 32 | { 33 | "id": "41382987", 34 | "title": "LLM Command Line Tool", 35 | "url": "https://llm.datasette.io/en/stable/", 36 | "dt": "2024-08-28T19:00:40", 37 | "points": 9, 38 | "submitter": "franze", 39 | "commentsUrl": "https://news.ycombinator.com/item?id=41382987", 40 | "numComments": 1 41 | }, 42 | { 43 | "id": "40909106", 44 | "title": "CLI tool and Python library for manipulating SQLite databases", 45 | "url": "https://sqlite-utils.datasette.io/en/stable/index.html#", 46 | "dt": "2024-07-08T20:09:43", 47 | "points": 4, 48 | "submitter": "punnerud", 49 | "commentsUrl": "https://news.ycombinator.com/item?id=40909106", 50 | "numComments": 1 51 | }, 52 | { 53 | "id": "40617385", 54 | "title": "Learn SQL with Datasette", 55 | "url": "https://datasette.io/tutorials/learn-sql", 56 | "dt": "2024-06-08T13:22:16", 57 | "points": 4, 58 | "submitter": "tosh", 59 | "commentsUrl": "https://news.ycombinator.com/item?id=40617385", 60 | "numComments": 0 61 | }, 62 | { 63 | "id": "39591769", 64 | "title": "Shot-Scraper", 65 | "url": "https://shot-scraper.datasette.io/en/stable/", 66 | "dt": "2024-03-04T15:44:51", 67 | "points": 1, 68 | "submitter": "brk", 69 | "commentsUrl": "https://news.ycombinator.com/item?id=39591769", 70 | "numComments": 0 71 | }, 72 | { 73 | "id": "39504750", 74 | "title": "Shot-scraper: Scraping pages using JavaScript", 75 | "url": "https://shot-scraper.datasette.io/en/stable/javascript.html", 76 | "dt": "2024-02-25T21:05:57", 77 | "points": 1, 78 | "submitter": "stefankuehnel", 79 | "commentsUrl": "https://news.ycombinator.com/item?id=39504750", 80 | "numComments": 0 81 | }, 82 | { 83 | "id": "38097642", 84 | "title": "LLM CLI tool (can connect to public and self-hosted LLMs)", 85 | "url": "https://llm.datasette.io/en/stable/", 86 | "dt": "2023-11-01T13:03:51", 87 | "points": 2, 88 | "submitter": "tmsh", 89 | "commentsUrl": "https://news.ycombinator.com/item?id=38097642", 90 | "numComments": 0 91 | }, 92 | { 93 | "id": "36914612", 94 | "title": "SQLite-Utils", 95 | "url": "https://sqlite-utils.datasette.io/en/stable/index.html", 96 | "dt": "2023-07-28T23:09:17", 97 | "points": 142, 98 | "submitter": "dedalus", 99 | "commentsUrl": "https://news.ycombinator.com/item?id=36914612", 100 | "numComments": 17 101 | }, 102 | { 103 | "id": "36372190", 104 | "title": "llm 0.4: Notable update for command-line utility for interacting with LLMs", 105 | "url": "https://llm.datasette.io/en/stable/changelog.html", 106 | "dt": "2023-06-17T17:16:59", 107 | "points": 3, 108 | "submitter": "CharlesW", 109 | "commentsUrl": "https://news.ycombinator.com/item?id=36372190", 110 | "numComments": 0 111 | }, 112 | { 113 | "id": "34689624", 114 | "title": "OpenAI-to-SQLite", 115 | "url": "https://datasette.io/tools/openai-to-sqlite", 116 | "dt": "2023-02-07T06:57:40", 117 | "points": 203, 118 | "submitter": "thunderbong", 119 | "commentsUrl": "https://news.ycombinator.com/item?id=34689624", 120 | "numComments": 60 121 | }, 122 | { 123 | "id": "34317898", 124 | "title": "Building a location to time zone API with SpatiaLite and Datasette", 125 | "url": "https://datasette.io/tutorials/spatialite", 126 | "dt": "2023-01-09T23:11:35", 127 | "points": 2, 128 | "submitter": "todsacerdoti", 129 | "commentsUrl": "https://news.ycombinator.com/item?id=34317898", 130 | "numComments": 0 131 | }, 132 | { 133 | "id": "33792855", 134 | "title": "First alpha release of Datasette 1.0 intros new APIs for writing to the db", 135 | "url": "https://docs.datasette.io/en/latest/changelog.html#a0-2022-11-29", 136 | "dt": "2022-11-29T20:31:21", 137 | "points": 2, 138 | "submitter": "ghuntley", 139 | "commentsUrl": "https://news.ycombinator.com/item?id=33792855", 140 | "numComments": 0 141 | }, 142 | { 143 | "id": "33221723", 144 | "title": "Random ScotRail Apology Generator", 145 | "url": "https://scotrail.datasette.io/scotrail/random_apology", 146 | "dt": "2022-10-16T07:11:11", 147 | "points": 81, 148 | "submitter": "notpushkin", 149 | "commentsUrl": "https://news.ycombinator.com/item?id=33221723", 150 | "numComments": 46 151 | }, 152 | { 153 | "id": "32538495", 154 | "title": "ScotRail Random Apology Generator", 155 | "url": "https://scotrail.datasette.io/scotrail/random_apology", 156 | "dt": "2022-08-21T09:04:10", 157 | "points": 3, 158 | "submitter": "rcarmo", 159 | "commentsUrl": "https://news.ycombinator.com/item?id=32538495", 160 | "numComments": 1 161 | }, 162 | { 163 | "id": "32300050", 164 | "title": "Cleaning data with SQLite-utils and Datasette", 165 | "url": "https://datasette.io/tutorials/clean-data", 166 | "dt": "2022-07-31T23:49:00", 167 | "points": 3, 168 | "submitter": "ghuntley", 169 | "commentsUrl": "https://news.ycombinator.com/item?id=32300050", 170 | "numComments": 0 171 | }, 172 | { 173 | "id": "31176054", 174 | "title": "The Datasette Ecosystem", 175 | "url": "https://docs.datasette.io/en/stable/ecosystem.html", 176 | "dt": "2022-04-27T03:43:29", 177 | "points": 186, 178 | "submitter": "Tomte", 179 | "commentsUrl": "https://news.ycombinator.com/item?id=31176054", 180 | "numComments": 22 181 | }, 182 | { 183 | "id": "30575225", 184 | "title": "Learn SQL with Datasette", 185 | "url": "https://datasette.io/tutorials/learn-sql", 186 | "dt": "2022-03-06T05:15:00", 187 | "points": 5, 188 | "submitter": "JNRowe", 189 | "commentsUrl": "https://news.ycombinator.com/item?id=30575225", 190 | "numComments": 0 191 | }, 192 | { 193 | "id": "30446530", 194 | "title": "sqlite-utils - CLI & Python utility functions for manipulating SQLite databases", 195 | "url": "https://sqlite-utils.datasette.io/en/stable/index.html", 196 | "dt": "2022-02-23T21:13:36", 197 | "points": 134, 198 | "submitter": "punnerud", 199 | "commentsUrl": "https://news.ycombinator.com/item?id=30446530", 200 | "numComments": 16 201 | }, 202 | { 203 | "id": "28527978", 204 | "title": "Show HN: Datasette Desktop, macOS App for SQLite and CSVs", 205 | "url": "https://datasette.io/desktop", 206 | "dt": "2021-09-14T17:30:14", 207 | "points": 22, 208 | "submitter": "simonw", 209 | "commentsUrl": "https://news.ycombinator.com/item?id=28527978", 210 | "numComments": 2 211 | }, 212 | { 213 | "id": "28268484", 214 | "title": "The Datasette Ecosystem", 215 | "url": "https://docs.datasette.io/en/stable/ecosystem.html", 216 | "dt": "2021-08-22T19:07:33", 217 | "points": 4, 218 | "submitter": "Tomte", 219 | "commentsUrl": "https://news.ycombinator.com/item?id=28268484", 220 | "numComments": 0 221 | }, 222 | { 223 | "id": "27732281", 224 | "title": "Django SQL Dashboard", 225 | "url": "https://django-sql-dashboard.datasette.io/en/stable/", 226 | "dt": "2021-07-04T20:16:01", 227 | "points": 2, 228 | "submitter": "edward", 229 | "commentsUrl": "https://news.ycombinator.com/item?id=27732281", 230 | "numComments": 0 231 | }, 232 | { 233 | "id": "27107428", 234 | "title": "Show HN: Django SQL Dashboard", 235 | "url": "https://django-sql-dashboard.datasette.io/en/latest/", 236 | "dt": "2021-05-10T15:53:54", 237 | "points": 204, 238 | "submitter": "simonw", 239 | "commentsUrl": "https://news.ycombinator.com/item?id=27107428", 240 | "numComments": 27 241 | }, 242 | { 243 | "id": "25385296", 244 | "title": "Datasette: An open source multi-tool for exploring and publishing data", 245 | "url": "https://datasette.io/", 246 | "dt": "2020-12-11T13:09:55", 247 | "points": 285, 248 | "submitter": "robin_reala", 249 | "commentsUrl": "https://news.ycombinator.com/item?id=25385296", 250 | "numComments": 22 251 | }, 252 | { 253 | "id": "24734230", 254 | "title": "Datasette 0.50", 255 | "url": "https://docs.datasette.io/en/stable/changelog.html#v0-50", 256 | "dt": "2020-10-09T20:41:53", 257 | "points": 5, 258 | "submitter": "tosh", 259 | "commentsUrl": "https://news.ycombinator.com/item?id=24734230", 260 | "numComments": 0 261 | }, 262 | { 263 | "id": "21389850", 264 | "title": "SQL Murder Mystery", 265 | "url": "https://sql-murder-mystery.datasette.io/sql-murder-mystery", 266 | "dt": "2019-10-29T17:36:37", 267 | "points": 4, 268 | "submitter": "kickscondor", 269 | "commentsUrl": "https://news.ycombinator.com/item?id=21389850", 270 | "numComments": 0 271 | } 272 | ] 273 | -------------------------------------------------------------------------------- /simonwillison-net.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "46321965", 4 | "title": "Agent Skills (Open Standard)", 5 | "url": "https://simonwillison.net/2025/Dec/19/agent-skills/", 6 | "dt": "2025-12-19T03:22:59", 7 | "points": 2, 8 | "submitter": "yomismoaqui", 9 | "commentsUrl": "https://news.ycombinator.com/item?id=46321965", 10 | "numComments": 1 11 | }, 12 | { 13 | "id": "46313297", 14 | "title": "Your job is to deliver code you have proven to work", 15 | "url": "https://simonwillison.net/2025/Dec/18/code-proven-to-work/", 16 | "dt": "2025-12-18T14:52:11", 17 | "points": 847, 18 | "submitter": "simonw", 19 | "commentsUrl": "https://news.ycombinator.com/item?id=46313297", 20 | "numComments": 655 21 | }, 22 | { 23 | "id": "46306696", 24 | "title": "Gemini 3 Flash", 25 | "url": "https://simonwillison.net/2025/Dec/17/gemini-3-flash/", 26 | "dt": "2025-12-17T22:52:28", 27 | "points": 4, 28 | "submitter": "slig", 29 | "commentsUrl": "https://news.ycombinator.com/item?id=46306696", 30 | "numComments": 3 31 | }, 32 | { 33 | "id": "46301823", 34 | "title": "The new ChatGPT Images is here [1.5]", 35 | "url": "https://simonwillison.net/2025/Dec/16/new-chatgpt-images/", 36 | "dt": "2025-12-17T13:39:59", 37 | "points": 2, 38 | "submitter": "philipwhiuk", 39 | "commentsUrl": "https://news.ycombinator.com/item?id=46301823", 40 | "numComments": 1 41 | }, 42 | { 43 | "id": "46295771", 44 | "title": "I ported JustHTML from Python to JavaScript with Codex CLI and GPT-5.2 in hours", 45 | "url": "https://simonwillison.net/2025/Dec/15/porting-justhtml/", 46 | "dt": "2025-12-16T22:48:56", 47 | "points": 278, 48 | "submitter": "pbowyer", 49 | "commentsUrl": "https://news.ycombinator.com/item?id=46295771", 50 | "numComments": 143 51 | }, 52 | { 53 | "id": "46290011", 54 | "title": "Gemini thinking trace, reviewing feedback on its code from another model", 55 | "url": "https://simonwillison.net/2025/Dec/16/gemini-thinking-trace/", 56 | "dt": "2025-12-16T15:48:22", 57 | "points": 3, 58 | "submitter": "zdw", 59 | "commentsUrl": "https://news.ycombinator.com/item?id=46290011", 60 | "numComments": 1 61 | }, 62 | { 63 | "id": "46286652", 64 | "title": "I ported JustHTML from Python to JavaScript with LLMs in 4.5 hours", 65 | "url": "https://simonwillison.net/2025/Dec/15/porting-justhtml/", 66 | "dt": "2025-12-16T09:49:44", 67 | "points": 1, 68 | "submitter": "genericlemon24", 69 | "commentsUrl": "https://news.ycombinator.com/item?id=46286652", 70 | "numComments": 0 71 | }, 72 | { 73 | "id": "46283283", 74 | "title": "I ported JustHTML from Python to JavaScript with Codex CLI and GPT-5.2 in 4.5hrs", 75 | "url": "https://simonwillison.net/2025/Dec/15/porting-justhtml/", 76 | "dt": "2025-12-16T00:51:05", 77 | "points": 14, 78 | "submitter": "simonw", 79 | "commentsUrl": "https://news.ycombinator.com/item?id=46283283", 80 | "numComments": 3 81 | }, 82 | { 83 | "id": "46283037", 84 | "title": "2025 Word of the Year: Slop", 85 | "url": "https://simonwillison.net/2025/Dec/15/2025-word-of-the-year-slop/", 86 | "dt": "2025-12-16T00:24:37", 87 | "points": 2, 88 | "submitter": "vismit2000", 89 | "commentsUrl": "https://news.ycombinator.com/item?id=46283037", 90 | "numComments": 1 91 | }, 92 | { 93 | "id": "46267003", 94 | "title": "Copywriters reveal how AI has decimated their industry", 95 | "url": "https://simonwillison.net/2025/Dec/14/copywriters-reveal-how-ai-has-decimated-their-industry/", 96 | "dt": "2025-12-14T21:15:53", 97 | "points": 4, 98 | "submitter": "abdelhousni", 99 | "commentsUrl": "https://news.ycombinator.com/item?id=46267003", 100 | "numComments": 0 101 | }, 102 | { 103 | "id": "46264701", 104 | "title": "JustHTML is an example of vibe engineering in action", 105 | "url": "https://simonwillison.net/2025/Dec/14/justhtml/", 106 | "dt": "2025-12-14T17:13:16", 107 | "points": 5, 108 | "submitter": "lumpa", 109 | "commentsUrl": "https://news.ycombinator.com/item?id=46264701", 110 | "numComments": 0 111 | }, 112 | { 113 | "id": "46261998", 114 | "title": "Willison on Merchant's \"Copywriters reveal how AI has decimated their industry\"", 115 | "url": "https://simonwillison.net/2025/Dec/14/copywriters-reveal-how-ai-has-decimated-their-industry/", 116 | "dt": "2025-12-14T10:01:25", 117 | "points": 80, 118 | "submitter": "planckscnst", 119 | "commentsUrl": "https://news.ycombinator.com/item?id=46261998", 120 | "numComments": 92 121 | }, 122 | { 123 | "id": "46257185", 124 | "title": "What happens when the coding becomes the least interesting part of the work", 125 | "url": "https://simonwillison.net/2025/Dec/13/obie-fernandez/", 126 | "dt": "2025-12-13T19:31:24", 127 | "points": 6, 128 | "submitter": "mmaunder", 129 | "commentsUrl": "https://news.ycombinator.com/item?id=46257185", 130 | "numComments": 4 131 | }, 132 | { 133 | "id": "46250332", 134 | "title": "OpenAI are quietly adopting skills, now available in ChatGPT and Codex CLI", 135 | "url": "https://simonwillison.net/2025/Dec/12/openai-skills/", 136 | "dt": "2025-12-12T23:30:19", 137 | "points": 587, 138 | "submitter": "simonw", 139 | "commentsUrl": "https://news.ycombinator.com/item?id=46250332", 140 | "numComments": 324 141 | }, 142 | { 143 | "id": "46226272", 144 | "title": "Dark mode now available on Simon Willison's blog", 145 | "url": "https://simonwillison.net/2025/Dec/10/dark-mode/", 146 | "dt": "2025-12-11T00:54:53", 147 | "points": 1, 148 | "submitter": "macote", 149 | "commentsUrl": "https://news.ycombinator.com/item?id=46226272", 150 | "numComments": 0 151 | }, 152 | { 153 | "id": "46223882", 154 | "title": "Useful patterns for building HTML tools", 155 | "url": "https://simonwillison.net/2025/Dec/10/html-tools/", 156 | "dt": "2025-12-10T21:08:41", 157 | "points": 352, 158 | "submitter": "simonw", 159 | "commentsUrl": "https://news.ycombinator.com/item?id=46223882", 160 | "numComments": 94 161 | }, 162 | { 163 | "id": "46164937", 164 | "title": "The Resonant Computing Manifesto", 165 | "url": "https://simonwillison.net/2025/Dec/5/resonant-computing/", 166 | "dt": "2025-12-05T18:07:15", 167 | "points": 2, 168 | "submitter": "mooreds", 169 | "commentsUrl": "https://news.ycombinator.com/item?id=46164937", 170 | "numComments": 3 171 | }, 172 | { 173 | "id": "46118685", 174 | "title": "DeepSeek-v3.2", 175 | "url": "https://simonwillison.net/2025/Dec/1/deepseek-v32/", 176 | "dt": "2025-12-02T07:40:38", 177 | "points": 7, 178 | "submitter": "doppp", 179 | "commentsUrl": "https://news.ycombinator.com/item?id=46118685", 180 | "numComments": 0 181 | }, 182 | { 183 | "id": "46104964", 184 | "title": "ChatGPT's Third Birthday", 185 | "url": "https://simonwillison.net/2025/Nov/30/chatgpt-third-birthday/", 186 | "dt": "2025-12-01T08:40:20", 187 | "points": 2, 188 | "submitter": "vismit2000", 189 | "commentsUrl": "https://news.ycombinator.com/item?id=46104964", 190 | "numComments": 0 191 | }, 192 | { 193 | "id": "46101421", 194 | "title": "ChatGPT is three years old today", 195 | "url": "https://simonwillison.net/2025/Nov/30/chatgpt-third-birthday/", 196 | "dt": "2025-11-30T23:12:29", 197 | "points": 6, 198 | "submitter": "ingve", 199 | "commentsUrl": "https://news.ycombinator.com/item?id=46101421", 200 | "numComments": 2 201 | }, 202 | { 203 | "id": "46085641", 204 | "title": "ChatGPT prompt consumes equivalent to 10s of Netflix", 205 | "url": "https://simonwillison.net/2025/Nov/29/chatgpt-netflix/", 206 | "dt": "2025-11-29T06:55:31", 207 | "points": 8, 208 | "submitter": "makeavish", 209 | "commentsUrl": "https://news.ycombinator.com/item?id=46085641", 210 | "numComments": 4 211 | }, 212 | { 213 | "id": "46067294", 214 | "title": "Claude Opus 4.5, and why evaluating new LLMs is increasingly difficult", 215 | "url": "https://simonwillison.net/2025/Nov/24/claude-opus/", 216 | "dt": "2025-11-27T09:04:06", 217 | "points": 6, 218 | "submitter": "jonesn11", 219 | "commentsUrl": "https://news.ycombinator.com/item?id=46067294", 220 | "numComments": 1 221 | }, 222 | { 223 | "id": "46057223", 224 | "title": "Building Effective Agents", 225 | "url": "https://simonwillison.net/2024/Dec/20/building-effective-agents/", 226 | "dt": "2025-11-26T13:31:15", 227 | "points": 1, 228 | "submitter": "gearnode", 229 | "commentsUrl": "https://news.ycombinator.com/item?id=46057223", 230 | "numComments": 0 231 | }, 232 | { 233 | "id": "46042281", 234 | "title": "Claude Opus 4.5, and why evaluating new LLMs is increasingly difficult", 235 | "url": "https://simonwillison.net/2025/Nov/24/claude-opus/", 236 | "dt": "2025-11-25T04:14:52", 237 | "points": 1, 238 | "submitter": "gingersnap", 239 | "commentsUrl": "https://news.ycombinator.com/item?id=46042281", 240 | "numComments": 1 241 | }, 242 | { 243 | "id": "46038489", 244 | "title": "Claude Opus 4.5, and why evaluating new LLMs is increasingly difficult", 245 | "url": "https://simonwillison.net/2025/Nov/24/claude-opus/", 246 | "dt": "2025-11-24T19:59:22", 247 | "points": 7, 248 | "submitter": "janpio", 249 | "commentsUrl": "https://news.ycombinator.com/item?id=46038489", 250 | "numComments": 2 251 | }, 252 | { 253 | "id": "46022682", 254 | "title": "Olmo 3 is a fully open LLM", 255 | "url": "https://simonwillison.net/2025/Nov/22/olmo-3/", 256 | "dt": "2025-11-23T11:27:36", 257 | "points": 5, 258 | "submitter": "lumpa", 259 | "commentsUrl": "https://news.ycombinator.com/item?id=46022682", 260 | "numComments": 2 261 | }, 262 | { 263 | "id": "46009839", 264 | "title": "LLM cmd, an LLM plugin to prompt and edit a shell command", 265 | "url": "https://simonwillison.net/2024/Mar/26/llm-cmd/", 266 | "dt": "2025-11-21T22:35:10", 267 | "points": 2, 268 | "submitter": "skeledrew", 269 | "commentsUrl": "https://news.ycombinator.com/item?id=46009839", 270 | "numComments": 0 271 | }, 272 | { 273 | "id": "46008619", 274 | "title": "The fate of \"small\" open source", 275 | "url": "https://simonwillison.net/2025/Nov/17/the-fate-of-small-open-source/", 276 | "dt": "2025-11-21T20:29:59", 277 | "points": 2, 278 | "submitter": "synergy20", 279 | "commentsUrl": "https://news.ycombinator.com/item?id=46008619", 280 | "numComments": 0 281 | }, 282 | { 283 | "id": "45994906", 284 | "title": "Nano Banana Pro is the best available image generation model", 285 | "url": "https://simonwillison.net/2025/Nov/20/nano-banana-pro/", 286 | "dt": "2025-11-20T17:08:45", 287 | "points": 3, 288 | "submitter": "xnx", 289 | "commentsUrl": "https://news.ycombinator.com/item?id=45994906", 290 | "numComments": 0 291 | }, 292 | { 293 | "id": "45982583", 294 | "title": "Google Antigravity", 295 | "url": "https://simonwillison.net/2025/Nov/18/google-antigravity/", 296 | "dt": "2025-11-19T17:56:38", 297 | "points": 2, 298 | "submitter": "bilsbie", 299 | "commentsUrl": "https://news.ycombinator.com/item?id=45982583", 300 | "numComments": 0 301 | } 302 | ] 303 | --------------------------------------------------------------------------------