Skip to content

[EN]: improve the website of 1024techcamp #67

@Nliver

Description

@Nliver

Execute the following tasks exclusively on the blog branch to enable seamless GitHub Pages deployment:

  1. Directory Restructuring & Migration

    • Migrate all Markdown source files from ./2025/ into the repository’s unified posts directory (e.g., _posts/), preserving front matter and content integrity.
    • Update all internal references (navigation, archives, RSS feeds) to reflect new paths.
    • After successful build verification, permanently delete the ./2025/ directory.
  2. Slug Standardization

    • For every post (including migrated 2025 content):
      • Auto-translate non-English slugs (or title-derived slugs) into clear, SEO-friendly English.
      • Enforce kebab-case formatting: lowercase, hyphen-separated words (e.g., future-of-ai-in-2025).
      • Guarantee slug uniqueness; update all intra-site links referencing old slugs.
    • Implementation note: Integrate a translation fallback (e.g., transliteration library like unidecode + manual mapping file) if API-based translation is infeasible. Document the method used.
  3. Edit Path Unification

    • Modify theme/templates to set all "Edit this page" links to target the blog branch and unified directory structure:
      https://github.com/<owner>/<repo>/edit/blog/_posts/{filename}.md
    • Remove hardcoded paths containing /2025/ or references to other branches.
  4. Deployment Validation

    • Confirm GitHub Pages is configured to deploy from the root of the blog branch.
    • Locally build the site (using the project’s SSG) and verify:
      ✓ All 2025 articles render correctly with new slugs
      ✓ Archives/indexes include 2025 content
      ✓ Zero broken links or path errors
      ✓ Edit links resolve to correct blog-branch paths
  5. Final Commit Protocol

    • Commit changes incrementally with descriptive messages (e.g., "feat: migrate 2025 posts to _posts/", "fix: standardize slugs to kebab-case").
    • Only after validation, commit the deletion of ./2025/.
    • Ensure .nojekyll (if required) and _config.yml (baseurl, permalink settings) are optimized for GitHub Pages.

⚠️ Critical Constraints

  • Preserve all article content, dates, and non-slug metadata.
  • Do not alter deployment configuration for other branches.
  • All changes must reside solely within the blog branch workflow.
  • Translation must prioritize readability and URL safety over literal accuracy.

This specification ensures full compatibility with GitHub Pages while maintaining content integrity and editorial workflow clarity. 🌐✨

Docusaurus Article Migration & Tag Configuration Request


🎯 Objective

Migrate all articles from the 2025 directory under the blog branch into the Docusaurus-based website, automatically configure associated tags and metadata, and auto-translate article slugs to English using kebab-case (- separator).


📁 Scope

  • Source: blog/2025/ directory (all article files)
  • Destination: Docusaurus website/ structure
  • Assumption: Articles are in Markdown/MDX format with potentially non-English titles

Required Actions

1. Article Migration to Docusaurus Structure

Determine Content Type:

  • If articles are blog posts: migrate to website/blog/ directory
  • If articles are documentation: migrate to website/docs/ directory with appropriate sidebar placement

File Naming Convention:

YYYY-MM-DD-english-slug.md

Example: 2025-01-15-getting-started-with-ai.md


2. Automatic Slug Translation

Slug Generation Workflow:

/**
 * Generate English slug from article title
 * @param {string} originalTitle - Original article title (may be non-English)
 * @returns {string} English slug in kebab-case
 */
async function generateEnglishSlug(originalTitle) {
  // Step 1: Extract title from frontmatter or first heading
  const title = extractTitle(originalTitle);
  
  // Step 2: Translate to English
  const englishTitle = await translateToEnglish(title);
  
  // Step 3: Convert to kebab-case slug
  return toKebabCase(englishTitle);
}

/**
 * Translate text to English
 * Options: DeepL API, Google Translate API, or local dictionary fallback
 */
