DEV Community

Takuya Niioka
Takuya Niioka

Posted on • Originally published at takuyaniioka.com

Building an Automated Bilingual Blog System with Obsidian: Going Global in Two Languages

Introduction: Why I Built This System

For 9 years since joining the company, I've worked as an engineer in the AD/ADAS field. While I accumulated expertise, I felt it was a career risk that my work wasn't visible outside the company and had zero recognition in the global market.

Expertise might as well not exist if it isn't visible.

Then I realized: Nothing will change unless I put myself out there.

However, I faced the following challenges:

  • Lack of time: With a full-time job, I couldn't dedicate 10 hours per week to blogging
  • Difficulty maintaining: Manual posting is cumbersome and leads to quick abandonment
  • Global reach: Japanese-only content has limitations; English content is also necessary

In this article, I'll introduce the bilingual automated blog posting system I built that costs only $10.18 per year to operate.


What This System Can Achieve

Key Features

Write article (Obsidian) → One button → Distribute worldwide

Specifically:

  • Write in Japanese → Auto-generate English version via AI translation
  • Automatic SEO optimization
  • Auto-publish to custom domain blog
  • Auto-generate LinkedIn posts
  • Prepare for distribution to Medium, Dev.to, etc.
  • Automatic Google Analytics tracking

Time required: Within 5 minutes (excluding article writing)
Annual cost: $10.18 (domain fee only)

Challenges Solved

Before (Pre-System Build)

3 hours to publish one article:

  • Writing in Obsidian: 2 hours
  • Manual HTML conversion: 20 minutes
  • Image optimization: 15 minutes
  • SEO configuration: 15 minutes
  • GitHub push: 10 minutes
  • Deploy verification: 10 minutes
  • LinkedIn post creation: 30 minutes
  • English translation: 1 hour (outsourced or self-translated)

Total: 4-5 hours
→ Impossible to publish 2 articles per week
→ Gave up

After (Post-System Build)

1 hour to publish one article:

  • Writing in Obsidian: 50 minutes
  • Run automation script: 5 minutes → AI translation → SEO optimization → Image optimization → Automatic GitHub push → Automatic Cloudflare deployment → Auto-generate LinkedIn post
  • Final check: 5 minutes

Total: 1 hour
→ Possible to publish 2 articles per week
→ Sustainable


System Architecture

Overall System Diagram

graph TD
    subgraph Writing["Writing Environment (Obsidian)"]
        A[Write Articles in Markdown] --> B[Core Vault]
        B --> C[Blog Vault]
    end

    subgraph Automation["Automation Layer (Python + AI)"]
        C --> D[AI Translation<br/>Claude API]
        D --> E[SEO Optimization<br/>Auto Description Generation]
        E --> F[Quality Check<br/>AI Analysis]
        F --> G[Hugo Static Site Generation]
    end

    subgraph Deploy["Deployment & Delivery"]
        G --> H[GitHub Repository]
        H --> I[Cloudflare Pages<br/>Auto Build]
        I --> J[Custom Domain Blog<br/>CDN Delivery]
    end

    subgraph SNS["Social Media Distribution"]
        G --> K[LinkedIn Post Generation]
        K --> L[LinkedIn API Posting]
        G --> M[Medium/Dev.to<br/>Distribution Prep]
    end

    subgraph Analytics["Analytics"]
        J --> N[Google Analytics GA4]
    end

    J --> O((Readers))
    L --> O
    M --> O

    style A fill:#DCE7FF,stroke:#333
    style D fill:#FFE6CC,stroke:#333
    style E fill:#FFE6CC,stroke:#333
    style F fill:#FFE6CC,stroke:#333
    style I fill:#ADD8E6,stroke:#333
    style J fill:#90EE90,stroke:#333
    style O fill:#FFB6C1,stroke:#333
Enter fullscreen mode Exit fullscreen mode

Technology Stack

