README.theme.md
November 24, 2025 · View on GitHub

astro-erudite is an opinionated, unstyled static blogging template built with Astro, Tailwind, and shadcn/ui. Extraordinarily loosely based off the Astro Micro theme by trevortylerlee.
![]() | ![]() |
|---|---|
![]() | ![]() |
Note
To learn more about why this template exists, read The State of Static Blogs in 2024, where I share my take on what constitutes a great blogging template and my goals while developing this one.
Community Examples
Below are some fantastic examples of websites based on this template. If you wish to add your site to this list, open a pull request!
| Site | Author | Description/Features | Source |
|---|---|---|---|
| enscribe.dev | @jktrn | Heavily modified bento-style homepage with client interactivity, with custom MDX components! | → |
| emile.sh | @echoghi | A minimalist personal blog using the flexoki theme | → |
| decentparadox.me | @decentparadox | A heavily customized personal portfolio with a sci-fi theme! | → |
| flocto.github.io | @flocto | A slightly modified personal blog | → |
| dumbprism.me | @dumbprism | A customized portfolio inspired by enscribe's bento grid style adding my gist of UI | → |
| hyuki.dev | @snow0406 | A minimalist blog with a blue color scheme, focusing on simplicity! | → |
| ldd.cc | @xJoyLu | The cream of the idlers. | → |
| rezarezvan.com | @rezaarezvan | A academic blog with personal touches :). | → |
| blog.z0x.ca | @z0x | Very minimal version of erudite, stripping it down to the bare essentials | → |
| angelaytchan.net | @wispyplant | An artist portfolio and activities archive | → |
| kaezr.xyz | @kaezrr | A minimal porfolio and blog website with slight tweaks to the original. | → |
| worldwidewong | @brendanwong-web | A slightly funky portfolio, blog, and resume site with an added photo gallery. | → |
| bgajjala.dev | @bgajjala8 | A minimal blog featuring a paper-color inspired color scheme | → |
| ankitz007.vercel.app | @ankitz007 | A personal blog with a few modifications and updates to the original. | → |
| sadman.ca | @sadmanca | A customized personal blog with: Goodreads reading progress tracker, SVG thumbnails, custom heading styles, and dynamic media grids (books, movies, etc.) | → |
| marcel-to.vercel.app | @Marcel-TO | A content‑driven personal portfolio showcasing software projects, deep–dive blog series and multi-part project documentation. | → |
Features
- Astro's Islands architecture for selective hydration and client-side interactivity while maintaining fast static site rendering.
- shadcn/ui with Tailwind color conventions for automatic light and dark theme styling. Features accessible, theme-aware UI components for navigation, buttons, and more.
- Expressive Code for enhanced code block styling, syntax highlighting, and code block titles.
- Blog authoring with MDX for component-rich content and math rendering via KaTeX.
- Astro View Transitions in SPA mode for smooth route animations.
- SEO optimization with granular metadata and Open Graph tag control for each post.
- RSS feed and sitemap generation.
- Subpost support for breaking long content into digestible parts and organizing related series.
- Author profiles with a dedicated authors page and multi-author post support.
- Project tags with a dedicated tags page for post categorization and discovery.
- Custom Callout component variants for enhanced technical writing.
Repository Structure at a Glance
| Area | Purpose |
|---|---|
src/consts.ts | Centralizes site metadata, navigation, social links, and an icon lookup map for consistent branding across the site. |
src/content.config.ts | Declares Astro content collections for blog posts, authors, and projects with Zod schemas that validate frontmatter. |
src/content/ | Houses MDX and Markdown content grouped by collection; the README inside explains required frontmatter fields. |
src/layouts/Layout.astro | Provides the global page shell, wiring shared CSS, header, footer, and optional slots for head metadata, navigation, and TOCs. |
src/components/ | Astro components for site chrome (header, footer, breadcrumbs, cards, callouts) that consume data from consts.ts and lib helpers. |
src/components/ui/ | Reusable React components powered by class-variance-authority and the shared cn helper for consistent styling. |
src/lib/ | Data and formatting utilities—including loaders for posts/authors/tags, reading-time calculations, TOC builders, and date helpers. |
src/pages/ | File-based routes that fetch content through the lib helpers, render Astro/React components, and slot optional sidebars. |
src/styles/global.css | Tailwind 4 setup with Flexoki-inspired tokens, font imports, and light/dark theme variables. |
public/ | Static assets such as favicons, fonts, OG fallbacks, and showcase imagery. |
scripts/ | TypeScript automation for generating posts, favicons, OG images, and other design assets (see scripts/README.md). |
How the Pieces Fit Together
- Content ingestion – MDX/Markdown files are validated against
content.config.ts, then loaded throughsrc/lib/data-utils.ts, which handles draft filtering, sorting, subpost hierarchies, reading times, and TOC extraction. - Site chrome & theming –
src/layouts/Layout.astrowraps every page in shared CSS, header, and footer components. The header reads navigation/social metadata fromsrc/consts.ts, whileThemeToggle.astrokeeps light/dark selections in sync across view transitions. - Page metadata –
src/components/PageHead.astroandsrc/components/PostHead.astroconsolidate canonical URLs, SEO tags, and Open Graph/Twitter metadata, falling back to shared OG imagery when a post omits one. - UI building blocks – Astro and React components (cards, callouts, pagination, buttons) compose Tailwind tokens with
class-variance-authorityand the sharedcnhelper, keeping styling predictable. - Routing & presentation – Files in
src/pages/map directly to routes, orchestrating data fetching, layout slots, breadcrumb generation, and optional TOC sidebars for blog posts and subposts.
Tooling & Configuration Highlights
astro.config.tsenables integrations for MDX, React islands, sitemap generation, Expressive Code, Astro Icon, Tailwind, KaTeX, emoji, and sets the dev server tolocalhost:1234.package.jsonscripts coordinate builds, OG image generation, Astro type-checking, and content scaffolding (for example,npm run new-post).- Automation scripts in
scripts/render OG assets, favicons, and logos via the React templates insrc/components/ui/using Satori and Resvg.
Next Steps for New Contributors
- Customize branding and navigation – Update
src/consts.tswith your title, description, navigation tabs, and social links; tweak theme tokens insrc/styles/global.cssfor your color system. - Author new content quickly – Follow the content README guidance or run
npm run new-postto scaffold MDX files that satisfy collection schemas and generate matching OG assets. - Understand dynamic behavior – Review
src/lib/data-utils.tsalongsidesrc/pages/posts/[...id].astroto see how subposts, TOCs, and metadata are composed when rendering individual posts. - Extend the component library – Use the shadcn-inspired React components in
src/components/ui/and Astro wrappers (likeCallout.astroorBlogCard.astro) as references for building new interactive or MDX-friendly UI. - Tinker with build tooling – Modify
astro.config.tsor augment the automation scripts if you need additional markdown processing, asset generation, or linting during the build.
Technology Stack
This is a list of the various technologies used to build this template:
| Category | Technology Name |
|---|---|
| Framework | Astro |
| Styling | Tailwind |
| Components | shadcn/ui |
| Content | MDX |
| Codeblocks | Expressive Code, Shiki |
| Graphics | Figma |
| Deployment | Vercel |
Getting Started
-
Hit “Use this template”, the big green button on the top right, to create a new repository in your own GitHub account with this template.
-
Clone the repository:
git clone https://github.com/[YOUR_USERNAME]/[YOUR_REPO_NAME].git cd [YOUR_REPO_NAME] -
Install dependencies:
npm install -
Start the development server:
npm run dev -
Open your browser and visit
http://localhost:1234to get started. The following commands are also available:Command Description npm run startAlias for npm run devnpm run buildRun type checking and build the project npm run previewPreviews the built project npm run astroRun Astro CLI commands npm run prettierBlanket format all files using Prettier
Customization
Site Configuration
Edit the src/consts.ts file to update your site's metadata, navigation links, and social links:
export const SITE: Site = {
title: 'astro-erudite',
description: // ...
href: 'https://astro-erudite.vercel.app',
featuredPostCount: 2,
postsPerPage: 3,
}
export const NAV_LINKS: SocialLink[] = [
{
href: '/posts',
label: 'posts',
},
// ...
]
export const SOCIAL_LINKS: SocialLink[] = [
{
href: 'https://github.com/jktrn',
label: 'GitHub',
},
// ...
]
Color Palette
Colors are defined in src/styles/global.css in OKLCH format, using the shadcn/ui convention:
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
}
[data-theme='dark'] {
/* ... */
}
Favicons
Favicons are generated using RealFaviconGenerator. To adjust the favicons, replace the files in the public/ directory (such as favicon.ico, favicon.svg, apple-touch-icon.png, etc.) with your own. After updating the favicon files, you'll also need to adjust the references in src/components/Favicons.astro to match your new favicon filenames and paths:
<!-- Replace these with the generated meta tags -->
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="astro-erudite" />
<link rel="manifest" href="/site.webmanifest" />
Adding Content
Blog Posts
Add new blog posts as MDX files in the src/content/blog/ directory. Use the following frontmatter structure:
---
title: 'Your Post Title'
description: 'A brief description of your post!'
date: 2024-01-01
tags: ['tag1', 'tag2']
image: './image.png'
authors: ['author1', 'author2']
draft: false
---
The blog post schema is defined as follows:
| Field | Type (Zod) | Requirements | Required |
|---|---|---|---|
title | string | Should be ≤60 characters. | Yes |
description | string | Should be ≤155 characters. | Yes |
date | coerce.date() | Must be in YYYY-MM-DD format. | Yes |
order | number | Sort order for subposts with the same date. Defaults to 0 if not provided. | Optional |
image | image() | Should be exactly 1200px × 630px. | Optional |
tags | string[] | Preferably use kebab-case for these. | Optional |
authors | string[] | If the author has a profile, use the id associated with their Markdown file in src/content/authors/ (e.g. if their file is named jane-doe.md, use jane-doe in the array). | Optional |
draft | boolean | Defaults to false if not provided. | Optional |
Authors
Add author information in src/content/authors/ as Markdown files. A file named [author-name].md can be associated with a blog post if "author-name" (the id) is added to the authors field:
---
name: 'enscribe'
pronouns: 'he/him'
avatar: 'https://gravatar.com/avatar/9bfdc4ec972793cf05cb91efce5f4aaaec2a0da1bf4ec34dad0913f1d845faf6.webp?size=256'
bio: 'd(-_-)b'
website: 'https://enscribe.dev'
twitter: 'https://twitter.com/enscry'
github: 'https://github.com/jktrn'
mail: 'jason@enscribe.dev'
---
The author schema is defined as follows:
| Field | Type (Zod) | Requirements | Required |
|---|---|---|---|
name | string | n/a | Yes |
pronouns | string | n/a | Optional |
avatar | string.url() or string.startsWith('/') | Should be either a valid URL or a path starting with /. Preferably use Gravatar with the ?size=256 size parameter. | Yes |
bio | string | n/a | Optional |
mail | string.email() | Must be a valid email address. | Optional |
website | string.url() | Must be a valid URL. | Optional |
twitter | string.url() | Must be a valid URL. | Optional |
github | string.url() | Must be a valid URL. | Optional |
linkedin | string.url() | Must be a valid URL. | Optional |
discord | string.url() | Must be a valid URL. | Optional |
Tip
You can add as many social media links as you want, as long as you adjust the schema! Make sure you also support the new field in the src/components/SocialIcons.astro component.
Projects
Add projects in src/content/projects/ as Markdown files:
---
name: 'Project A'
description: 'This is an example project description! You should replace this with a description of your own project.'
tags: ['Framework A', 'Library B', 'Tool C', 'Resource D']
image: '/static/1200x630.png'
link: 'https://example.com'
startDate: '2024-01-01'
endDate: '2024-01-01'
---
The project schema is defined as follows:
| Field | Type (Zod) | Requirements | Required |
|---|---|---|---|
name | string | n/a | Yes |
description | string | n/a | Yes |
tags | string[] | n/a | Yes |
image | image() | Should be exactly 1200px × 630px. | Yes |
link | string.url() | Must be a valid URL. | Yes |
startDate | coerce.date() | Must be in YYYY-MM-DD format. | Optional |
endDate | coerce.date() | Must be in YYYY-MM-DD format. | Optional |
License
This project is open source and available under the MIT License.
Star History
Built with ♥ by enscribe!



