Introduction
Welcome back to the IoT Weekend 2026 series!
In Part 1: The 2026 Architecture, we established our foundation by setting up a secure, serverless HiveMQ Cloud Broker for MQTT 5.0 communication. We decided to ditch the old, insecure ways of 2018 in favor of TLS encryption and scalable infrastructure.
Today, in Part 2, we are building the "brain" of our operation. We are moving away from long-running, expensive servers and deploying a high-performance TypeScript Webhook on Vercel to handle interactions from the LINE Messaging API.
The Goal for Part 2
By the end of this tutorial, you will have:
- Created a LINE Messaging API Channel.
- Designed a modern UI using LINE Rich Menus.
- Coded and deployed a Serverless Webhook on Vercel.
- Successfully published a secure MQTT message via a chat command.
Step 1: Create your LINE Messaging API Channel
To let users talk to our system, we need a LINE Official Account.
- Log in to the LINE Developers Console with your LINE account.
- Create a new Provider: If you don't have one, create one. Name it something like "My Smart Home".
- Create a Messaging API Channel:
- Select your provider and create a new channel of type "Messaging API".
- Give your Bot a name (e.g., "HomeController-26") and upload a nice profile picture.
- Get your Credentials: Once created, navigate to the Messaging API tab. Scroll down and issue a Channel access token (long-lived). Copy this token and your Channel secret (found on the Basic settings tab) to a safe place. We need them for Step 4.
Step 2: Designing the 2026 UI (Rich Menu)
In the old days, we asked users to type "ON" or "OFF". That's bad UX. In 2026, we use Rich Menus—a persistent menu bar at the bottom of the chat screen.
- Go to the LINE Official Account Manager.
- Select your account from the list.
- Navigate to Home > Rich menus > Create new.
- Design a simple menu with two large buttons.
- Set the Action type for both buttons to Text.
- Button 1 Text:
ON - Button 2 Text:
OFF
- Button 1 Text:
- Save and activate the menu as the default for all users.
Now, when you tap a button, it sends the text command automatically!
Step 3: Coding the Serverless Webhook
We will use Next.js API Routes hosted on Vercel. This function will wake up only when LINE sends an event, process it, and go back to sleep—saving immense costs compared to a 24/7 server.
1. Initialize the project
Open your terminal and create a new Next.js project with TypeScript:
npx create-next-app@latest iot-webhook --ts
cd iot-webhook
npm install mqtt @line/bot-sdk
2. Create the Webhook Logic
In a modern serverless environment, we want our function to be stateless and fast. Create a new file at src/pages/api/webhook.ts.
This script performs three critical tasks:
- Verifies the incoming request from LINE.
- Connects to HiveMQ using TLS (Port 8883).
- Publishes the command and Replies to the user.
// src/pages/api/webhook.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { Client, WebhookEvent, TextMessage } from '@line/bot-sdk';
import mqtt from 'mqtt';
// 1. Initialize LINE SDK with environment variables
const lineConfig = {
channelAccessToken: process.env.LINE_ACCESS_TOKEN || '',
channelSecret: process.env.LINE_CHANNEL_SECRET || '',
};
const lineClient = new Client(lineConfig);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Only allow POST requests from LINE
if (req.method !== 'POST') {
return res.status(405).end();
}
const events: WebhookEvent[] = req.body.events;
// Process events in parallel
await Promise.all(events.map(async (event) => {
if (event.type !== 'message' || event.message.type !== 'text') return null;
const userMessage = event.message.text.toUpperCase();
const replyToken = event.replyToken;
// 2. Secure MQTT Connection (TLS 1.3)
// We connect within the handler to ensure a fresh session for the serverless hit
const mqttClient = await mqtt.connectAsync(`mqtts://${process.env.MQTT_BROKER}`, {
username: process.env.MQTT_USER,
password: process.env.MQTT_PASSWORD,
port: 8883,
});
try {
if (userMessage === 'ON') {
await mqttClient.publishAsync('home/living-room/light', '1', { qos: 1 });
await lineClient.replyMessage(replyToken, { type: 'text', text: '💡 Light turned ON' });
} else if (userMessage === 'OFF') {
await mqttClient.publishAsync('home/living-room/light', '0', { qos: 1 });
await lineClient.replyMessage(replyToken, { type: 'text', text: '🌑 Light turned OFF' });
}
} catch (err) {
console.error('MQTT/LINE Error:', err);
} finally {
// 3. Gracefully close MQTT connection to allow the Lambda to freeze
await mqttClient.end();
}
}));
res.status(200).send('OK');
}
Step 4: Deployment & Security
In 2026, we never hardcode credentials. We use environment variables to keep our secrets safe and our code clean.
- Push to GitHub: Create a private repository and push your Next.js project.
- Connect to Vercel: Import your repository into Vercel.
- Configure Environment Variables: In the Vercel Dashboard, navigate to Settings > Environment Variables and add the following keys:
-
LINE_ACCESS_TOKEN(Your Long-lived Channel Access Token) -
LINE_CHANNEL_SECRET(Found in Basic Settings) -
MQTT_BROKER(Your HiveMQ Cluster URL, e.g.,xxx.s1.eu.hivemq.cloud) -
MQTT_USER(The MQTT credentials created in Part 1) MQTT_PASSWORD
-
- Configure Webhook: * Once deployed, copy your Vercel deployment URL (e.g.,
https://iot-webhook.vercel.app/api/webhook).- Go to the LINE Developers Console > Messaging API tab.
- Paste the URL into the Webhook URL field.
- Toggle "Use Webhook" to Enabled.
Step 5: Testing the Logic
Now it’s time to see the cloud-to-cloud communication in action.
- Open the LINE Bot on your smartphone.
- Tap the "ON" button on your Rich Menu (which we designed in Step 2).
- Check HiveMQ: Open your HiveMQ Cloud Web Console. Under the "Web Client" tab, you should see a message
1published to the topichome/living-room/light. - Check LINE: Your Bot should reply instantly: "💡 Light turned ON".
Summary
By leveraging Serverless functions, our bot only "lives" for the few milliseconds it takes to process a command. We’ve eliminated the need for a 24/7 running server, making this architecture highly cost-efficient, low-maintenance, and ready for the 2026 standard.
Coming Up Next
In Part 3, we finally bridge the gap between bits and atoms! We will flash our ESP32-S3 with C++ code to listen to these secure MQTT messages and finally toggle a physical LED in your room.
Happy Coding! 🚀

Top comments (0)