Category Technology Role Cost
Writing Obsidian Markdown article creation, knowledge production core Free
SSG Hugo Static site generation (Markdown→HTML) Free
AI Claude API Translation, quality check, SEO optimization $5-10/month
Hosting Cloudflare Pages Auto deployment & CDN delivery Free
Version Control GitHub Source control & CI/CD Free
Domain NameCheap Custom domain $10.18/year ✅
DNS Cloudflare DNS management & email forwarding Free
SNS API LinkedIn API Auto posting Free
Analytics Google Analytics Access tracking Free

Total Annual Cost: $10.18 + API usage $60-120 = $70.18-130.18 (approximately ¥10,000)


Core Implementation: 5 Stages

Stage 1: Draft

Purpose: Review and modify articles locally

draft.bat

# Or include English translation simultaneously
draft_translate.bat
Enter fullscreen mode Exit fullscreen mode

Process:

  1. Retrieve articles from Obsidian (Core Vault)
  2. Automatically convert to Hugo format
  3. Save with draft: true (private)
  4. Auto-launch Hugo server
  5. Open http://localhost:1313 in browser

At this stage:

  • No GitHub push
  • Multiple revisions and previews possible
  • Completely local process

AI Translation Feature:

# translate_article.py (excerpt)
def translate_with_claude(japanese_text):
    """Translate Japanese to English using Claude API"""
    prompt = f"""
    Please translate the following technical article to English:
    - Use appropriate technical terms
    - Natural, readable English
    - Preserve Markdown formatting

    {japanese_text}
    """
    # Call Claude API
    response = call_claude_api(prompt)
    return response
Enter fullscreen mode Exit fullscreen mode

Stage 2: Quality Check

Purpose: Perform AI-based article quality analysis

check.bat
Enter fullscreen mode Exit fullscreen mode

Check Items:

  • Detection of omitted subjects (Japanese-specific issue)
  • Detection of logical gaps
  • Abstract-to-concrete correspondence
  • Detection of ambiguous expressions
  • Accuracy of technical terms
  • SEO improvement suggestions

Output Example:

# Quality Report

## Subject Omission (3 places)
- Line 45: "Built the system" → Who did?
  Suggestion: "I built the system"

## Logic Gaps (2 locations)
- Line 78-82: Gap between Step 2 and Step 3
  Suggestion: Add intermediate steps

## Ambiguous Expressions (5 locations)
- Line 92: "quite fast" → what are the specific numbers?
  Suggestion: "3 times faster (7h → 2h)"

## Overall Rating: 85/100
Can improve to: 90/100
Enter fullscreen mode Exit fullscreen mode

Stage 3: Pre-Publish Optimization

Purpose: Perform SEO optimization and Description auto-generation

# Automatically executed when publish.bat runs
Enter fullscreen mode Exit fullscreen mode

Execution Details:

1. Description Auto-generation (Claude API)

def generate_description(article_text):
    """Generate SEO-optimized summary automatically"""
    prompt = f"""
    Please generate an SEO-optimized summary from the following article.

    Requirements:
    - 120-160 characters
    - Naturally include keywords
    - Capture reader interest
    - Convey article core message

    {article_text}
    """
    description = call_claude_api(prompt)
    return description
Enter fullscreen mode Exit fullscreen mode

2. Automated SEO Check

seo_checks = {
    'title_length': Within 60 characters?,
    'h1_exists': Has H1 tag?,
    'description': Between 120-160 characters?,
    'images': Has alt attributes?,
    'word_count': Minimum 1,500 words?,
    'tags': Has 3-5 tags?,
    'internal_links': Has internal links?
}
Enter fullscreen mode Exit fullscreen mode

3. H1 Handling (Important)

Issue: Hugo theme outputs title as H1
     → Duplicates with H1 in Markdown
     → Bad for SEO

Solution: 
1. Comment out H1 in Markdown
2. Hide with CSS
3. Keep in HTML (for SEO)
Enter fullscreen mode Exit fullscreen mode

Stage 4: Publish

Purpose: Actually publish the article

publish.bat
Enter fullscreen mode Exit fullscreen mode

Execution Flow:

