# Astro in the 30 Seconds of Code Project: Static Site Generation Architecture

> Discover Astro's role in the 30 Seconds of Code project. Learn how Astro powers a fast, SEO-friendly static site with minimal JavaScript, replacing Next.js.

- Repository: [Angelos Chalaris/30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code)
- Tags: architecture
- Published: 2026-02-25

---

**Astro serves as the static-site generation (SSG) engine for the 30 seconds of code project, replacing the previous Next.js implementation to deliver a fast, SEO-friendly website with minimal JavaScript overhead.**

The [Chalarangelo/30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code) repository uses Astro to transform its content model into a high-performance static website. This architecture separates content preparation from rendering, allowing Astro to consume pre-generated JSON bundles and compile them into optimized HTML at build time.

## Astro's Role in the Build Pipeline

### Build Orchestration via bin/prepare

The build process begins with the `bin/prepare` CLI script, which orchestrates the generation of Astro-compatible content. During both development and production builds, the script invokes `AstroContent.generate()` to create the JSON data files that Astro consumes.

```javascript
// bin/prepare (dev / full commands)
AstroContent.generate();   // ← generates pages for Astro

```

This step ensures that all snippet data, collection metadata, and page structures are serialized to disk before Astro begins its static site generation phase.

### Configuration in astro.config.mjs

Astro's behavior is controlled through `astro.config.mjs`, which defines the source directory and site metadata. The configuration points Astro to the `src/astro` directory where page components and layouts reside.

```javascript
// astro.config.mjs
export default defineConfig({
  site: settings.websiteUrl,
  srcDir: 'src/astro',
  // …
});

```

This configuration separates Astro's rendering layer from the content preparation logic, maintaining a clean architectural boundary between data generation and presentation.

## Content Generation for Astro

### Generating JSON Bundles with astroContent.js

The [`src/lib/astroContent.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/astroContent.js) module acts as the bridge between the project's content models and Astro's static generation pipeline. It reads the compiled content from `.content/pages/` and writes three primary JSON bundles: home, collections, and snippets.

```javascript
// src/lib/astroContent.js
static generateSnippetPages() {
  const snippets = process.env.NODE_ENV === 'development'
    ? Snippet.all
    : Snippet.scope('published');
  const pages = snippets.reduce((acc, snippet) => {
    acc[snippet.page.key] = snippet.page.serialize;
    return acc;
  }, {});
  fs.writeJson(settings.paths.out.snippets, pages, ...this.outputParams);
}

```

These JSON files serve as the data source for Astro's page components, allowing the static site generator to render pages without accessing the database or content management system at build time.

### Data Flow from Snippet Models to Static Files

The content flow follows a unidirectional pattern: raw snippet files are parsed into model objects, serialized to JSON via `AstroContent.generate()`, and finally consumed by Astro components during the static build. This decoupling allows the project to maintain complex content relationships while serving a purely static, edge-cached website.

## Page Rendering and Component Architecture

### Dynamic Route Handling in Astro Components

Astro handles dynamic routing through file-based routing conventions. The snippet page component at `src/astro/pages/[lang]/s/[snippet].astro` demonstrates how Astro receives pre-generated data via props and renders the final HTML.

```astro
---
// src/astro/pages/[lang]/s/[snippet].astro
const { snippet, breadcrumbs, journey, pageDescription, structuredData } = Astro.props;
---
<Layout title={snippet.title} description={pageDescription} …>
  <main slot="main-content">
    <Breadcrumb breadcrumbs={breadcrumbs} />
    <SnippetContent snippet={snippet} />
    {journey && <Pagination journey={journey} />}
    <PreviewList contentItems={recommendations}>
      <h2 slot="title">More like this</h2>
    </PreviewList>
    <ContentComponentsFallback />
  </main>
  <TableOfContents tableOfContents={snippet.tableOfContents} slot="side-bar" />
</Layout>

```

This component architecture leverages Astro's partial hydration capabilities, ensuring that only essential JavaScript ships to the browser while the core content remains static HTML.

### Layout and UI Composition

The `Layout.astro` component provides the base HTML structure, while specialized components like `SnippetContent`, `TableOfContents`, and `PreviewList` compose the user interface. This modular approach allows the project to maintain consistent styling and behavior across hundreds of snippet pages while keeping individual components lightweight and focused.

## Performance Benefits Over Next.js

The migration from Next.js to Astro in the 30 seconds of code project delivers measurable performance improvements. Astro's **zero-JavaScript-by-default** approach eliminates the client-side hydration overhead that characterized the previous Next.js implementation. By shipping only static HTML for content pages and selectively hydrating interactive components, the site achieves faster **Time to First Byte (TTFB)** and improved **Core Web Vitals** scores. The build process remains efficient despite the large volume of snippets, as Astro's static generation handles the [`home.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/home.json), [`collections.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/collections.json), and [`snippets.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/snippets.json) bundles without requiring runtime database queries.

## Summary

- **Astro acts as the SSG engine** for the 30 seconds of code website, replacing the previous Next.js stack to improve performance and reduce JavaScript overhead.
- **Content preparation** occurs in `bin/prepare` and [`src/lib/astroContent.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/astroContent.js), which serialize snippet data into JSON bundles that Astro consumes at build time.
- **Configuration** is centralized in `astro.config.mjs`, pointing Astro to the `src/astro` directory for page components and layouts.
- **Dynamic routing** uses file-based conventions like `[lang]/s/[snippet].astro` to render individual snippet pages from pre-generated props.
- **Performance gains** stem from Astro's static HTML generation and minimal client-side JavaScript, resulting in faster load times and better SEO compared to the previous implementation.

## Frequently Asked Questions

### Why did 30 seconds of code switch from Next.js to Astro?

The project migrated to Astro to eliminate unnecessary JavaScript overhead and improve static site performance. While Next.js required client-side hydration for pages, Astro generates pure static HTML by default, resulting in faster page loads, better Core Web Vitals scores, and reduced hosting costs on Netlify.

### How does Astro receive content data in this project?

Astro consumes pre-generated JSON bundles rather than querying a database at build time. The `AstroContent.generate()` method in [`src/lib/astroContent.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/astroContent.js) serializes snippet models into three JSON files—[`home.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/home.json), [`collections.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/collections.json), and [`snippets.json`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/snippets.json)—which Astro page components import via `Astro.props` during static generation.

### What files control Astro's configuration and content generation?

The primary configuration lives in `astro.config.mjs`, which defines the source directory (`src/astro`) and site URL. Content generation is handled by [`src/lib/astroContent.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/astroContent.js), while the build orchestration script `bin/prepare` triggers the generation process. Page routing and rendering logic resides in `src/astro/pages/`, including dynamic routes like `[snippet].astro`.

### Does Astro handle dynamic routing for snippet pages?

Yes, Astro uses file-based routing to handle dynamic snippet pages. The component at `src/astro/pages/[lang]/s/[snippet].astro` defines a dynamic route that matches URL patterns like `/en/s/array-flatten`. During the build process, Astro generates static HTML files for every snippet by iterating over the pre-generated JSON data, creating optimized pages without requiring a server at runtime.