Skip to content

makecolour/Inkspired

Β 
Β 

Repository files navigation

Inkspired Blog

PRs Welcome code style: prettier Tested with Vitest Deploy with Vercel

A modern, bilingual blog platform built with Next.js, Tailwind CSS, and MDX. Perfect for creators, developers, and writers who want a lightweight, customizable blogging solution with Vietnamese and English language support.

Write your blog in Markdown with bilingual content support and ship it to everyone on the internet! ✨

  • Framework: Next.js 15 with App Router
  • Deployment: Vercel
  • Styling: Tailwind CSS
  • Content: MDX with metadata
  • Languages: Vietnamese & English with dynamic switching
  • Package Manager: pnpm
Dark Mode Light Mode

Features

  • πŸ“ Write posts in MDX format with YAML frontmatter
  • 🌐 Bilingual support - Vietnamese and English with language switcher
  • πŸ”„ Smart language detection - Auto-detects browser language preference
  • πŸ’Ύ Language persistence - Saves language choice to localStorage
  • πŸ“„ Multilingual blog posts - Support for tagged bilingual content in a single file
  • ⚑ Fast performance with Next.js - all static HTML files, 100% Core Web Vitals
  • πŸ–ΌοΈ Dynamic Open Graph image generation
  • πŸ“° Auto-generated RSS and Atom feeds
  • πŸ—ΊοΈ Automatically generated sitemap
  • πŸ” SEO-friendly with structured data (JSON-LD) and semantic HTML
  • β™Ώ WCAG 2.2 accessibility compliant with proper semantic markup
  • 🎨 Customizable author branding and social links
  • πŸ“± Responsive lightweight design with system-based dark mode

Getting Started

Prerequisites

  • Node.js v18.17 or higher
  • pnpm (recommended) or npm

Installation

  1. Clone the repository:

    git clone https://github.com/yourusername/open-blog.git
    cd open-blog
  2. Copy the environment template and fill in your details:

    cp .env.example .env.local
  3. Edit .env.local with your personal information:

    NEXT_PUBLIC_SITE_URL=https://yourblog.com/
    NEXT_PUBLIC_SITE_NAME=Your Blog Name
    NEXT_PUBLIC_SITE_DESCRIPTION=Your blog description
    NEXT_PUBLIC_AUTHOR_NAME=Your Name
    NEXT_PUBLIC_AUTHOR_EMAIL=[email protected]
    NEXT_PUBLIC_AUTHOR_IMAGE_URL=https://github.com/yourusername.png
    NEXT_PUBLIC_GITHUB_URL=https://github.com/yourusername/
    NEXT_PUBLIC_LINKEDIN_URL=https://www.linkedin.com/in/yourprofile/
    NEXT_PUBLIC_TWITTER_HANDLE=@yourhandle
    NEXT_PUBLIC_COPYRIGHT_YEAR=2025
  4. Install dependencies:

    pnpm install
  5. Start the development server:

    pnpm dev

    Open http://localhost:3000 to view your blog.

Development Commands

# Start development server
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Lint code
pnpm lint

# Format code
pnpm format
pnpm format:check

Project Structure

Inkspired/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                    # Next.js App Router pages
β”‚   β”‚   β”œβ”€β”€ blog/              # Blog posts directory
β”‚   β”‚   β”‚   β”œβ”€β”€ [slug]/        # Dynamic blog post folders
β”‚   β”‚   β”‚   β”‚   └── page.mdx   # Individual blog post content
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx     # Blog layout wrapper
β”‚   β”‚   β”‚   └── page.tsx       # Blog index page
β”‚   β”‚   β”œβ”€β”€ layout.tsx         # Root layout with LanguageProvider
β”‚   β”‚   β”œβ”€β”€ page.tsx           # Homepage
β”‚   β”‚   └── not-found.tsx      # 404 page
β”‚   β”œβ”€β”€ components/            # React components
β”‚   β”‚   β”œβ”€β”€ bilingual-content.tsx   # Bilingual content components
β”‚   β”‚   β”œβ”€β”€ blog-post-layout.tsx    # Blog post wrapper with "Back" link
β”‚   β”‚   β”œβ”€β”€ footer.tsx              # Footer with translations
β”‚   β”‚   β”œβ”€β”€ header.tsx              # Header with language switcher
β”‚   β”‚   β”œβ”€β”€ language-switcher.tsx   # Language toggle button
β”‚   β”‚   └── ...                     # Other components
β”‚   β”œβ”€β”€ contexts/              # React contexts
β”‚   β”‚   └── language-context.tsx    # Language state management
β”‚   β”œβ”€β”€ locales/               # Translation files
β”‚   β”‚   β”œβ”€β”€ en.json            # English UI translations
β”‚   β”‚   └── vi.json            # Vietnamese UI translations
β”‚   β”œβ”€β”€ lib/                   # Utility functions
β”‚   β”‚   β”œβ”€β”€ blog.ts            # Blog metadata helpers
β”‚   β”‚   └── utils.ts           # Common utilities
β”‚   └── styles/                # Global styles
β”‚       └── globals.css        # Tailwind CSS imports
β”œβ”€β”€ mdx-components.tsx         # MDX component overrides
└── .env.local                 # Environment variables