def publish_workflow():
    # 1. Generate description
    description = generate_description(article)

    # 2. SEO automatic check
    seo_result = check_seo(article)
    if not seo_result.passed:
        print("SEO issues found:", seo_result.issues)
        if not confirm("Publish anyway?"):
            return

    # 3. Convert to Hugo format (draft: false)
    convert_to_hugo(article, draft=False)

    # 4. Save Japanese and English versions
    save_bilingual_articles(article_ja, article_en)

    # 5. Automatic Git push
    git_push_with_message(f"Publish: {article.title}")

    # 6. Generate LinkedIn posts
    generate_linkedin_posts(article)

    print("✅ Publishing complete!")
    print(f"Japanese: https://takuyaniioka.com/ja/posts/{slug}/")
    print(f"English: https://takuyaniioka.com/posts/{slug}/")
Enter fullscreen mode Exit fullscreen mode

Post-publish Auto-deployment:

GitHub Push
    ↓ (Webhook)
Cloudflare Pages Detection
    ↓
Hugo Auto-build (about 30 seconds)
    ↓
CDN Distribution
    ↓
Blog Published
Enter fullscreen mode Exit fullscreen mode

Stage 5: Social Media (LinkedIn)

Purpose: Automatically generate LinkedIn posts from articles

linkedin_post.bat
Enter fullscreen mode Exit fullscreen mode

This system can automatically generate LinkedIn posts from articles. We plan to modify the design in the future to allow manual editing and posting as needed.

Stage 6: Analytics

Google Analytics GA4 Integration:

# BlogVault/config.toml
[params]
  googleAnalytics = "G-XXXXXXXXXX"
Enter fullscreen mode Exit fullscreen mode

Tracking Data:

  • Real-time access
  • Traffic sources (LinkedIn, Medium, Google etc.)
  • Popular article rankings
  • Device and region statistics
  • Time on site and bounce rate

Design Philosophy: Why This Architecture?

1. Obsidian-Centric Approach

Reasons:

  • Second Brain: Core of my intellectual productivity
  • Unified Management: Articles and notes, all managed in Obsidian
  • Prevent Thought Fragmentation: Information is not scattered

Structure:

Obsidian/
├── Core Vault/          # Private & intellectual production
│   ├── Daily Notes/
│   ├── Projects/
│   └── Articles/        # Article drafts
│
└── Blog Vault/          # Public & blog-specific
    ├── content/
    ├── static/
    └── config.toml
Enter fullscreen mode Exit fullscreen mode

Reasons for Separation:

  • Core Vault is private (personal notes & confidential information)
  • Blog Vault is public (pushed to GitHub)
  • Maintains clear boundaries

2. AI Utilization Philosophy

AI is "Augmentation" not "Replacement"

[Wrong Usage]
Let AI write everything
→ Zero originality
→ Zero value

[Correct Usage]
Human: Write core insights & experiences
AI: Automate translation, SEO, quality checks

→ Humans focus on intellectual production
→ AI handles repetitive tasks
Enter fullscreen mode Exit fullscreen mode

Concrete Examples:

  • ✅ AI Translation: Think deeply in Japanese, AI translates to English
  • ✅ SEO Optimization: AI auto-generates descriptions
  • ✅ Quality Check: AI provides objective review
  • ❌ Article Writing: Written by humans (AI assists only)

3. Staged Workflow

Why Split into 5 Stages:

Reason 1: Safety

  • Gradual verification instead of immediate publication
  • Detect and fix issues at each stage

Reason 2: Flexibility

  • Can pause at any point
  • Can resume from any stage

Reason 3: Debuggability

  • Clear identification of where problems occur
  • Logs provide immediate clarity

Implementation Details: Core Features

Feature 1: Article Format Conversion

Challenge:

  • Obsidian format (EvolutionVault)
  • Hugo format (BlogVault)
  • Different formats

Solution:

def convert_evolution_to_hugo_format(source_file, draft_mode=True):
    """EvolutionVault format → Hugo format"""

    # 1. Parse YAML frontmatter
    with open(source_file, 'r', encoding='utf-8') as f:
        content = f.read()

    # Separate frontmatter and body
    if content.startswith('---'):
        parts = content.split('---', 2)
        frontmatter = parts[1]
        body = parts[2] if len(parts) > 2 else ""

    # 2. Convert for Hugo
    hugo_frontmatter = convert_frontmatter(frontmatter)
    hugo_frontmatter['draft'] = draft_mode

    # 3. Save
    output_path = get_hugo_path(source_file)
    save_hugo_file(output_path, hugo_frontmatter, body)
