Rift Logo RiftJS
$ npm create rift@latest

Rift. Static, but Alive.

A static site generator for developers who don’t want opinions. Markdown, HTML, TS. No magic. Just output.

No Framework

Bring your own templating engine or just render HTML. We don't care.

Controller Files

Need dynamic data? Write a .controller.ts file and export params() and render().

Static Done Right

Everything compiles to raw HTML. No client JS unless you say so.

Modular & Pluggable

Rift is built to be extended. Use plugins or write your own.

// src/rift.config.ts
import { defineConfig } from "@riftjs/rift";
import { 
    njkPlugin, 
    markdownPlugin,
    staticAssets,
    sitemapPlugin,
    i18nPlugin,
    minifyPlugin,
    rssPlugin
} from "@riftjs/plugins";

// Configure your plugins to your needs
export default defineConfig({
    baseUrl: "https://riftjs.dev",
    plugins: [
        njkPlugin(),
        markdownPlugin(),
        staticAssets([
            {
                src: "./assets/**/*",
                dest: "./"
            }
        ]),
        sitemapPlugin({
            exclude: ["/404", "/assets/*"],
        }),
        i18nPlugin({
            locales: ["en", "es"],
            defaultLocale: "en",
        }),
        minifyPlugin(),
        rssPlugin({
            collections: ["posts"],
            permalink: ({ collection, locale, params }) => `/${locale}/post/${params.slug}`,
        }),
    ]
});
    

Metadata & Frontmatter

Rift uses frontmatter to define metadata for your pages.

---
permalink: /post/my-first-post
date: 2023-10-01
tags: [rift, static site generator]
description: This is a description of my first post.
---
<h1>My First Post</h1>
<p>This is the content of my first post.</p>

Control your data

Simple code. Full control over how your pages are created.

// src/controllers/blog.controller.ts
export function params() {
    return await getContent("posts/**/*.md", item => ({
        ...item.metadata,
        content: item.content,
    }))
}

export async function permalink({ locale, params }) {
    return `/${locale}/post/${params.slug}`;
}

Internationalization

Rift supports i18n out of the box.

// src/pages/page.rift
<span i18n="hello-world">Hello World</span>
// src/locales/en.json
{
    "hello-world": "Hello World"
}
// src/locales/es.json
{
    "hello-world": "Hola Mundo"
}
// src/pages/blog.controller.ts
export function params({ locale }) {
    return await getContent(`posts/**/*.${locale}.md`, item => ({
        ...item.metadata,
        content: item.content,
    }))
}

Project Structure

Rift is designed to be simple and easy to understand.

πŸ“ src
β”œβ”€β”€ πŸ“ assets       β†’ Static assets like images, icons
β”‚   └── πŸ–ΌοΈ logo.png     β†’ Your site logo
β”œβ”€β”€ πŸ“ controllers  β†’ Controller files that export params/render
β”‚   └── βš™οΈ blog.controller.ts
β”œβ”€β”€ πŸ“ locales      β†’ Translation/localization JSON files
β”‚   β”œβ”€β”€ 🌐 en.json
β”‚   └── 🌐 es.json
β”œβ”€β”€ πŸ“ pages        β†’ `.rift` files that define routes and layout
β”‚   β”œβ”€β”€ πŸ“„ index.rift
β”‚   └── πŸ“„ post.rift
β”œβ”€β”€ πŸ“ content        β†’ Markdown content per locale
β”‚   β”œβ”€β”€ πŸ“ post1.en.md
β”‚   β”œβ”€β”€ πŸ“ post1.es.md
β”‚   β”œβ”€β”€ πŸ“ post2.en.md
β”‚   └── πŸ“ post2.es.md
βš™οΈ rift.config.ts   β†’ Project config file

Join the Community

Join our Discord community and follow us on Twitter for updates.

Showcase

Check out some amazing sites built with Rift.

Get Started with Rift

Ready to build your next static site? Start your journey with Rift today.

Explore the Docs