This article discusses the Nobelium framework used by this blog when it was on Notion. The blog has now switched to the Astro framework.
Finding#
In February of this year, I migrated the blog from Typecho to Notion due to server issues, driven by Super.so. To be honest, I wasn't very satisfied overall, mainly for the following three reasons:
- Super.so has not yet provided RSS subscription for blogs. Initially, I used an RSS feed created with rss.com, but found it unstable and unable to output full text; then I switched to fetchrss.com, which could only display full text in some RSS readers; finally, I saw DIYgod's new project, the open-source blog xLog, which solved the RSS issue.
- Super.so also does not integrate a comment feature. Although my blog does not have many comments, there are still some. Even when I found Tally, it was criticized for having a high barrier to entry for readers.
- Super.so is more suitable for building simple websites rather than blogs. Using Notion + Super.so as a CMS is very appropriate, but if you purely want to create a blog, especially when the content increases, the issues of complex and chaotic page management become apparent.
So, I started looking for a blog-driven service that better matches Notion.
There are many projects that use Notion for website building. After filtering, I picked out four: Feather.so, Notablog, NotionNext, and Nobelium.
Feather.so is excellent; you could say that if you want to use Notion as a blog, this is the best driving service. It not only has RSS but also a comment feature, very good SEO optimization, and smooth page management logic... However, good services often come with high prices; I found Super.so at $12 per month expensive, let alone this one at $39 per month.
Notablog is a project I have been following for a long time, open-sourced by a Chinese-American on GitHub. The overall feel is very simple and elegant, and the operation and management logic are clear, making it easy to deploy on a VPS. However, this project has not had much update in the past year.
NotionNext is a project I had previously deployed; I not only wrote articles introducing it but also recommended it to several friends. So far, the developer's updates are still frequent, and it has been diligently maintained. However, the support for Notion Block is not comprehensive, and updating can be a bit troublesome, which is not suitable for someone as lazy as me.
Nobelium, like Notablog and NotionNext, is an open-source project on GitHub, but it differs significantly from the latter two. Notablog is more like a personal website; NotionNext, due to supporting many themes, appears much flashier; Nobelium is a minimalist blog, without fancy rendering, variable themes, or complex features. The ordinary Nobelium gave me a sense of returning to simplicity; isn't that what a personal blog should be?
Deployment#
The deployment of Nobelium is not complicated; the developer has written it in detail on the GitHub project page, so I will just briefly explain.
Step 1: Copy the Notion template to your own Notion account.
Each property in this database is very easy to understand.
Step 2: After forking the project to your GitHub account, you need to modify the content in blog.config.js
.
const BLOG = {
title: "CRAIGARY", // Your blog name (title)
author: "Craig Hart", // Your nickname
email: "[email protected]", // Your email
link: "https://nobelium.vercel.app", // Your blog URL
description: "This gonna be an awesome website.", // Your blog description (subtitle)
lang: "en-US", // Language, 'en-US' for English, 'zh-CN' for Simplified Chinese, 'zh-HK' for Traditional Chinese (Hong Kong), 'zh-TW' for Traditional Chinese (Taiwan), 'ja-JP' for Japanese, 'es-ES' for Spanish
timezone: "Asia/Shanghai", // Timezone, more details can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
font: "sans-serif", // Font, 'sans-serif' for sans-serif font, 'serif' for serif font
lightBackground: "#ffffff", // Light background, use hexadecimal color, e.g., #fffefc, remember not to forget #
darkBackground: "#18181B", // Dark background, use hexadecimal color, remember not to forget #
path: "", // Unless you want to deploy in a folder, keep this empty
since: 2021, // Blog start date; if left blank, it uses the current year
sortByDate: false, // Sort by date; false means no, true means yes
showAbout: true, // Show about this site
showArchive: true, // Show archive
autoCollapsedNavBar: false, // Automatically collapse the navigation bar
ogImageGenerateURL: "https://og-image-craigary.vercel.app", // Generate OG image link
socialLink: "https://twitter.com/craigaryhart", // Social platform link; after filling in, clicking your nickname on the article page will redirect to the corresponding platform
seo: {
keywords: ["Blog", "Website", "Notion"], // Keywords
googleSiteVerification: "", // Remove this value or replace it with your own Google site verification code
},
notionPageId: process.env.NOTION_PAGE_ID, // Do not change this!!!
notionAccessToken: process.env.NOTION_ACCESS_TOKEN, // Use this if you do not want to make the database public
analytics: {
provider: "", // Currently supports Google Analytics and Ackee for visitor statistics; if you want to use Google Analytics, fill in 'ga'; if you want to use Ackee, fill in 'ackee'; leave empty if not using
ackeeConfig: {
tracker: "", // If using Ackee, fill in, e.g., 'https://ackee.craigary.net/tracker.js'
dataAckeeServer: "", // If using Ackee, fill in, e.g., 'https://ackee.craigary.net'
domainId: "", // If using Ackee, fill in, e.g., '0e2257a8-54d4-4847-91a1-0311ea48cc7b'
},
gaConfig: {
measurementId: "", // If using Google Analytics, fill in, e.g., 'G-XXXXXXXXXX'
},
},
comment: {
// Currently integrated comment plugins include gitalk, utterances, and cusdis
provider: "", // Fill in the comment plugin you are using; leave empty if not using
gitalkConfig: {
repo: "", // Please fill in the information you obtained from gitalk
owner: "", // Please fill in the information you obtained from gitalk
admin: [], // Please fill in the information you obtained from gitalk
clientID: "", // Please fill in the information you obtained from gitalk
clientSecret: "", // Please fill in the information you obtained from gitalk
distractionFreeMode: false,
},
utterancesConfig: {
repo: "", // Please fill in the information you obtained from utterances
},
cusdisConfig: {
appId: "", // Please fill in the information you obtained from cusdis
host: "https://cusdis.com", // If you have deployed the cusdis service yourself, replace it with your own service address
scriptSrc: "https://cusdis.com/js/cusdis.es.js", // If you have deployed the cusdis service yourself, replace it with your own service address
},
},
isProd: process.env.VERCEL_ENV === "production", // Distinguish between development and production environments; see https://vercel.com/docs/environment-variables#system-environment-variables for details
};
// export default BLOG
module.exports = BLOG;
Step 3: After completing the modifications, you can deploy it on Vercel, remembering to fill in NOTION_PAGE_ID
in 1️⃣ and the Page ID in 2️⃣, then click Add
.
-
What is Notion Page ID
In Notion, click
Share
, then openShare to web
, which will generate a publicly accessible URL, such ashttps://xxx.notion.site/80c301f9f7264a4aa5dfc1f8b9841222?v=37fe9de07b164c27a9cc3a7c5614a7c4
. The segment of code afterhttps://xxx.notion.site/
and before?v=
is the Page ID, which is80c301f9f7264a4aa5dfc1f8b9841222
.
Cusdis#
I strongly agree with Pingru in “Why I Wanted to Stop Using Cusdis but Changed My Mind?” about the ideal comment system:
It should have the function of anonymous comments; it should allow different login methods like Twitter, Github, Telegram, FB, Google, etc.; it should also allow email login; it should support markdown; it should connect to communication software like Tg or Slack for real-time notifications; it should notify commenters via email when their comments are replied to (if they left an email); it should be lightweight and privacy-focused.
From blog.config.js
, we can see that Nobelium's comment plugins support gitalk, utterances, and cusdis.
I have not used Utterances, so I won't consider it. Gitalk requires logging in with a GitHub account to write comments, which is not anonymous, and its access is poor in China, so I won't consider it. Cusdis, developed by Randy, is a comment plugin that is not only compact and convenient but also does not require any account login for anonymous comments, making it the only choice. I have used it before and found it very close to the ideal comment system.
I chose not to self-host but to use Cusdis's official service directly, adding a Webhook to receive real-time notifications on Tg for new comments. I had previously set up MTPROTO, so I didn't have to worry about Tg not receiving notifications.
Since Cusdis is a login-free comment service, every anonymous comment needs to be approved by the administrator, which seems a bit cumbersome. However, during testing, I found that I could approve comments directly in Tg without logging in, and the redirection was also very convenient.
Modifications#
After deployment, I moved the articles originally in the Super.so database from Notion to the Nobelium database. Then I refreshed the blog page and found that I was not very satisfied with the default navigation bar, footer, code blocks, and fonts. So, with no coding knowledge, I started customizing with the help of ChatGPT.
Navigation Bar#
The first thing I modified was the navigation bar. In components/Header.js
, there is a piece of code like this:
const NavBar = () => {
const BLOG = useConfig()
const locale = useLocale()
const links = [
{ id: 0, name: locale.NAV.INDEX, to: BLOG.path || '/', show: true },
{ id: 1, name: locale.NAV.ABOUT, to: '/about', show: BLOG.showAbout },
{ id: 2, name: locale.NAV.RSS, to: '/feed', show: true, external: true },
{ id: 3, name: locale.NAV.SEARCH, to: '/search', show: true }
]
Where id: 0, name: locale.NAV.INDEX, to: BLOG.path || '/', show: true
can be translated to id: display order, name: local.NAV. variable, to: 'path', show: true
.
Simply put, the variable
is the name variable that needs to be displayed in the navigation bar, and the path
is where this variable points to the URL. For example, the variable for the link with id: 0
is INDEX, and the path is the blog address.
Since there are variables, I need to set the variable names in the file that declares them. In assets/i18n/basic
, I can see files like en-US.json
, which correspond to the languages set in blog.config.js
. So, I modified and added the navigation bar variables and display names in zh-CN.json
.
// Before modification
"NAV": {
"INDEX": "博客",
"RSS": "订阅",
"SEARCH": "搜索",
"ABOUT": "关于"
},
// After modification
"NAV": {
"INDEX": "Blog",
"RSS": "RSS",
"SEARCH": "Search",
"ABOUT": "About",
"Page": "Page",
"Newsletter":"Newsletter"
},
Considering that I added Newsletter, which will link to my paid column subscription on the newspaper boy, displaying RSS as subscription would create semantic ambiguity. So I simply changed all variable display names to English.
After modifying zh-CN.json
, I went back to Header.js
to modify the display order of each link in the navigation bar and removed About (the content was moved to the Page page).
After modifying the above code content, I returned to Notion and added two pages with type
as Page
in the Nobelium database, one with the title
as Newsletter, leaving slug
empty (since it has already been added in the code); the other with the title
as Page, and slug
as page.
Footer#
The default footer of Nobelium has © Nickname Blog Start Year - Current Year
on the left and ▲ Powered by Vercel
on the right.
I found this unappealing, so I thought about moving the left © Nickname Blog Start Year - Current Year
to the right, moving ▲ Powered by Vercel
to the Page page, and displaying the Creative Commons icon with a Copyright page link on the left.
After looking at components/Footer.js
for a long time, I didn't know how to modify it. So I asked ChatGPT, and it directly generated the code for me. After copying and pasting it in, the appearance improved significantly after redeployment.
Code Blocks#
I noticed that in the dark theme, the color of the code blocks was still light, which was very glaring at night. After searching for a while, I found that Leon also mentioned this in “Recording the New Blog: Nobelium, Vercel, Tailwind CSS, and Domain”. He used the dark background prism-tomorrow.css
provided by Prism.js and modified the code in notion.css
. I didn't want to go through that trouble, so I simply replaced the originally referenced prism.css
in pages/_app.js
.
// Before replacement
import "prismjs/themes/prism.css";
// After replacement
import "prismjs/themes/prism-tomorrow.css";
Fonts#
I have always liked the LXGW font open-sourced on GitHub. When I was using Typecho before, I wanted to change the font to LXGW WenKai but was unsuccessful. This time, I had to give it a try.
I saw that there were four woff2 font files in public/fonts
, so I found the LXGW Bright GB version of LXGW WenKai, downloaded it, and uploaded LXGWBrightGB-Regular.woff2
.
Then I first declared the font in styles/globals.css
.
@font-face {
font-family: 'LXGWBrightGB-Regular';
src: url('/fonts/LXGWBrightGB-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
Then I added the font in tailwind.config.js
.
// Before modification
fontFamily: {
sans: FONTS_SANS,
serif: FONTS_SERIF,
noEmoji: [
'"IBM Plex Sans"',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'sans-serif'
]
}
// After modification
fontFamily: {
lxgw: ['LXGWBrightGB-Regular', 'sans-serif'],
sans: FONTS_SANS,
serif: FONTS_SERIF,
noEmoji: [
'"IBM Plex Sans"',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'sans-serif'
]
}
Then I modified the two files Container.js
and NotionRenderer.js
in the components
folder.
Finally, I configured the LXGW font on the blog, fulfilling a wish.
Refinement#
After completing the code modifications, the next step was to return to Notion and refine the blog content in the Nobelium database.
First, I refined the content on the Page page. I defined the Page page as an independent entry point for the blog; it should only be a menu button without a link. Its structure in an ideal state is as follows:
Page
├──── [Memos](https://memo.hhzz.plus/explore)
├──── [File Gallery](https://file.hhzz.love)
├──── [Monitor](https://monitor.hhzz.plus/status/public)
├──── [About](https://justgoidea.com/about)
├──── [Copyright](https://justgoidea.com/copyright)
└──── [Friend Link](https://justgoidea.com/links)
Since Nobelium currently does not support submenus, to keep the navigation bar simple, I had to place my Memos, File Gallery, and Monitor, which should be independent pages, along with the content that should originally be presented in About and Friend Link, all on the Page page.
Memos is a quick memo I self-deployed using the open-source project memos that mimics flomo on GitHub. It stores some currently immature ideas and can also be seen as my private "Twitter." The current categories include #闪念
, #思考
, #碎碎念
, #吐槽
, #推荐
, etc.
File Gallery is a resource sharing site that collects fun and practical resources.
Monitor is a monitoring site used to monitor the operation of the websites, services, and VPS I have deployed online.
About is divided into two parts: About This Site and About Me.
In About This Site, I listed the blog's name (title), URL, Logo, description (subtitle), copyright statement, technical construction, DNS and CDN services, and the fonts used. Since I removed the footer's ▲ Powered by Vercel
, I made a note in the technical statement and expressed gratitude to Vercel. Similarly, I used Cloudflare for DNS and CDN services and used the LXGW font; both provide excellent free services, so I should acknowledge and thank them. Additionally, I wrote a short paragraph about my original intention to keep writing the blog.
In About Me, I briefly described my MBTI personality, identity, and profession, wrote my motto, and left my Email and Twitter.
After refining the content on the Page page, I also created a Copyright page and modified Footer.js
to make the left Creative Commons icon point to this page.
Summary#
A blog should be pure, used for recording and sharing. Notion is very useful, and Nobelium is very simple, meeting all my needs for a blog. In this process, I also learned a lot, such as about Tailwind CSS and Next.js. I still haven't gotten into it, but at least I can understand it and know how to ask ChatGPT to output the code I want. Next, I need to seriously organize and think about how to continue improving the quality of my writing.