Mark Ku's Blog
Open in ChatGPTOpen in Claude

歡迎收聽 Mark 的 Tech Insights,我是主持人璦廷。如果只給你一天的時間,你能打造出一個結合最新技術的現代化部落格嗎? 今天的文章記錄了這項挑戰。作者與人工智慧協作,僅花一天就將網站升級到 Next.js 15 架構。這個重點值得注意,新架構不僅提升了載入速度,完善的轉址機制更成功保留了搜尋引擎權重,讓流量迎來六倍的成長。 讓我們來看看最精彩的核心:全自動化的人工智慧內容生成管線。現在,每篇文章都能一鍵生成專屬封面圖、背景音樂與語音摘要。更厲害的是,透過最新的影像生成模型,只要輸入文字描述,就能自動產出技術展示影片,還會自動上傳影音平台來節省空間。 這次改版是內容創作流程的革命。省下繁瑣的製圖與剪輯時間,創作者能專注於文章本身。這不禁讓我們思考:當人工智慧為我們代勞了基礎工作,您的下一步,想創造什麼樣的獨特價值呢?

Introduction

This blog has been with me for nearly five years and has gone through two major redesigns. The first version was a static blog I built myself with Gatsby + MDX. This time, for the second redesign, I aimed higher: rebuilding it with the modern Next.js 15 and integrating a complete AI generation pipeline.

Early this year, I decided to get started. I also set a challenge for myself: to build the core architecture of the new blog in a single day, collaborating with Claude Code AI.

The result? I actually did it. This post is a complete record of the redesign, covering the pain points of the old site, the design decisions for the new architecture, the hands-on experience of developing with AI, and the full process of integrating Vertex AI Veo 3.1 to generate a showcase video.


1. Old Site's Tech Stack: What Were the Pain Points?

The first version of the blog used Gatsby + gatsby-theme-flexiblog. Articles were written in MDX format and stored directly in a Git repository, with Gatsby statically generating pages at build time. It was quite modern at the time, but after a few years, more and more problems emerged.

First, theme customization was limited. gatsby-theme-flexiblog uses a system called Theme Shadowing for customization. While you could override components, the overall design style was basically fixed. Trying to make significant layout changes or add new interactive elements always felt like a battle against the theme's underlying structure. Changing one small thing could mean digging through several layers of source code.

Next was the maintenance burden of the Gatsby ecosystem. To be honest, Gatsby's position in the React ecosystem has largely been taken over by Next.js. Plugin version conflicts, a complicated GraphQL data layer, and occasional build failures made the maintenance cost increasingly high. Every upgrade was a nerve-wracking experience.

Finally, MDX support wasn't great. Integrating custom components was cumbersome, and syntax highlighting for code blocks required configuring a bunch of plugins. Want to embed an interactive component or a video player in an article? The amount of setup required would make you want to give up.


2. New Site's Tech Stack: What Problems Did It Solve?

The new site uses the following tech stack, and has accumulated 244 articles to date:

AspectTechnology Choice
FrameworkNext.js 15 + React 19
LanguageTypeScript
StylingTailwind CSS 4
BundlerTurbopack (default)
Content FormatMDX (parsed with gray-matter)
DeploymentVercel
CommentsGiscus (GitHub Discussions)
AnalyticsGoogle Analytics 4

MDX-centric Content Architecture

Each article is a separate directory with a very simple structure:

public/content/posts/{handle}/
├── index.mdx          # 文章本文 + frontmatter
├── summary.json       # AI 生成的摘要文字
├── audio/
│   └── summary.mp3   # TTS 語音摘要
├── images/
│   └── cover.webp    # AI 生成封面圖
└── videos/
    └── demo.mp4      # AI 生成展示影片

The frontmatter defines all of the article's metadata: title, date, category, tags, thumbnail path, as well as multimedia fields like video and audio URLs.

Seamless Migration with SEO 301 Redirects

The biggest fear with a redesign is having all the old URLs result in 404s, wiping out years of accumulated SEO rankings overnight. So, I designed a 301 redirect mechanism:

舊 URL: /my-post-slug
    ↓  middleware.ts 攔截(Edge Runtime)
    ↓  查詢 redirect-map.json