Language System Architecture

UI Translations

All UI strings are stored in JSON files (src/locales/en.json and src/locales/vi.json). Components use the useLanguage() hook to access translations:

import { useLanguage } from "@/contexts/language-context";

function MyComponent() {
  const { t } = useLanguage();
  return <button>{t.nav.home}</button>;
}

Language Context

The LanguageProvider wraps the entire app and provides:

  • Current language state (en | vi)
  • Language switcher function
  • Translations object
  • Auto-detection of browser language
  • LocalStorage persistence

Bilingual Blog Content

Blog posts can include content in both languages using tagged components. The content automatically switches based on the selected language without page reload.

Development Commands

# Start development server
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Lint code
pnpm lint

# Format code
pnpm format

### Single-Language Posts

1. Create a new directory in `src/app/blog/`:

   ```bash
   mkdir src/app/blog/my-first-post
  1. Add a page.mdx file with frontmatter:

    ---
    title: "My First Post"
    description: "A brief description of the post"
    date: 2024-01-15
    ---
    
    Your content here...
  2. The post will automatically appear on your blog at /blog/my-first-post/

Bilingual Posts

For posts with Vietnamese and English content, use the bilingual components:

  1. Add Vietnamese metadata to frontmatter:

    ---
    title: "My First Post"
    titleVi: "BΓ i viαΊΏt Δ‘αΊ§u tiΓͺn cα»§a tΓ΄i"
    description: "A brief description of the post"
    descriptionVi: "Mô tả ngắn gọn về bài viết"
    date: 2024-01-15
    ---
  2. Import bilingual components:

    import { T, P, H2, H3, Bilingual } from "@/components/bilingual-content";
  3. Use components for bilingual content:

    <H2 en="Introduction" vi="Giα»›i thiệu" />
    
    <P
      en={<p>This is English content.</p>}
      vi={<p>ĐÒy lΓ  nα»™i dung tiαΊΏng Việt.</p>}
    />
    
    <Bilingual
      en={<ul><li>English list item</li></ul>}
      vi={<ul><li>Mα»₯c danh sΓ‘ch tiαΊΏng Việt</li></ul>}
    />

πŸ“š Check out the bilingual example post for a complete demonstration!

Bilingual Components Reference

  • <T> - Inline bilingual text
  • <P> - Bilingual paragraphs
  • <H2>, <H3>, <H4> - Bilingual headings
  • <Bilingual> - Generic bilingual wrapper for any content
  • <BilingualSection> - For complex multi-element sections

Syntax Highlighting

The blog uses Shiki for beautiful code syntax highlighting. Here are the features you can use in your code blocks:

Basic Code Block

```javascript
console.log("Hello World");
```

Highlight a Single Line

Use // [!code highlight] comment to highlight the line:

```javascript
function hello() {
  console.log("This line is highlighted"); // [!code highlight]
  console.log("Normal");
}
```

Highlight Multiple Lines

Use // [!code highlight:N] where N is the number of lines to highlight:

```javascript
function hello() {
  console.log("Start highlighting"); // [!code highlight:3]
  console.log("This is highlighted");
  console.log("This is also highlighted");
  console.log("Normal");
}
```

Focus on Lines

Use // [!code focus] for a single line or // [!code focus:N] for multiple lines:

```typescript
const [count, setCount] = useState(0); // [!code focus:2]
const [step, setStep] = useState(1);

export function formatDate(date: string) {
  return new Date(date).toLocaleDateString("en-US", { // [!code focus:3]
    year: "numeric",
    month: "short",
  });
}
```

Inline Code

Use backticks for inline code: `const x = 10;`

License

MIT License - feel free to use this project for any purpose. Attribution is appreciated!

Support

For issues, feature requests, or questions, please open an issue on GitHub.

About

Open Blog - A minimal lightweight blogging platform for developers

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 83.2%
  • MDX 12.1%
  • CSS 3.9%
  • JavaScript 0.8%