async function translateToEnglish(text) {
  // Option A: DeepL API (recommended for accuracy)
  // const response = await fetch('https://api-free.deepl.com/v2/translate', {
  //   method: 'POST',
  //   headers: { 'Authorization': `DeepL-Auth-Key ${DEEPL_API_KEY}` },
  //   body: new URLSearchParams({
  //     text: text,
  //     target_lang: 'EN'
  //   })
  // });
  // return await response.json().translations[0].text;
  
  // Option B: Google Translate API
  // const { Translate } = require('@google-cloud/translate').v2;
  // const translate = new Translate();
  // const [translation] = await translate.translate(text, 'en');
  // return translation;
  
  // Option C: Local dictionary fallback for common terms
  const dictionary = {
    '介绍': 'introduction',
    '指南': 'guide',
    '教程': 'tutorial',
    '最佳实践': 'best-practices',
    '入门': 'getting-started',
    '高级': 'advanced',
    '配置': 'configuration',
    '部署': 'deployment',
    // ... extend as needed
  };
  
  // Simple replacement for known terms
  let translated = text;
  Object.entries(dictionary).forEach(([cn, en]) => {
    translated = translated.replace(cn, en);
  });
  
  return translated;
}

/**
 * Convert string to kebab-case slug
 */
function toKebabCase(str) {
  return str
    .toLowerCase()                           // lowercase
    .normalize('NFD')                        // normalize unicode
    .replace(/[\u0300-\u036f]/g, '')         // remove diacritics
    .replace(/[^a-z0-9]+/g, '-')             // replace non-alphanumeric with -
    .replace(/^-+|-+$/g, '')                 // trim leading/trailing -
    .replace(/-+/g, '-');                    // collapse multiple -
}

Slug Format Rules:

Rule Example
Lowercase only getting-started
Hyphen separator machine-learning-guide
No special characters getting_started! → ✅ getting-started
Trim leading/trailing hyphens -guide- → ✅ guide
Collapse multiple hyphens getting--started → ✅ getting-started

3. Docusaurus Frontmatter Standardization

Update each article's frontmatter with translated slug:

For Blog Posts (website/blog/):

---
slug: /blog/getting-started-with-ai        # ← Auto-translated English slug
title: "AI入门指南"                          # ← Original title preserved
authors: [author1, author2]
tags: [ai, machine-learning, tutorial]
date: 2025-01-15
description: "本文介绍如何开始学习人工智能"
image: /img/og-image.png
hide_table_of_contents: false
---

For Documentation (website/docs/):

---
sidebar_position: 1
sidebar_label: "AI入门指南"
title: "AI入门指南"
description: "本文介绍如何开始学习人工智能"
slug: /docs/getting-started-with-ai        # ← Auto-translated English slug
tags: [ai, machine-learning, tutorial]
---

4. Configure Blog Plugin (if using blog posts)

Update docusaurus.config.js:

module.exports = {
  // ...
  presets: [
    [
      '@docusaurus/preset-classic',
      {
        blog: {
          path: './blog',
          routeBasePath: '/blog',
          blogTitle: 'Blog',
          blogDescription: 'Technical articles and updates',
          postsPerPage: 10,
          blogSidebarTitle: 'All posts',
          blogSidebarCount: 'ALL',
          feedOptions: {
            type: 'all',
            copyright: `Copyright © ${new Date().getFullYear()} Your Company`,
          },
        },
        // ...
      },
    ],
  ],
  // ...
};

5. Automatic Tag Extraction & Assignment

Option A - Content-based Tag Extraction:

// Pseudo-logic for tag extraction
const extractTags = (content) => {
  const keywords = extractKeywords(content);
  const predefinedTags = ['ai', 'machine-learning', 'web-development', 'cloud', 'devops', 'javascript', 'react', 'typescript'];
  
  return keywords
    .filter(k => predefinedTags.includes(k))
    .slice(0, 5); // Max 5 tags per article
};

Option B - Category-based Mapping:

const tagMapping = {
  'machine-learning': ['ai', 'machine-learning', 'data-science'],
  'web-dev': ['web-development', 'javascript', 'frontend'],
  'cloud-infrastructure': ['cloud', 'aws', 'devops'],
  // ... extend based on article topics
};

6. Sidebar Configuration (for docs)

Update sidebars.js with translated slugs:

module.exports = {
  docs: [
    {
      type: 'category',
      label: '2025 Articles',
      collapsed: false,
      items: [
        '2025/getting-started-with-ai',           // ← Translated slug
        '2025/machine-learning-best-practices',   // ← Translated slug
        '2025/cloud-deployment-guide',            // ← Translated slug
        // ... auto-generate from migrated files
      ],
    },
    // ... existing sidebar items
  ],
};