新 URL: /post/my-post-slug  (HTTP 301)

Each article's frontmatter has a oldSlug field to record the old path. Before the build, generate-redirect-map.mjs automatically scans all articles and generates a lookup table, redirect-map.json:

{
  "/my-old-slug": "/post/my-new-handle"
}

middleware.ts intercepts requests in the Edge Runtime, looks up the table, and returns a 301. It also performs a case-insensitive comparison (since some URLs on the old platform used mixed case). All 246 migrated articles' old links are seamlessly redirected, fully preserving their accumulated search engine authority.

App Router + Static Generation

The App Router in Next.js 15 makes route organization more intuitive. generateStaticParams pre-generates all article pages at build time, resulting in a first-paint load speed far superior to the old platform.

Turbopack Developer Experience

With the old Webpack setup, starting the dev server for a large project took several seconds. After switching to Turbopack, Fast Refresh is nearly 10 times faster. Changes to components are reflected almost instantly, making the developer experience so much better.


3. AI-Automated Content Generation Pipeline

The biggest differentiator for the new blog is this AI media generation pipeline. All scripts run locally and offline (saving API costs and avoiding Vercel timeouts), and the generated assets are committed directly to Git as static resources.

Cover Image Generation (Gemini Image)

npm run generate-post-cover -- --handle migrate-blog-with-ai

The script reads the article's title and category, has gemini-2.5-flash generate an image prompt, and then uses gemini-3.1-flash-image-preview to create a 16:9 tech-style cover image. Each category has a corresponding color scheme—purple for AI, blue for Frontend, green for DevOps—creating a visually consistent look.

AI Audio Summary (Gemini + VoAI Offline TTS)

npm run generate-audio -- --handle migrate-blog-with-ai

The script uses Gemini to generate a 350-500 word summary and podcast script in Traditional Chinese for each article, then synthesizes an mp3 audio file offline using VoAI.

VoAI is an AI voice synthesis tool developed locally in Taiwan. It supports Traditional Chinese and offers a variety of natural-sounding voices, delivering a smooth and fluent Chinese AI voiceover experience.

Background Music (Google Lyria)

npm run generate-music

I use Google's Lyria music generation model to create background music suitable for a reading environment. The music style is described by an AI music curator persona named "Melody."

Category Icons and Banners

Each of the 22 article categories has an iOS-style icon and banner, all generated by the Gemini image model, resulting in a very consistent style.


4. Vertex AI Veo 3.1: Generating a Tech Showcase Video with AI

This is the key technology highlighted in this post: using Google Vertex AI's veo-3.1-generate-001 model to generate video directly from a text prompt.

Why do this?

Pairing technical articles with videos can certainly help readers understand the content better. But honestly, the cost of recording and editing is high; just setting up screen recording software takes a significant amount of time. Veo 3.1 allows me to generate a pretty decent tech architecture showcase video from just a text description—no screen recording, no editing software needed.

How to Call the Veo 3.1 API

Veo 3.1 uses Vertex AI's Long-running Operation model because video generation takes a considerable amount of time:

// 1. 發起生成請求
const response = await fetch(
  `https://us-central1-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/veo-3.1-generate-001:predictLongRunning`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      instances: [{
        prompt: "A cinematic visualization of a modern Next.js 15 blog architecture: data flowing from MDX files through gray-matter parsing, through React Server Components, rendered as a beautiful dark-themed blog. Indigo and teal color scheme, technical diagram style with glowing nodes and connecting lines."
      }],
      parameters: {
        aspectRatio: "16:9",
        sampleCount: 1,
        durationSeconds: 8,
        generateAudio: false,
      }
    })
  }
)

// 2. 取得 operation name
const { name: operationName } = await response.json()

// 3. 輪詢等待完成
let result
while (true) {
  const pollResponse = await fetch(
    `https://us-central1-aiplatform.googleapis.com/v1/${operationName}`,
    { headers: { 'Authorization': `Bearer ${accessToken}` } }
  )
  result = await pollResponse.json()
  if (result.done) break
  await sleep(10000) // 每 10 秒輪詢一次
}

