diuu: a small website foundation with sign-in and bilingual publishing
A website built on mkfast-lite, with Google sign-in, D1-backed content, and independent Chinese and English publishing.
A small website does not always need a large administration platform. A clear homepage, sign-in, content publishing, and two languages can support the first product introduction and the updates that follow.
diuu builds on the open-source mkfast-lite template. This implementation adds a working blog administration interface to its existing multilingual website and authentication foundation. The goal is straightforward: finish the essential journeys so creators can focus on their product and their words.
Start with a clear public website
The frontend uses React, TanStack Start, and TanStack Router. It keeps the template's warm paper palette, orange and yellow accents, and visible ink borders. The site supports light and dark themes, with English and Simplified Chinese interfaces.
The English blog lives at /blog, and its Chinese counterpart at /zh/blog. Readers can browse articles, filter by category, search, and move between pages before opening a full article. Published content has its own title, excerpt, sharing metadata, and sitemap entry.
These features serve a simple purpose: help people find a useful article and read it without distraction.
Keep sign-in and content in one application
The application runs on Cloudflare Workers. Cloudflare D1 stores authentication and blog data, with database structure and migrations managed through Drizzle.
Better Auth provides Google and email/password sign-in. Blog administration currently follows a deliberately narrow rule: the signed-in user's application ID must match the BLOG_ADMIN_USER_ID environment variable.
The Header shows the management entry only to the administrator. Hiding an entry is not the security boundary: private reads, saves, publication, and unpublication all check the authenticated identity on the server. Mutations also check the request origin.
This fits the current single-administrator publishing workflow without introducing a larger organization or role-management system.
Saving a draft does not change the live article
The editor supports Markdown, preview, draft saving, publication, and unpublication. Common headings, lists, links, and code formatting are supported. Raw HTML is not rendered as executable content.
Editable drafts and published snapshots are stored separately:
- Create an article and prepare its title, excerpt, and body.
- Save the draft. Readers continue to see the previously published version.
- Review the preview, then publish the selected language to update the public page.
- Unpublish to remove public access while preserving the draft and publication record for later use.
An article's shared URL becomes locked after its first publication, protecting links that have already been shared. Saves and publication use revision numbers; conflicting edits are rejected rather than silently replacing another version.
Leaving an unsaved editor or switching its content language offers three explicit choices: save and continue, discard the edit, or cancel.
Publish each language when it is ready
Bilingual publishing means maintaining separate expressions, not placing the same body at two addresses. Chinese and English have independent titles, excerpts, bodies, SEO fields, drafts, and publication states.
Chinese can go live while English remains a draft. Unpublishing one translation leaves the other available. When the entire article needs to come down, administration also offers an explicit operation that unpublishes both languages.
Public language links connect only to published translations. If a translation is unavailable, the site explains that state instead of substituting another language's body.
Keep the scope small
This release completes the core website, sign-in, and blog journeys. It does not add comments, user submissions, scheduled publication, automatic translation, payments, newsletters, or image uploads.
Covers currently use HTTPS image URLs and require an image description. Paraglide manages fixed interface messages, while article content lives in the database. Editing an article does not require recompiling interface translations or redeploying the whole site.
Further capabilities can follow real needs. For now, the useful next step is simple: write the first article and share the content that is ready.