7. Migration Script

Create scripts/migrate-articles.js:

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const matter = require('gray-matter');

// Configuration
const SOURCE_DIR = './blog/2025';
const DEST_DIR = './website/blog';
const TAG_DICTIONARY = require('./tag-dictionary.json');

async function migrateArticles() {
  const files = fs.readdirSync(SOURCE_DIR).filter(f => f.endsWith('.md'));
  
  for (const file of files) {
    const sourcePath = path.join(SOURCE_DIR, file);
    const content = fs.readFileSync(sourcePath, 'utf8');
    const { data: frontmatter, content: body } = matter(content);
    
    // Generate English slug
    const englishSlug = await generateEnglishSlug(frontmatter.title || file);
    
    // Extract tags
    const tags = extractTags(body, frontmatter.tags);
    
    // Build new frontmatter
    const newFrontmatter = {
      slug: `/blog/${englishSlug}`,
      title: frontmatter.title || extractTitleFromContent(body),
      date: frontmatter.date || extractDateFromFile(file),
      tags: tags,
      description: frontmatter.description || generateDescription(body),
      ...(frontmatter.authors && { authors: frontmatter.authors }),
    };
    
    // Write to destination
    const destFile = `${formatDate(newFrontmatter.date)}-${englishSlug}.md`;
    const destPath = path.join(DEST_DIR, destFile);
    
    const output = matter.stringify(body, newFrontmatter);
    fs.writeFileSync(destPath, output);
    
    console.log(`✓ Migrated: ${file}${destFile}`);
  }
}

// Helper functions
function formatDate(date) {
  return new Date(date).toISOString().split('T')[0];
}

function extractTags(content, existingTags = []) {
  // Implement tag extraction logic
  return [...new Set([...existingTags, ...autoExtractTags(content)])];
}

migrateArticles().catch(console.error);

8. Tag Index Page Generation

Create a tags overview page at website/docs/tags.md:

---
sidebar_position: 99
title: Tags
description: Browse articles by tag
---

# Tags

Browse all articles organized by tags:

- [AI](#ai)
- [Machine Learning](#machine-learning)
- [Web Development](#web-development)
- [Cloud](#cloud)
- [DevOps](#devops)

<!-- Auto-generate tag sections with filtered article lists -->

9. Authors Configuration (Optional)

If using authors field, configure in docusaurus.config.js:

module.exports = {
  // ...
  presets: [
    [
      '@docusaurus/preset-classic',
      {
        blog: {
          // ...
          authorsMapPath: './authors.yml',
        },
      },
    ],
  ],
};

Create website/blog/authors.yml:

author1:
  name: John Doe
  title: Senior Engineer
  url: https://github.com/johndoe
  image_url: https://github.com/johndoe.png

author2:
  name: Jane Smith
  title: Technical Writer
  url: https://github.com/janesmith
  image_url: https://github.com/janesmith.png

📤 Expected Output

  1. Migrated Files: List of all articles with new paths and English slugs
  2. Slug Translation Report: Mapping of original titles → English slugs
  3. Updated Frontmatter: Sample before/after for representative articles
  4. Configuration Updates: Modified docusaurus.config.js, sidebars.js, migration script
  5. Tag Summary Report: All unique tags extracted and their article counts

🧪 Verification Commands

# Install dependencies
npm install gray-matter

# Run migration script
node scripts/migrate-articles.js

# Install Docusaurus dependencies
cd website
npm install

# Build the site
npm run build

# Start local dev server
npm run start

# Verify:
# - Blog posts visible at http://localhost:3000/blog
# - Slugs are in English kebab-case format
# - Tags displayed correctly on each post

📋 Slug Translation Examples

Original Title English Slug
AI入门指南 getting-started-with-ai
机器学习最佳实践 machine-learning-best-practices
云原生部署教程 cloud-native-deployment-tutorial
前端性能优化技巧 frontend-performance-optimization-tips
React Hooks详解 react-hooks-explained

💡 Notes

  • All modifications apply only to the blog branch
  • Preserve original article content and title; only modify slug and frontmatter
  • If translation API is unavailable, use local dictionary fallback with manual review
  • Consider adding a slug_mapping.json file to track original → translated slug mapping for reference
  • For large volumes of articles, batch translation with rate limiting is recommended

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions