Automate Like a Pro: Flutter Meets n8n for Real-Time Hacker News Search + Auto-Posting

In this post, I’ll walk you through how I connected a Flutter mobile app with n8n, a powerful low-code automation tool, to:
Accept a search query from Flutter,
Trigger a workflow via Webhook,
Fetch results from the Hacker News Algolia API,
Return the results back to the app in real-time,
Let’s break it down step by step.
🛠 Step 1: Set Up n8n with Docker
You can get up and running with n8n in seconds using Docker. Here’s the docker-compose.yml
I used:
version: '3.8'
services:
n8n:
image: docker.n8n.io/n8nio/n8n
container_name: n8n
ports:
- "5678:5678"
volumes:
- n8n_data:/home/node/.n8n
restart: unless-stopped
environment:
- N8N_SECURE_COOKIE=false # disable secure cookie flag for local development
volumes:
n8n_data:
Run it:
docker-compose up -d
n8n will be available at http://localhost:5678
🧠 Step 2: Create the n8n Workflow
Here’s what the workflow does:
Receives a POST request from Flutter
Calls the Hacker News API via HTTP Request
Formats the top 5 results using a Function node
Returns them to the mobile app
Workflow Diagram
graph TD;
A[Webhook: Receive from Flutter] --> B[HTTP Request: HN Search];
B --> C[Function: Format Articles];
Hacker News API Used:
GET https://hn.algolia.com/api/v1/search?query=<keyword>
Function Code in Format Articles
Node:
const results = $json.hits.slice(0, 5).map(hit => ({
title: hit.title || hit.story_title,
url: hit.url || hit.story_url
}));
return [{ json: { articles: results } }];
📱 Step 3: Flutter Integration
Here’s the core Flutter code that sends the query and displays the result.
Search Function
Future<void> searchHackerNews(String keyword) async {
final response = await http.post(
Uri.parse('http://localhost:5678/webhook/hn-search?query=$keyword'),
headers: {'Content-Type': 'application/json'},
);
final data = jsonDecode(response.body);
for (var article in data['articles']) {
print('${article['title']} → ${article['url']}');
}
}
UI Snippet with ListView
ListView.builder(
itemCount: articles.length,
itemBuilder: (context, index) {
final article = articles[index];
return ListTile(
title: Text(article['title']),
subtitle: Text(article['url']),
onTap: () => launch(article['url']),
);
},
)
Subscribe to my newsletter
Read articles from shamnad sherief directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

shamnad sherief
shamnad sherief
The future needs more programmers — follow me to learn more about my adventures as a programmer!