diff --git a/packages/www/next.config.js b/packages/www/next.config.js
index e4d9086d..48279f46 100644
--- a/packages/www/next.config.js
+++ b/packages/www/next.config.js
@@ -1,5 +1,57 @@
// @ts-check
+const fs = require("fs");
+const path = require("path");
+
+function parseMarkdownTitle(/** @type {string} */ source) {
+ const firstLine = source.split("\n")[0];
+ if (firstLine == null) {
+ throw new Error("No title.");
+ }
+ const START = 'export const title = "';
+ if (!firstLine.startsWith(START) || !firstLine.endsWith('";')) {
+ throw new Error(`Invalid title line:\n${firstLine}`);
+ }
+ return firstLine.substring(START.length, firstLine.length - 2).trim();
+}
+
+function computeAllMedatada() {
+ const BLOG_POSTS_ROOT = path.join("src", "app", "blog", "(blog-posts)");
+
+ /** @type {import("./src/lib/metadata").BlogPostMetadata[]} */
+ const allMetadata = [];
+ for (const year of fs.readdirSync(BLOG_POSTS_ROOT)) {
+ if (year === "layout.tsx") {
+ continue;
+ }
+ for (const month of fs.readdirSync(path.join(BLOG_POSTS_ROOT, year))) {
+ for (const date of fs.readdirSync(path.join(BLOG_POSTS_ROOT, year, month))) {
+ for (const titleSlug of fs.readdirSync(path.join(BLOG_POSTS_ROOT, year, month, date))) {
+ const fullPath = path.join(BLOG_POSTS_ROOT, year, month, date, titleSlug, "page.mdx");
+ const content = fs.readFileSync(fullPath).toString();
+ try {
+ const title = parseMarkdownTitle(content);
+ allMetadata.push({ title, year, month, date, titleSlug });
+ } catch (error) {
+ throw new Error(`Failed to parse ${fullPath}, error: ${error}`);
+ }
+ }
+ }
+ }
+ }
+
+ allMetadata.sort((a, b) => {
+ let c = b.year.localeCompare(a.year);
+ if (c !== 0) return c;
+ c = b.month.localeCompare(a.month);
+ if (c !== 0) return c;
+ c = b.date.localeCompare(a.date);
+ return c;
+ });
+
+ return allMetadata;
+}
+
const withMDX = require("@next/mdx")({
extension: /\.mdx?$/,
options: {
@@ -10,8 +62,10 @@ const withMDX = require("@next/mdx")({
/** @type {import('next').NextConfig} */
const nextConfig = {
+ pageExtensions: ["tsx", "mdx"],
experimental: { mdxRs: true },
output: "export",
+ env: { ALL_BLOG_POST_METADATA: JSON.stringify(computeAllMedatada()) },
typescript: { ignoreBuildErrors: true },
};
diff --git a/packages/www/package.json b/packages/www/package.json
index 0c18e904..aecdc624 100644
--- a/packages/www/package.json
+++ b/packages/www/package.json
@@ -10,7 +10,7 @@
"dependencies": {
"@mdx-js/loader": "^2.3.0",
"@mdx-js/react": "2.0.0",
- "@next/mdx": "^13.5.3",
+ "@next/mdx": "^13.5.4",
"@types/mdx": "^2.0.8",
"autoprefixer": "^10.4.16",
"dev-sam-theme": "^0.0.1",
diff --git a/packages/www/blog/1970-01-01-welcome-to-my-blog.mdx b/packages/www/src/app/blog/(blog-posts)/1970/01/01/welcome-to-my-blog/page.mdx
similarity index 83%
rename from packages/www/blog/1970-01-01-welcome-to-my-blog.mdx
rename to packages/www/src/app/blog/(blog-posts)/1970/01/01/welcome-to-my-blog/page.mdx
index b4867f66..06851bcc 100755
--- a/packages/www/blog/1970-01-01-welcome-to-my-blog.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/1970/01/01/welcome-to-my-blog/page.mdx
@@ -1,4 +1,6 @@
export const title = "Welcome to My Blog!";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
This is the zeroth post in my blog. Since the content of the post might change when I migrate the
blog from one place to another, I choose to set the time to be `1970-01-01`.
diff --git a/packages/www/blog/2016-12-30-nerd-pride.mdx b/packages/www/src/app/blog/(blog-posts)/2016/12/30/nerd-pride/page.mdx
similarity index 99%
rename from packages/www/blog/2016-12-30-nerd-pride.mdx
rename to packages/www/src/app/blog/(blog-posts)/2016/12/30/nerd-pride/page.mdx
index 9cf0e298..b80ff376 100644
--- a/packages/www/blog/2016-12-30-nerd-pride.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2016/12/30/nerd-pride/page.mdx
@@ -1,4 +1,6 @@
export const title = "Nerd Pride";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
On the evening of December 8, 2016, exactly on 5:01 PM in Eastern Standard Time, the photons of
Cornell Engineering acceptance letter struck my eyes. For me, it was a confirmation, a confirmation
diff --git a/packages/www/blog/2017-05-31-project-defcon-1.mdx b/packages/www/src/app/blog/(blog-posts)/2017/05/31/project-defcon-1/page.mdx
similarity index 95%
rename from packages/www/blog/2017-05-31-project-defcon-1.mdx
rename to packages/www/src/app/blog/(blog-posts)/2017/05/31/project-defcon-1/page.mdx
index d776035f..1696dd44 100644
--- a/packages/www/blog/2017-05-31-project-defcon-1.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2017/05/31/project-defcon-1/page.mdx
@@ -1,4 +1,6 @@
export const title = "Project DEFCON 1: A Confidential Data Storage System";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
## 1.Introduction
diff --git a/packages/www/blog/2018-06-15-sampl-alpha-design-choices.mdx b/packages/www/src/app/blog/(blog-posts)/2018/06/15/sampl-alpha-design-choices/page.mdx
similarity index 98%
rename from packages/www/blog/2018-06-15-sampl-alpha-design-choices.mdx
rename to packages/www/src/app/blog/(blog-posts)/2018/06/15/sampl-alpha-design-choices/page.mdx
index f3fec473..9cf481c8 100755
--- a/packages/www/blog/2018-06-15-sampl-alpha-design-choices.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2018/06/15/sampl-alpha-design-choices/page.mdx
@@ -1,4 +1,6 @@
export const title = "Design Choice of SAMPL - Written After the First Alpha Release";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
## Beginning
diff --git a/packages/www/blog/2018-06-19-sampl-fun-ref-mistake-fix.mdx b/packages/www/src/app/blog/(blog-posts)/2018/06/19/sampl-fun-ref-mistake-fix/page.mdx
similarity index 97%
rename from packages/www/blog/2018-06-19-sampl-fun-ref-mistake-fix.mdx
rename to packages/www/src/app/blog/(blog-posts)/2018/06/19/sampl-fun-ref-mistake-fix/page.mdx
index 4ba5d743..d167c617 100755
--- a/packages/www/blog/2018-06-19-sampl-fun-ref-mistake-fix.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2018/06/19/sampl-fun-ref-mistake-fix/page.mdx
@@ -1,4 +1,6 @@
export const title = "Function Reference in SAMPL - A Design Mistake and the Fix";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
## Background
diff --git a/packages/www/blog/2018-08-27-cw-turing-complete.mdx b/packages/www/src/app/blog/(blog-posts)/2018/08/27/cw-turing-complete/page.mdx
similarity index 98%
rename from packages/www/blog/2018-08-27-cw-turing-complete.mdx
rename to packages/www/src/app/blog/(blog-posts)/2018/08/27/cw-turing-complete/page.mdx
index eccfb941..e04e6b73 100755
--- a/packages/www/blog/2018-08-27-cw-turing-complete.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2018/08/27/cw-turing-complete/page.mdx
@@ -1,4 +1,6 @@
export const title = "Critter World is Turing Complete - A Not-So-Rigorous Proof";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
Critter World is Cornell's CS 2112's Final Project. It is a simulated hexagon world where critters,
controled by programs, can move, eat, mate, bud, attack, etc. The programming language is very
diff --git a/packages/www/blog/2018-12-31-cs-in-high-schools.mdx b/packages/www/src/app/blog/(blog-posts)/2018/12/31/cs-in-high-schools/page.mdx
similarity index 99%
rename from packages/www/blog/2018-12-31-cs-in-high-schools.mdx
rename to packages/www/src/app/blog/(blog-posts)/2018/12/31/cs-in-high-schools/page.mdx
index c7974939..ffe5f6d0 100755
--- a/packages/www/blog/2018-12-31-cs-in-high-schools.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2018/12/31/cs-in-high-schools/page.mdx
@@ -1,4 +1,6 @@
export const title = "Computer Science in High Schools";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
This year, I got an intern with a resume that did not mention my high school's CS project with a
single word. Therefore, at this point, either success or failure in my high school CS career does
diff --git a/packages/www/blog/2019-01-12-samlang-alpha-design-choices.mdx b/packages/www/src/app/blog/(blog-posts)/2019/01/12/samlang-alpha-design-choices/page.mdx
similarity index 98%
rename from packages/www/blog/2019-01-12-samlang-alpha-design-choices.mdx
rename to packages/www/src/app/blog/(blog-posts)/2019/01/12/samlang-alpha-design-choices/page.mdx
index da2fe489..2cb08303 100755
--- a/packages/www/blog/2019-01-12-samlang-alpha-design-choices.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2019/01/12/samlang-alpha-design-choices/page.mdx
@@ -1,4 +1,6 @@
export const title = "Design Choice of samlang in Alpha";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
## Background
diff --git a/packages/www/blog/2020-01-07-my-decade-in-review.mdx b/packages/www/src/app/blog/(blog-posts)/2020/01/07/my-decade-in-review/page.mdx
similarity index 99%
rename from packages/www/blog/2020-01-07-my-decade-in-review.mdx
rename to packages/www/src/app/blog/(blog-posts)/2020/01/07/my-decade-in-review/page.mdx
index 34002ea5..b1805935 100644
--- a/packages/www/blog/2020-01-07-my-decade-in-review.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2020/01/07/my-decade-in-review/page.mdx
@@ -1,4 +1,6 @@
export const title = "My Decade in Review";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
Following the lead of React and JavaScript god [Dan Abramov](https://overreacted.io/), I decided to
also publish my decade in review blog post.
diff --git a/packages/www/blog/2020-01-09-implement-autocomplete.mdx b/packages/www/src/app/blog/(blog-posts)/2020/01/09/implement-autocomplete/page.mdx
similarity index 99%
rename from packages/www/blog/2020-01-09-implement-autocomplete.mdx
rename to packages/www/src/app/blog/(blog-posts)/2020/01/09/implement-autocomplete/page.mdx
index c0a79157..fa40943b 100644
--- a/packages/www/blog/2020-01-09-implement-autocomplete.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2020/01/09/implement-autocomplete/page.mdx
@@ -1,4 +1,6 @@
export const title = "How to Implement Autocomplete";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
Implement autocomplete in 79 lines of code. Actually, it's not that easy.
diff --git a/packages/www/blog/2020-05-14-one-year-as-dev-lead.mdx b/packages/www/src/app/blog/(blog-posts)/2020/05/14/one-year-as-dev-lead/page.mdx
similarity index 98%
rename from packages/www/blog/2020-05-14-one-year-as-dev-lead.mdx
rename to packages/www/src/app/blog/(blog-posts)/2020/05/14/one-year-as-dev-lead/page.mdx
index 976612b3..4900362f 100644
--- a/packages/www/blog/2020-05-14-one-year-as-dev-lead.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2020/05/14/one-year-as-dev-lead/page.mdx
@@ -1,4 +1,6 @@
export const title = "One Year as Developer Lead";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
Almost a year ago, I started to perform developer lead responsibilities at
[Cornell DTI](https://www.cornelldti.org). My first major task was to grade part of developers at
diff --git a/packages/www/blog/2020-05-17-samlang-in-browser.mdx b/packages/www/src/app/blog/(blog-posts)/2020/05/17/samlang-in-browser/page.mdx
similarity index 99%
rename from packages/www/blog/2020-05-17-samlang-in-browser.mdx
rename to packages/www/src/app/blog/(blog-posts)/2020/05/17/samlang-in-browser/page.mdx
index 3ad92ff8..8b91ed6d 100644
--- a/packages/www/blog/2020-05-17-samlang-in-browser.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2020/05/17/samlang-in-browser/page.mdx
@@ -1,4 +1,6 @@
export const title = "Making samlang Run in Browsers";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
## Background
diff --git a/packages/www/blog/2020-08-30-samlang-ts-rewrite.mdx b/packages/www/src/app/blog/(blog-posts)/2020/08/30/samlang-ts-rewrite/page.mdx
similarity index 98%
rename from packages/www/blog/2020-08-30-samlang-ts-rewrite.mdx
rename to packages/www/src/app/blog/(blog-posts)/2020/08/30/samlang-ts-rewrite/page.mdx
index 0384e8d7..766ed7de 100644
--- a/packages/www/blog/2020-08-30-samlang-ts-rewrite.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2020/08/30/samlang-ts-rewrite/page.mdx
@@ -1,4 +1,6 @@
export const title = "Rewriting samlang in TypeScript";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
A lot has changed since my [last blog post](/blog/2020/05/17/samlang-in-browser) on my effort to make
samlang run in browsers. The samlang demo site has been merged into the samlang documentation site
diff --git a/packages/www/blog/2021-01-24-samlang-llvm-backend.mdx b/packages/www/src/app/blog/(blog-posts)/2021/01/24/samlang-llvm-backend/page.mdx
similarity index 99%
rename from packages/www/blog/2021-01-24-samlang-llvm-backend.mdx
rename to packages/www/src/app/blog/(blog-posts)/2021/01/24/samlang-llvm-backend/page.mdx
index 4ee401be..d76f57d8 100644
--- a/packages/www/blog/2021-01-24-samlang-llvm-backend.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2021/01/24/samlang-llvm-backend/page.mdx
@@ -1,4 +1,6 @@
export const title = "Supporting the LLVM Backend for samlang";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
LLVM is a collection of compiler toolchain that allows you to target any instruction set from any
source-level programming language. Once the source code has been lowered to LLVM IR, the LLVM
diff --git a/packages/www/blog/2021-02-16-squash-and-merge.mdx b/packages/www/src/app/blog/(blog-posts)/2021/02/16/squash-and-merge/page.mdx
similarity index 98%
rename from packages/www/blog/2021-02-16-squash-and-merge.mdx
rename to packages/www/src/app/blog/(blog-posts)/2021/02/16/squash-and-merge/page.mdx
index ed08919f..ffd15a6f 100644
--- a/packages/www/blog/2021-02-16-squash-and-merge.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2021/02/16/squash-and-merge/page.mdx
@@ -1,4 +1,6 @@
export const title = "The Case for Squash and Merge";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
There are several things I have very passionate opinions on, like whether opening braces `{` should
be on a new line, etc. _(Answer: NO NO NO!)_ Merging in a pull request using squash and merge is
diff --git a/packages/www/blog/2021-10-29-samlang-wasm-backend.mdx b/packages/www/src/app/blog/(blog-posts)/2021/10/29/samlang-wasm-backend/page.mdx
similarity index 98%
rename from packages/www/blog/2021-10-29-samlang-wasm-backend.mdx
rename to packages/www/src/app/blog/(blog-posts)/2021/10/29/samlang-wasm-backend/page.mdx
index 7544df4c..976f2cb4 100644
--- a/packages/www/blog/2021-10-29-samlang-wasm-backend.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2021/10/29/samlang-wasm-backend/page.mdx
@@ -1,5 +1,6 @@
export const title = "WebAssembly Backend for samlang";
-export const ogImage = "/blog/2021-10-29-samlang-wasm-backend/wasm.png";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title, "/blog/2021-10-29-samlang-wasm-backend/wasm.png");
Since the release of Apple M1 MacBook, a ticking bomb starts: eventually there will be a day that I
cannot run the compiled samlang code anymore, if samlang compiler does not change. samlang must
diff --git a/packages/www/blog/2022-01-02-courseplan-review.mdx b/packages/www/src/app/blog/(blog-posts)/2022/01/02/courseplan-review/page.mdx
similarity index 98%
rename from packages/www/blog/2022-01-02-courseplan-review.mdx
rename to packages/www/src/app/blog/(blog-posts)/2022/01/02/courseplan-review/page.mdx
index 8672e32b..9dc9cc90 100644
--- a/packages/www/blog/2022-01-02-courseplan-review.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2022/01/02/courseplan-review/page.mdx
@@ -1,5 +1,6 @@
export const title = "CoursePlan: A Unique Design & Tech Initiative";
-export const ogImage = "/blog/2022-01-02-courseplan-review/two-graphs-theory.png";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title, "/blog/2022-01-02-courseplan-review/two-graphs-theory.png");
## Introduction
diff --git a/packages/www/blog/2022-01-28-why-useless-code.mdx b/packages/www/src/app/blog/(blog-posts)/2022/01/28/why-useless-code/page.mdx
similarity index 95%
rename from packages/www/blog/2022-01-28-why-useless-code.mdx
rename to packages/www/src/app/blog/(blog-posts)/2022/01/28/why-useless-code/page.mdx
index 59c087a4..19d0d3d5 100644
--- a/packages/www/blog/2022-01-28-why-useless-code.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2022/01/28/why-useless-code/page.mdx
@@ -1,4 +1,6 @@
export const title = "Why I Write Useless Code";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
There are a lot of ways you can categorize code, but in this blog post, I will mostly focus on their
usefulness. Some code can be useful, or designed to be useful but actually useless. You might
diff --git a/packages/www/blog/2022-09-05-bounded-qualification.mdx b/packages/www/src/app/blog/(blog-posts)/2022/09/05/bounded-qualification/page.mdx
similarity index 98%
rename from packages/www/blog/2022-09-05-bounded-qualification.mdx
rename to packages/www/src/app/blog/(blog-posts)/2022/09/05/bounded-qualification/page.mdx
index 0947c7c4..a34d2337 100644
--- a/packages/www/blog/2022-09-05-bounded-qualification.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2022/09/05/bounded-qualification/page.mdx
@@ -1,5 +1,6 @@
export const title = "Bounded Qualification in samlang";
-export const ogImage = "/blog/2022-09-05-bounded-qualification/bounded-qualification.png";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title, "/blog/2022-09-05-bounded-qualification/bounded-qualification.png");
## Introduction
diff --git a/packages/www/blog/2023-01-08-samlang-rust-rewrite.mdx b/packages/www/src/app/blog/(blog-posts)/2023/01/08/samlang-rust-rewrite/page.mdx
similarity index 97%
rename from packages/www/blog/2023-01-08-samlang-rust-rewrite.mdx
rename to packages/www/src/app/blog/(blog-posts)/2023/01/08/samlang-rust-rewrite/page.mdx
index aee0e927..994909b4 100644
--- a/packages/www/blog/2023-01-08-samlang-rust-rewrite.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2023/01/08/samlang-rust-rewrite/page.mdx
@@ -1,5 +1,6 @@
export const title = "Rewriting samlang in Rust";
-export const ogImage = "/blog/2023-01-08-samlang-in-rust/optimization.png";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title, "/blog/2023-01-08-samlang-in-rust/optimization.png");
## Motivation
diff --git a/packages/www/blog/2023-09-11-life-of-high-school-cs-club-member.mdx b/packages/www/src/app/blog/(blog-posts)/2023/09/11/life-of-high-school-cs-club-member/page.mdx
similarity index 98%
rename from packages/www/blog/2023-09-11-life-of-high-school-cs-club-member.mdx
rename to packages/www/src/app/blog/(blog-posts)/2023/09/11/life-of-high-school-cs-club-member/page.mdx
index 150efd0a..1702d22c 100644
--- a/packages/www/blog/2023-09-11-life-of-high-school-cs-club-member.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2023/09/11/life-of-high-school-cs-club-member/page.mdx
@@ -1,4 +1,6 @@
export const title = "Life of a High School CS Club President, from a SWE's Perspective";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
Imagine yourself being the president of the [CS club at my high school](https://computerization.io).
You are now in grade 11 and have just taken over the presidency from the seniors. You have grand
diff --git a/packages/www/blog/2023-09-23-samlang-perf-opt.mdx b/packages/www/src/app/blog/(blog-posts)/2023/09/23/samlang-perf-opt/page.mdx
similarity index 97%
rename from packages/www/blog/2023-09-23-samlang-perf-opt.mdx
rename to packages/www/src/app/blog/(blog-posts)/2023/09/23/samlang-perf-opt/page.mdx
index c2ca4737..3dd19d4a 100644
--- a/packages/www/blog/2023-09-23-samlang-perf-opt.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2023/09/23/samlang-perf-opt/page.mdx
@@ -1,5 +1,6 @@
export const title = "Performance Optimization on the samlang Compiler";
-export const ogImage = "/blog/2023-09-23-samlang-perf-opt/comparison.png";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title, "/blog/2023-09-23-samlang-perf-opt/comparison.png");
With a long-planned Rust rewrite of samlang finally done at the start of 2023, I decided to focus this year on fixing a lot of rough edges of the language, including syntax, semantics, and IDE services. Nine months later, I managed to tick quite a few items in the continuously growing [checklist](https://github.com/SamChou19815/samlang/issues/921).
diff --git a/packages/www/blog/2023-10-01-what-happens-if-react-is-eager.mdx b/packages/www/src/app/blog/(blog-posts)/2023/10/01/what-happens-if-react-is-eager/page.mdx
similarity index 98%
rename from packages/www/blog/2023-10-01-what-happens-if-react-is-eager.mdx
rename to packages/www/src/app/blog/(blog-posts)/2023/10/01/what-happens-if-react-is-eager/page.mdx
index a8c32538..6f8fbcf8 100644
--- a/packages/www/blog/2023-10-01-what-happens-if-react-is-eager.mdx
+++ b/packages/www/src/app/blog/(blog-posts)/2023/10/01/what-happens-if-react-is-eager/page.mdx
@@ -1,4 +1,6 @@
export const title = "What Will Happen if React Evaluates JSX Eagerly?";
+import blogPostPageMetadata from '../../../../../../../lib/blog-post-page-metadata';
+export const metadata = blogPostPageMetadata(title);
TLDR: Absolute Chaos
diff --git a/packages/www/src/app/blog/(blog-posts)/layout.tsx b/packages/www/src/app/blog/(blog-posts)/layout.tsx
new file mode 100644
index 00000000..53abc018
--- /dev/null
+++ b/packages/www/src/app/blog/(blog-posts)/layout.tsx
@@ -0,0 +1,14 @@
+import BlogDocumentWrapper from "../../../lib/BlogDocumentWrapper";
+import BlogPostItemContextAware from "../../../lib/BlogPostItemContextAware";
+
+export default function BlogPostPageLayout({ children }: { children: React.ReactNode }) {
+ return (
+
+