Skip to content
Back to Articles

Zero-Friction Content: How to Automate Blog Publishing With Next.js, Telegram, and AI

SEPTEMBER 12, 20264 MIN READ
Zero-Friction Content: How to Automate Blog Publishing With Next.js, Telegram, and AI

How to Automate Blog Publishing With Next.js, Telegram, and AI

EXCERPT: Eliminate the friction of writing by building an automated publishing pipeline that turns rough Telegram messages into fully polished, SEO-optimized blog posts deployed on Next.js.

TAGS: Next.js, Automation, AI, Web Development, TypeScript

IMAGE_PROMPT: Minimalist isometric 3D render of a glowing smartphone sending luminous data streams to a futuristic server rack, cybernetic aesthetic, deep indigo and neon cyan lighting, octane render, smooth glass textures, clean dark background, no text

CONTENT: The biggest obstacle to consistent blogging isn't a lack of ideas—it's the friction of the publishing workflow.

Consider the typical journey: you have a flash of inspiration while walking the dog. By the time you get back to your desk, open your terminal, fire up your IDE, create a new MDX file, construct frontmatter, write the prose, run a local build, commit the changes, and wait for CI/CD, the spark has evaporated.

What if publishing an article was as frictionless as sending a quick text message to a colleague?

In this guide, we'll architect and implement an automated, headless publishing pipeline. By pairing a Telegram Bot as our mobile CMS, an LLM (via OpenAI/Anthropic) as our drafting and formatting assistant, and a Next.js App Router site backed by GitHub, we can publish production-ready, beautifully formatted technical essays directly from a phone.


System Architecture

The pipeline uses an asynchronous, event-driven pattern designed around git-backed content:

  1. Input: You send a raw idea, bulleted list, or voice memo to a private Telegram bot.
  2. Ingestion & Auth: A Next.js Route Handler receives the Telegram webhook, verifying that the sender's Telegram ID matches your authorized administrator ID.
  3. AI Generation: The payload is sent to an LLM with strict system instructions to generate structured MDX, including title, tags, SEO description, and semantic body copy.
  4. Git Persistence: The generated content is committed directly to your Next.js repository via the GitHub REST API using an Octokit client.
  5. Deployment & Feedback: Vercel triggers an incremental build, and the bot replies to your Telegram chat with the live preview URL.
[ Telegram App ]
       │
       ▼ (Webhook POST)
[ Next.js Route Handler (/api/bot) ]
       │
       ├─► Verify User ID
       │
       ├─► OpenAI API (Format raw thought to structured MDX)
       │
       ├─► GitHub API (Commit file to /content/posts/*.mdx)
       │
       ▼ (Reply Markdown with commit link)
[ Telegram Chat ]

1. Setting Up the Telegram Bot

First, open Telegram and search for @BotFather. Run /newbot and follow the prompts to create your bot. Copy the HTTP API Token provided.

Next, get your private Telegram User ID so your endpoint rejects messages from unauthorized users. Message @userinfobot on Telegram to get your numeric ID.

Add these values to your .env.local file:

env
TELEGRAM_BOT_TOKEN="123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ" ALLOWED_TELEGRAM_USER_ID="987654321" OPENAI_API_KEY="sk-proj-..." GITHUB_ACCESS_TOKEN="ghp_..." GITHUB_REPO_OWNER="your-username" GITHUB_REPO_NAME="your-nextjs-blog"

2. Drafting Structured MDX with AI

To ensure your Next.js site parses the generated content reliably, the LLM must return strict JSON containing both the metadata and the markdown body.

Here is a utility function using the OpenAI SDK with structured outputs:

typescript
// lib/ai.ts import OpenAI from "openai"; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); interface GeneratedPost { title: string; slug: string; excerpt: string; tags: string[]; content: string; } export async function generateBlogPost(rawThought: string): Promise<GeneratedPost> { const response = await openai.chat.completions.create({ model: "gpt-4o", messages: [ { role: "system", content: `You are an expert technical editor. Transform the user's raw notes, ideas, or voice transcriptions into a coherent, publication-ready technical blog post formatted in Markdown. Guidelines: - Output valid JSON matching the requested schema. - Create an engaging, clear title and an SEO-optimized slug (kebab-case). - Organize the body with logical H2 and H3 headings. - Preserve the author's original perspective while expanding on points that need clarity. - Include a 1-2 sentence excerpt for social previews.` }, { role: "user", content: rawThought, }, ], response_format: { type: "json_schema", json_schema: { name: "blog_post_schema", strict: true, schema: { type: "object", properties: { title: { type: "string" }, slug: { type: "string" }, excerpt: { type: "string" }, tags: { type: "array", items: { type: "string" } }, content: { type: "string" }, }, required: ["title", "slug", "excerpt", "tags", "content"], additionalProperties: false, }, }, }, }); const rawJson = response.choices[0].message.content; if (!rawJson) throw new Error("Empty response from AI engine"); return JSON.parse(rawJson) as GeneratedPost; }

3. Pushing Content Directly to Git

Instead of managing a separate database, storing content directly in your repository as Markdown files keeps your blog version-controlled, portable, and low-cost.

Using @octokit/rest, we can commit the new post directly to the main branch:

typescript
// lib/github.ts import { Octokit
M

Written by Miraz Ahmed

Full-stack developer and UI designer crafting beautiful digital experiences. Specializing in React, Next.js, and modern web technologies.

Share