Oriel

$npm i @orieljs/framework
Early alpha. The full release is on its way.

Oriel is a Laravel-style, full-stack TypeScript framework for Node and Bun. Routing, models, queues, mail, validation and auth arrive together, designed as one typed toolkit, so you can build the whole app and not just the API.

Everything you reach for in Laravel has a home here, with types all the way down: route names, validated input, model attributes and the props you hand to your pages.

routes/web.ts
Route.get('/', () => inertia('Welcome'))
Route.resource('posts', PostController)

Route.middleware(['auth']).group(() => {
  Route.get('/dashboard', [DashboardController, 'index'])
})
app/Http/Controllers/PostController.ts
export class PostController extends Controller {
  async store() {
    const data = await StorePostRequest.validate()
    const post = await Post.create(data)
    return redirect().route('posts.show', post)
  }
}
RoutingModelsQueuesMailCacheAuthViewsEventsOriel

Why Oriel?

Node has fast servers and good ORMs, but you still wire a dozen libraries together before you ship a login page. Laravel showed a better way: one framework where every piece already knows the others.

What comes in the box?

HTTP and routing, a console, an ORM, validation, auth and sessions, queues, mail and notifications, cache, events, files, logs and views. Each part is its own package, and they all share one container, one config and one set of contracts.

Routing and controllers

Named routes, groups, middleware and model binding. Every route name is typed, so a typo in a link fails the build, not the user.

app/Http/Controllers/PostController.ts
export class PostController extends Controller {
  async store() {
    const data = await StorePostRequest.validate()
    const post = await Post.create(data)
    return redirect().route('posts.show', post)
  }
}

Models and migrations

An Eloquent-style ORM on Postgres, MySQL and SQLite, with relations, scopes, eager loading, factories and seeders.

app/Models/Post.ts
export class Post extends Model {
  protected override fillable = ['title', 'body']

  author() {
    return this.belongsTo(User)
  }
}

const posts = await Post.with('author').paginate(15)

Queues and mail

Push slow work onto Redis or your database. Jobs, batches, retries and a scheduler, with mail and notifications that queue themselves.

app/Jobs/SendInvoice.ts
export class SendInvoice extends Queueable {
  constructor(public order: Order) {
    super()
  }

  async handle() {
    await Mail.to(this.order.email).send(new Invoice(this.order))
  }
}

SendInvoice.dispatch(order).onQueue('billing')

And more

  • Validation

    Laravel's rule strings and form requests that return typed, validated data.

  • Auth and sessions

    Guards, sessions, hashing, encrypted cookies and API tokens, ready from the start.

  • Cache and events

    Memory, file, database and Redis stores with atomic locks, and queued listeners.

  • Inertia and Live

    Pages in React, Vue, Svelte, Solid or Angular, or server-driven Live components.

  • A real console

    Generators, migrations, workers and your own commands, all behind one oriel CLI.

  • Files and logs

    Local and cloud disks behind one API, and channels for every kind of log.

Three commands to a running app

Pick a starter kit, and you get auth, a database, queues and your frontend wired together from the first command.

Terminal
$npx create-oriel-app blog
Created blog with the React starter kit
$cd blog && node oriel migrate
Migrated users, sessions and jobs
$node oriel serve
Server running on http://localhost:3000

The first alpha is on npm. Follow along while the rest lands.