- Published on
Build an n8n workflow that summarizes Hacker News with an LLM
- Authors

- Name
- Nadim Tuhin
- @nadimtuhin
Most "automate it with AI" demos stop at a screenshot. This one is a workflow you can import, run and change in about ten minutes.
I use small workflows like this for clients who want a daily digest of something (news, tickets, competitor pages) without a new SaaS subscription. The pattern is always the same: fetch, shape, ask an LLM, deliver.
What we're building
A manual-trigger workflow with 7 nodes that:
- Fetches the top story ids from the Hacker News API
- Keeps the first 5
- Fetches each story
- Builds one prompt from the titles and links
- Sends it to an LLM
- Returns a digest plus the single most useful story for a developer
Real output from my last run:
Magnitude provides self-optimizing inference engine for agents.
Commit Description demonstrates using commit messages as thinking tool.
Bloomberg terminal history covers evolution of financial data terminals.
You Said No MCP discusses Model Context Protocol.
I Could've Accessed 17T Microsoft Records describes security researcher access to massive data.
Most useful: Commit Description as a Thinking Tool.
Prerequisites
- Docker
- An OpenAI-compatible chat endpoint. I used a local gateway at
http://localhost:20128/v1with a free model. Any provider with the same/chat/completionsshape works.
Step 1: Run n8n in Docker
docker run -d --name n8n-demo -p 5678:5678 \
-e N8N_BLOCK_ENV_ACCESS_IN_NODE=false \
-e LLM_KEY=your-key-here \
-v n8n-data:/home/node/.n8n \
n8nio/n8n:latest
N8N_BLOCK_ENV_ACCESS_IN_NODE=false lets expressions read $env.LLM_KEY, so the key never lives inside the workflow JSON. Open http://localhost:5678 and create the owner account.
Step 2: Fetch the stories
Two HTTP Request nodes do the fetching:
- Top story ids:
GET https://hacker-news.firebaseio.com/v0/topstories.json - Fetch story:
GET https://hacker-news.firebaseio.com/v0/item/{{ $json.id }}.json
In between, a Code node keeps the first five ids.
Note: n8n splits a JSON array response into one item per element. A bare number arrives as
json.data. My first version tried to.slice()a single array and failed withids.slice is not a function.
// Code node: "Take first 5"
return $input
.all()
.slice(0, 5)
.map((i) => ({ json: { id: i.json.data ?? i.json } }))
Step 3: Build one prompt
One call for all five stories is cheaper and faster than five calls.
// Code node: "Build prompt"
const lines = $input.all().map((i) => `- ${i.json.title} (${i.json.url || 'no url'})`)
return [
{
json: {
prompt:
'Summarize these Hacker News stories in one sentence each, then name the single most useful one for a developer:\n' +
lines.join('\n'),
},
},
]
Step 4: Call the LLM
An HTTP Request node, method POST, URL http://host.docker.internal:20128/v1/chat/completions. Inside the container localhost is the container itself, so host.docker.internal is how you reach a gateway on your machine.
- Header:
Authorization: Bearer {{ $env.LLM_KEY }} - Body (JSON):
={{ JSON.stringify({ model: 'free', messages: [{ role: 'user', content: $json.prompt }] }) }}
A final Set node pulls the text out with {{ $json.choices[0].message.content }} and stores it as digest.
Running it from the CLI
Handy for testing without clicking through the editor:
docker exec n8n-demo n8n import:workflow --input=/tmp/hn-digest.json
docker exec -e N8N_RUNNERS_BROKER_PORT=5690 n8n-demo n8n execute --id=hndigest0000001
Two things that cost me time:
import:workflowfails withNOT NULL constraint failed: workflow_entity.idunless the JSON has a top-level"id".n8n executeinside a running container collides on the task broker port (5679). SettingN8N_RUNNERS_BROKER_PORTto another port fixes it.
When to use this, and when not to
Good fit:
- A daily or weekly digest for a small team
- Any "read a list, summarize, send somewhere" job
- Prototyping before you commit to custom code
Not a good fit:
- Anything that needs exact, auditable output. LLM summaries vary between runs.
- Heavy scraping of sites that block bots. Use a real browser automation setup for that.
What's next
Replace the manual trigger with a Schedule Trigger and add a Slack, email or Telegram node at the end. That turns the demo into something your team reads every morning.
Final thoughts
The whole thing is seven nodes and two short scripts. The hard part is rarely the workflow. It is deciding which manual task is worth automating and what a good result looks like.
If you have a process like that, book a 30 minute call and tell me what you want to stop doing by hand.