Github: Project Titan


  • [ ] Custom Post Route
  • [ ] Post Translation
  • [x] Language Selector


  1. Fork and STAR it, please.
  2. Clone it locally
  3. npm install or yarn
  4. npm run dev or yarn dev


Post Header

Similar to YAML Header in Karmdown

YAML Header is required for all posts.

For post file posts/ with below YAML Header:

title: 'Post Title' // (Required)
categories: 'Life'  // (Optional)
date : '2017-05-19' // (Required) 
tags: ['A', 'B'] // (Optional) 
color?: "primary" | "secondary" // (Optional) Determines the color in post list, default to grey 

Will be routed as

/Life/2017/05/19/jekyllmarkdowntoc.html  // Avaiable on prod only

Post Content

Check the files in /posts then you may understand everything.

Implements with react-markdown

You can custom the renderer in file components\MarkdownRenderer.tsx

You don't need to care about it, at all.

It may show the lightbox on click of a image in any post.

Lightbox Example
Lightbox Example

Implements with react-image-lightbox

Code Highlighter

You don't need to care about it, at all.


  const a = 100;
  const f = (v) => v + 5;

Implements with highlight.js

Highlighter Theme

Change the css in _app.tsx:

import "highlight.js/styles/monokai.css";

Table of Content

You don't need to care about it, at all.

A responsive TOC will be automatically rendered in the sidebar.

Responsive TOC
Responsive TOC

Implements with tocbot

TOC Customization

Check the attributes in Sidebar.tsx:

  tocSelector: ".sidebarMid-Toc",
  contentSelector: ".main",
  headingSelector: "h1, h2, h3, h4, h5",
  hasInnerContainers: true,


Add Locale Strings

You can add translation set in locale.ts

export const locale = {
  siteTitle: {
    zh: "泰坦計劃",
    en: "Project Titan",

Display Translation

Usage with translate function translationString:

  textKey: "siteTitle",

Usage with hooks useTranslator:

const Example = (): JSX.Element => {
  const { translate, locale } = useTranslator();

  return <div>{`${translate(locale.siteTitle)}`}</div>;

Set Language

const Example = (): JSX.Element => {
  const { setLanguage } = useTranslator();

  return <div onClick={() => setLanguage("zh")}>Change Language</div>;

Static Pages

Static Pages with React Component

Here is an example of a static page with React components as content:

const About = (): JSX.Element => (
      textKey: "about",
        <Box>JSX Here</Box>

export default About;

Put these code to /pages/about.tsx then NextJS will route it as /about (example)

See more about Dynamic Routes

Static Pages With Markdown

Here is an example of a static page with pure markdown as content:

const markdown = `
# Title

# Title?

## Title!

## Title~

### Title-

const CustomPage = (): JSX.Element => (
        <MarkdownRenderer content={markdown} />

export default CustomPage;

Migrate From Project Gaia to Project Titan

That is easy to migrate

  1. Provide all posts with valid date in the post header

    title: 'Post Title' // You already have this in Jekyll 
    categories: 'Life' 
    date : '2017-05-19' // Make sure you have this attribute, date should be in format YYYY-MM-DD
    tags: ['A', 'B'] 

  2. NextJS is different from Jekyll, you may need to build before deploy.

    • Run yarn run build or npm run build to create a production version
    • Upload to your pages service
  3. (You can use Github Action, Jenkins for CI/CD or Vercel to simplify the build process)


  • Vercel
  • NextJS
  • Material UI
  • tocbot
  • react-markdown
  • react-image-lightbox
  • Doctor Jones