Enter fullscreen mode Exit fullscreen mode

Feature 2: Automated SEO Optimization

Challenge:

  • Manual description writing is time-consuming
  • Easy to miss SEO checks

Solution:

def optimize_seo(article):
    """Automated SEO optimization"""

    # 1. Auto-generate description (Claude API)
    description = generate_description_with_ai(article.content)
    article.description = description

    # 2. SEO checklist
    checks = [
        check_title_length(article.title),
        check_description_length(article.description),
        check_h1_tag(article.content),
        check_image_alt_tags(article.content),
        check_word_count(article.content),
        check_tags(article.tags),
        check_internal_links(article.content)
    ]

    # 3. Warning if issues found
    issues = [c for c in checks if not c.passed]
    if issues:
        print("⚠️ SEO issues:")
        for issue in issues:
            print(f"  - {issue.message}")

    return article
Enter fullscreen mode Exit fullscreen mode

Feature 3: Bilingual Support

Challenge:

  • Managing Japanese and English separately is complex
  • Separate URLs needed

Solution:

Utilizing Hugo's multilingual features:

Japanese:
https://takuyaniioka.com/ja/posts/article-slug/

English:
https://takuyaniioka.com/posts/article-slug/

Automatic switching:
- Detects browser language settings
- Japanese browser → /ja/
- English browser → /
Enter fullscreen mode Exit fullscreen mode

Implementation:

# config.toml
[languages]
  [languages.en]
    languageName = "English"
    weight = 1
    contentDir = "content"

  [languages.ja]
    languageName = "日本語"
    weight = 2
    contentDir = "content"

[params]
  defaultContentLanguage = "en"
  defaultContentLanguageInSubdir = false
Enter fullscreen mode Exit fullscreen mode

Results: What This System Delivered

Quantitative Results

Metric Before After Improvement
Writing Efficiency 5 hours/article 1 hour/article 5x faster
Weekly Posts 0-1 posts 2 posts 2x+
Annual Articles 10-20 (including dropouts) 60+ (achievable target) 3-6x
Cost Outsourced translation $50-100/article $10.18/year + API $10/month 95% reduction

How to Build This System

Construction Steps (Overview)

Step 1: Environment Setup (1 hour)

  1. Install Obsidian
  2. Install Hugo
  3. Install Git
  4. Install Python
  5. Create GitHub account
  6. Create Cloudflare account

Step 2: Domain Acquisition (15 minutes)

  1. Get custom domain from NameCheap ($10.18/year)
  2. Configure DNS in Cloudflare
  3. Set up email forwarding (optional)

Step 3: Hugo Setup (30 minutes)

  1. Create Hugo site
  2. Select theme (Hugo Clarity recommended)
  3. Configure config.toml
  4. Set up bilingual settings

Step 4: Cloudflare Pages Setup (15 minutes)

  1. Create GitHub repository
  2. Link to Cloudflare Pages
  3. Configure build settings (Hugo)
  4. Set up custom domain

Step 5: Automation Script Setup (1 hour)

  1. Install Python dependencies
  2. Deploy automation scripts
  3. Create .bat files
  4. Configure Claude API
  5. Run tests

Step 6: First Post Publication (30 minutes)

  1. Write article in Obsidian
  2. Run draft.bat
  3. Check preview
  4. Run publish.bat
  5. Complete publication

Total time required: About 4 hours

Summary: The Essence of This System

  • Time reduction: 5 hours → 1 hour
  • Cost reduction: 95% reduction
  • Multilingual support: Japanese-English automatic
  • Social media deployment: Automated

Resources

Reference Links

GitHub Repository

While it's not currently public, I'm open to considering making it public upon request. The content is expected to include the following structure:

  • Automation scripts
  • Setup guide
  • Troubleshooting
  • FAQ

Top comments (0)