Building Edonspace From Scratch
Why Build This
After a few years of coding and trading, my work was scattered everywhere — a handful of GitHub repos, local drafts that never shipped, fragmented ideas lost in chat threads. Nothing tied it together. No single place said “here’s who I am and what I do.”
A personal site isn’t vanity. It’s a signal amplifier. The code you write, the mistakes you document, the tools you build — if nobody sees them, they’re just a hobby. A site aggregates all of it so potential collaborators, employers, or fellow builders can quickly understand what you’re about.
There’s another reason: build in public. Recording the process forces you to actually finish things instead of perpetually deferring to “next week.”
Tech Choices
I picked Astro because it’s content-first. Blog posts and documentation are a natural fit for static site generation — no client-side JavaScript runtime needed. Loading a React bundle just to render an article is wasteful.
Tailwind CSS 4 moved to native CSS @theme configuration. No more tailwind.config.js. Design tokens live directly in CSS, closer to how the browser actually works.
Cloudflare Pages handles distribution. Global CDN, zero cold starts, generous free tier. Decent performance from mainland China too — better than Vercel or Netlify in my testing.
Trilingual support (English / Simplified Chinese / Traditional Chinese) was planned from day one. Not bolted on later. If you don’t architect i18n on the first day, the retrofit cost is brutal — routing, content directory structure, hreflang tags, UI string translations, every layer needs adaptation.
Architecture Decisions
Content is managed through Astro Content Collections. Every piece of content has a lang field and a translationKey field. The first identifies the language; the second links translations together. This way, switching languages navigates to the exact translated page instead of dumping you back to the homepage.
Directory structure splits by language: src/content/blog/en/, src/content/blog/zh-cn/. Page routes use language prefixes: /en/blog/, /zh-cn/blog/.
For design, I chose deep navy as the primary color (65%), cool gray as secondary (25%), amber as accent (10%). Headings use Space Grotesk — geometric but not sterile. Body text uses Inter for readability. Skipped Roboto — too generic.
What’s Next
The skeleton is in place. Up next: migrating options tutorial content from existing epub and YouTube transcripts, setting up publishing pipelines to WeChat and X, deploying to Cloudflare Pages.
This is the first post. More build logs to follow.