July 26, 2026

Starting a blog

Why the Guren blog is built with Guren, what the framework actually does, and what I plan to write here.

This is the first post on the Guren blog. I'll use it to say what the blog is for, and for anyone arriving cold, what Guren actually is.

The blog runs on Guren

The post list, this page, and the admin screen I wrote it in are all part of a Guren application. No external CMS, no static site generator.

The reason is simple: I can't recommend a framework I don't use myself. Writing documentation only gets you so far. Building something real is what surfaces the problems, and building this blog turned up a handful of bugs in the framework. All of them are fixed upstream now.

What Guren is

Guren is a full-stack TypeScript framework for Bun. It borrows its structure from Laravel, so routing, controllers, an ORM, authentication, queues, and mail all ship in the box.

Types connect all the way through

Route definitions, controllers, and page props are wired together through code generation.

// routes/web.ts
router.get('/posts/:id', [PostController, 'show']).name('posts.show')
// app/Http/Controllers/PostController.ts
export class PostController extends Controller {
  async show() {
    const { id } = this.validateParams(PostIdParamSchema)
    const post = await Post.findOrFail(id)   // throws a 404 on its own

    return this.inertia(pages.posts.Show, { post })
  }
}

pages.posts.Show is a generated constant, so deleting or renaming that component breaks the build. So does passing props the page never declared. On the frontend, <Link route="posts.show" params={{ id: 1 }}> checks the route name and its parameters too.

The point is to catch the kind of mistake you'd otherwise find in production, after a deploy, from a string you typed wrong six weeks ago.

Fewer decisions to make

Directory layout, file names, naming conventions: all settled. You don't spend time deciding where a controller goes. When you need something new, generate it.

bunx guren make:feature Post --fields "title:string,body:text,published:boolean"

That gives you the model, the routes, the controller, and the pages for a full CRUD feature.

Built with coding agents in mind

Guren ships commands that describe the project in a machine-readable form, check that routes, controllers, and pages still line up, and audit for missing validation or authentication.

bunx guren check    # routes, controllers, and pages agree
bunx guren audit    # validation, auth, raw SQL, secrets

Point an agent at those after it writes code and it can check its own work against the project's conventions instead of leaving all of it for you to catch in review.

What I'll write here

  • Release notes, with the reasoning that changelogs leave out
  • Design decisions, especially the ones where there was a real choice to make
  • What I learn from building things with Guren, including the parts that go badly
  • Short how-tos that aren't systematic enough for the documentation

I'd rather write about what I actually ran into than sell anything.

Getting started

bunx create-guren-app my-app

SQLite works out of the box, so there's nothing to set up before you have something running. The documentation takes it from there.

All of the code is public. If you spot something, issues and pull requests are equally welcome.

← All posts