// 4. 取出影片 base64 並存檔
const videoBase64 = result.response.videos[0].bytesBase64Encoded
fs.writeFileSync(outputPath, Buffer.from(videoBase64, 'base64'))

The generate-video.mjs script

scripts/generate-video.mjs integrates the entire generation process:

# 為指定文章生成展示影片(從文章標題與描述自動生成 prompt)
npm run generate-video -- --handle migrate-blog-with-ai

# 指定自訂 prompt
npm run generate-video -- --handle migrate-blog-with-ai --prompt "Modern blog architecture visualization"

# 強制重新生成
npm run generate-video -- --handle migrate-blog-with-ai --force

The script's job is simple: it reads the article's title and description, uses Gemini to translate the Chinese title into an English visual prompt suitable for Veo, calls the API, polls for completion, and finally saves the .mp4 to public/content/posts/{handle}/videos/architecture-demo.mp4.

Video Too Big? Auto-Upload to YouTube

Videos generated by Veo 3.1 can easily be 10-20MB. If stored directly in the Git repository, the repo would bloat quickly. Therefore, generate-video-youtube.mjs has a built-in file size check: if a video exceeds 5MB, it's automatically uploaded to YouTube and the local file is deleted.

# 自動判斷:影片 > 5MB 就上傳 YouTube,並刪除本地檔案
npm run generate-video-youtube -- --handle migrate-blog-with-ai

# 批次處理最近 5 篇文章
npm run generate-video-youtube:recent -- 5

# 強制重新生成並上傳(即使已有 YouTube URL)
npm run generate-video-youtube -- --handle migrate-blog-with-ai --force

The process is roughly as follows: first, call generate-video.mjs to generate the video. Check the file size. If it's over 5MB, upload it via the YouTube Data API v3, then automatically update the frontmatter's videoUrl to the YouTube URL, and finally delete the local video file. This way, the video is hosted by YouTube's CDN, and the Git repository only stores the YouTube URL, preventing the repo from getting bloated by AI-generated videos.

Embedding Videos in Articles

Just add videoUrl to the frontmatter:

videoUrl: "https://www.youtube.com/watch?v=tTQklpzEEzk"
scrollAutoPlay: false

The blog's video component automatically handles path resolution, supporting both local .mp4 and YouTube URL formats.


5. Results and Future Plans

Traffic grew from 10,000 to 60,000 visits per year, a 6x increase. This isn't just an effect of the redesign itself; it's a direct result of search engines awarding higher rankings after improvements to SEO structure and loading speed.

The Biggest Takeaway

Honestly, the biggest takeaway isn't just a better-looking blog, but a reusable AI content generation infrastructure. The cover image, audio summary, and showcase video for each new article can be generated with a single command. This has significantly lowered the barrier to writing—what used to take half an hour just to create a cover image is now done with a single line in the terminal.

What's Next

  • Use Veo 3.1 in more scenarios, like tutorial animations or dynamic architecture diagrams.
  • Experiment with Gemini's multimodal capabilities, for example, by feeding it screenshots to automatically generate descriptive text.
  • Build a RAG knowledge base so readers can ask questions directly about the blog's content.

Building this new blog in a day wasn't the end, but a new beginning.

AI tools allowed me to compress what would have been a week's work into a single day. The time saved can now be spent on a more valuable question: What should I write about next?

Author

Mark Ku

擁有 10+ 年經驗的資深軟體工程師,現為 AI 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。Read More

Found this useful?

The author's free tools, daily podcasts and newsletter are all here.

Mark Ku · This article is licensed under CC BY 4.0. Credit the author and link back to the original when reusing it.

Comments

Subscribe to Newsletter

Subscribe to get new posts delivered instantly — never miss a tech share.

By submitting, you agree to receive emails. You can anytime.

Popular Posts

View all
Mark Ku
··602

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution
Mark Ku
··490

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.
Mark Ku
··333

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki
Mark Ku
··264

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning
Mark Ku
··221

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1
Mark Ku
··215

Setting Up Samba on Ubuntu to Share Folders with Windows 11

Setting Up Samba on Ubuntu to Share Folders with Windows 11
用 AI 打造全新技術部落格:從舊架構到 Next.js 15 的完整改版歷程 - Mark Ku's Tech Notes