Guren を一目で
Bun で動く、Laravel のような書き心地のフルスタック TypeScript フレームワークです。
ドキュメント
ルーティング、モデル、認証、キューまで全サブシステムのガイドと、動くアプリを作る 2 つのコース。1 つは自分で書き、もう 1 つはコーディングエージェントに任せます。どのページも実行できるコードから始まります。
Bun で動く、Laravel のような書き心地のフルスタック TypeScript フレームワークです。
このページでは、Hono・Next.js・AdonisJS・Laravel と比べたときの Guren の立ち位置と、Guren が今の設計になっている理由を、長所も短所も含めて整理します。
Bun にはランタイム、パッケージマネージャ、バンドラ、テストランナーが入っていて、開発サーバーで HTML ページと API ルートを一緒に配信できます。ただしフルスタックフレームワークは含まれておらず、Bun の公式ドキュメントにもそう書かれています。
このガイドは 2 部構成です。Part A では、Docker もデータベースサーバーも使わずに、SQLite で新しい Guren アプリを 5 分ほどで動かします。Part B では、Postgres や MySQL、環境変数、機能ジェネレーター、本番ビルドといった本格的なセットアップを扱います。まず Part A を進め、必要になったら Part B に戻ってきてください。
このツアーでは、GET /posts という 1 つのリクエストを追いかけながら、Guren アプリのレイヤーを順に見ていきます。ルート、コントローラー、バリデーション、モデル、リソース、Inertia ページを通り、最後にテストで確かめます。全体像をつかむためのページなので、細部は各所に置いたガイドへのリンクからたどってください。
Guren アプリの設定は config/ に置きます。ここに置くファイルは次の 2 種類です。
Guren は、Laravel の設計思想を TypeScript で組み立て直し、Bun・Hono・Inertia.js・React・Drizzle ORM をまとめたフルスタック MVC フレームワークです。このページでは、ルーティングからレスポンスを返すまでの流れと、主なコンポーネントを説明します。
ルートは、メソッドと URL の組み合わせを、それに応答するコード(コントローラーのアクションかインラインハンドラー)に結び付けます。アプリケーションはそれぞれ 1 つの Router を持ちます。ルートファイルは registrar(そのルーターを受け取ってルートを登録する関数)を export し、src/app.ts がその registrar を createApp() に渡します。
コントローラーは HTTP リクエストを受け取り、モデルを通してデータを取得して、Inertia のページや JSON でレスポンスを返します。コントローラーはすべて app/Http/Controllers/ に置き、フレームワークの Controller 基底クラスを継承します。このガイドでは、routes/web.ts で定義したルートとコントローラーをつなぐ方法も説明します。
ミドルウェアは、リクエストの前後で処理を挟む仕組みです。コントローラーのアクションの前や後に処理を足したり、アクションの代わりにレスポンスを返したりできます。Guren は Hono のミドルウェアの仕組みをそのまま使っており、付ける場所は次の 3 つです。
CSRF(Cross-Site Request Forgery)は、悪意のあるサイトが認証済みユーザーになりすましてフォームを送信する攻撃です。Guren にはセッションと連携する CSRF ミドルウェアが組み込まれており、これを使って防ぎます。
リクエストの入力をスキーマで検証し、型の付いたパース済みの値を受け取ります。入力が不正なときは 422 のレスポンスを返して終わります。Inertia のリクエストなら、フィールドごとのエラーメッセージを付けてフォームへリダイレクトします。
リクエストの中で投げられた例外は、どこで投げられても ExceptionHandler に届き、報告するかどうかとクライアントに何を返すかがそこで決まります。カスタマイズはサービスプロバイダーから行い、その場で立て直したいエラーだけをコントローラーの try/catch で扱います。返す内容は、開発環境と本番環境で変わります。
Guren では、Drizzle のテーブルから作ったモデルを通してデータベースを読み書きします。クエリの API は Laravel の Eloquent に近い形で、スキーマから型が付きます。新しいアプリは SQLite を使うので準備は要らず、PostgreSQL、MySQL、Aurora Serverless へは設定を変えるだけで切り替えられます。
Guren では、Inertia.js と React を組み合わせてシングルページアプリのような操作感を作ります。コントローラーが Inertia レスポンスを返し、フロントエンドが resources/js/pages/ の下にある React コンポーネントを描画する、という分担です。サーバーが Inertia プロトコルのどこまでを実装しているかは Inertia プロトコル対応を参照してください。
Guren は Inertia のサーバーアダプタを @guren/core に自前で持っており、@inertiajs/react 3 が使う Inertia プロトコルに沿って実装しています。このページはその対応表で、プロトコルのどの部分を実装していてどの部分を実装していないか、それぞれの説明がどのガイドにあるかをまとめています。Laravel、Rails、AdonisJS のアダプタを使っていた方は、まずこのページを読み、次にフロントエンドガイドを読んでください。
this.view() は、JSX コンポーネントをサーバーでレンダリングし、ただの HTML レスポンスとして返します。this.inertia() と対になる、ハイドレーションしない側の仕組みです。ブログ記事やドキュメント、マーケティングページのように、公開されていて読むのが中心のページに向いています。返すドキュメントにはクライアントのフレームワークも、ハイドレーションも、Inertia のページペイロードのスクリプトも含まれません。guren.dev のブログ記事も、この仕組みで配信しています。
コマンド 1 つでアプリにログイン、新規登録、パスワードリセットを追加し、ルートを保護して、コントローラーでログイン中のユーザーを読めるようにします。このページの前半では生成されるものの使い方を、後半では動きを変えたいときのためにセッション、ガード、ユーザープロバイダーを説明します。
Guren には、「GitHub / Google / Discordでサインイン」のようなログインを作るための OAuth 2.0 認可コードフローが入っています。リダイレクト、CSRF対策を含むstateの管理、トークンの交換、プロフィールの取得は Guren が受け持つので、アプリ側で書くのはログイン用のコントローラーと、セッションへのログイン処理だけです。
認可は、認証済みのユーザーにどの操作を許すかを決める仕組みです。Guren の認可は、Laravel を参考にしたポリシーベースの設計になっています。
API リクエストの認証には、Guren の API トークンを使えます。トークンは保存する前にハッシュ化され、abilities(スコープ)と有効期限を指定できます。
Guren のパスワードリセット機能は、トークンの生成、検証、有効期限をまとめて扱います。トークン自体は保存せずに署名し、ストアには中身の読めないトークン ID だけを渡します。
Guren のメール確認機能は、トークンの生成、検証、有効期限をまとめて扱います。トークン自体は保存せずに署名し、ストアには中身の読めないトークン ID だけを渡します。
Guren には、データを暗号化するユーティリティと、パスワードを安全にハッシュ化するユーティリティが入っています。
Guren のイベントシステムを使うと、アプリケーション内のコンポーネント同士を疎結合に保てます。起きた出来事をイベントとして発行しておけば、アプリの別の部分がそれをリッスンして反応できます。
キューを使うと、メール送信、アップロードの処理、外部 API の呼び出しといった時間のかかる処理を、リクエストの処理から切り離せます。コントローラーはジョブをディスパッチしてすぐにレスポンスを返し、ジョブはあとからワーカープロセスが取り出して実行します。
キャッシュは、データベースのクエリや計算のような重い処理の結果をキーに保存し、次のリクエストですぐに読み出せるようにする仕組みです。bunx guren add cache で追加し、CACHESTORE で保存先を選び、コンテナから cache として取り出して使います。
Guren ではメールの送信を Fluent API で書け、配信に使うトランスポートを複数使い分けられます。キューと組み合わせれば非同期に送れ、HTML テンプレートや添付ファイルも扱えます。
Guren では、メール、データベース、Slack など複数のチャンネルへの通知を 1 つの API で送れます。通知はクラスとして書くので、使い回しやすく、テストも簡単です。
Guren のブロードキャスティングは、接続しているクライアントにイベントをリアルタイムで届ける仕組みです。ライブ通知、チャットアプリケーション、リアルタイムのダッシュボードといった機能を作るときに使います。
Guren のファイルストレージ API を使うと、ローカルのファイルシステム、Amazon S3、その他のクラウドストレージを、同じインターフェースで同じように扱えます。
アタッチメントは、アップロードされたファイルをモデルに結び付ける仕組みです。「Post は cover 画像を 1 つと images を複数持つ」とモデルに宣言すると、ファイルはストレージディスクに保存され、1 つの attachments テーブルで管理されます。画像のバリデーションと、サムネイル用のバリアント生成も最初から入っています。宣言をモデルに書くので、コレクション名、one/many の種別、バリアント名はどれもコンパイル時に検査されます。
Guren では、定期実行するタスクをアプリケーションの中で Fluent API を使って定義します。cron のエントリをいくつも管理しなくても、タスクのスケジュールをすべてコードに書けます。
コンソールコマンドを使うと、バックフィルや単発のメンテナンス、レポート生成といった処理をターミナルから実行できます。コマンドの中でも、HTTP ハンドラと同じモデル、サービス、コンテナをそのまま使えます。
レート制限は、アプリケーションを乱用から守るための仕組みです。Guren のレート制限は柔軟に設定でき、保存先のストレージを選べるほか、制限のキーを作る関数を差し替えたり、固定ウィンドウとスライディングウィンドウのどちらのアルゴリズムを使うかを選んだりできます。
Guren のロギングは、RFC 5424 に沿ったログレベル、複数のチャンネル、コンテキスト付きの記録に対応しています。
Guren のヘルスチェックを使うと、アプリケーションが依存しているサービスの状態をまとめて監視できます。ロードバランサーやオーケストレーター、監視ツールから見える /health エンドポイントを用意するときに使います。
Gurenには、国際化に必要なものが一通りそろっています。ファイルで管理する翻訳カタログ、リクエストごとのロケール検出、コントローラーとReactページで使う翻訳ヘルパー、15を超える言語の複数形ルール、型付きの翻訳キー、カタログの整合性チェックです。
APIリソースは、モデルを API レスポンスに変換する層です。モデルのデータをどういう JSON にするかを、フィールド単位で細かく決められます。
@guren/plugin-markdownは、markdownをHTMLにレンダリングするプラグインです。デフォルト設定のままで安全に使えるようにしてあり、GitHub Flavored Markdown、dangerouslySetInnerHTMLに渡しても安全なサニタイズ済みの出力、GitHubスタイルのアラート、見出しアンカーに対応し、shikiによるコードハイライトも追加できます。guren.dev自身のdocsとブログも、このパイプラインでレンダリングしています。
TestApp を使うと、アプリを HTTP 越しにテストできます。本物のミドルウェアとルートを通してリクエストを送り、レスポンスをアサートします。このページでは、ユーザーとしてログインした状態でのテスト、開発用データベースとの切り分け、メール・イベント・キューのフェイクも扱います。
create-guren-app で生成したアプリを本番環境へ出すまでの手順をまとめます。PostgreSQL を使える環境があるものとします。
Guren は AWS Lambda の Node.js ランタイムで動きます。バンドルは公式プラグイン @guren/plugin-lambda が受け持ち、HTTP、キュー、スケジュールタスク、CLI コマンド、静的アセットまでの一式は CDK コンストラクトがプロビジョニングします。
@guren/plugin-cloudflare を使うと、Guren を Cloudflare Workers 上で動かせます。データベースには D1 を使います。このガイドでは、まっさらなアカウントからデプロイが終わるまでをひと通り説明します。
GA(正式リリース)までに整えておきたい、最低限の運用基準をまとめます。
AI エージェントがコードを書く速さに、人が手でドキュメントを正しく保つ作業は追いつきません。Guren はこの問題に 1 つの原則で応えます。
文書で書いた仕様は議論になりがちですが、顧客が実際にクリックできる仕様なら具体的な訂正が返ってきます。プロトタイプモードを使うと、バックエンドがまだ何もない段階で機能の画面を作れます。作った画面はサーバーのいらない静的ファイルホストに置いて顧客に触ってもらい、そのあと同じコードからバックエンドの開発を始められます。顧客に見せたページが、そのまま出荷するページになります。
実装計画は、変更の設計をコードより先に JSON で書いておくドキュメントです。Guren は計画をアプリケーションと突き合わせて検査し、レビュー用のページとして描画します。承認すると計画に基準点が刻まれ、作業はステップに分けられ、どこまで実装できたかはコードから読み取られます。進捗は実装したエージェントの自己申告ではなく、plan:status と plan:verify がスキーマ、ルートグラフ、コントローラー、ページ、テスト結果から判定します。
このページでは、計画のファイルそのもの(セクション、要素の id と change、受け入れ振る舞い、質問、コマンド)を説明します。計画を描画し、承認し、実装する流れは実装計画にあり、このページで使う言葉(要素、振る舞い、ステップ)はその用語の表で定義しています。
plan:next は、scaffold と tests のステップを plan:scaffold で書くよう指示します。plan:scaffold は、承認済みの計画からコードとテストの雛形を書き出します。このページでは、書き出すもの、残しておくもの、拒否する場合を説明します。前後の流れは実装計画に、planned や wired といった要素の状態は進捗を読むにあります。
このページには、承認と検証の判定の規則をまとめています。判定が意外だったときに参照してください。規則が使われる流れは実装計画に、用語はその用語の表にあります。
AI エージェントは MCP を通じてアプリケーションを呼び出します。Guren では、エージェント向けにアプリケーションをもう 1 つ書く必要はありません。エージェントツールは、ルートがすでに持っているコントラクトから導出されます。ルートの params・query・body スキーマがツールの入力スキーマに、output スキーマがツールの出力スキーマに、ミドルウェアチェーンが検査するポリシーがツールの認可になります。
ルートをエージェントツールとして公開したあと(エージェントインターフェースを参照)、エージェントに何を許すかを決め、実際に何をしたかを残す仕組みが 3 つあります。
AI エージェントは、アプリケーションの中で言語モデルを呼び出すクラスです。エージェントがアプリケーションに触れる手段は、ルートがすでに宣言しているエージェントツールだけです。@guren/plugin-ai は Vercel AI SDK の上に作られていて、プロバイダとの通信は SDK が受け持ちます。モデルがどのルートを誰として呼べるか、何を記録するかは、プラグインが決めます。
永続エージェント(durable agent)は、アプリケーションが自分でホストする、長く動き続けて状態を持つプロセスです。アプリケーションには、ルートがすでに宣言しているエージェントツールを通してしかアクセスしません。
create-guren-app で作ったアプリには、AI エージェント向けのハーネスが入っています。コーディングエージェントに Guren のアプリでの作業のしかたを伝えるファイルと、作業中に Guren のチェックを走らせる hooks です。このページでは、エージェントごとに入るもの、hooks の動き、agent:init と agent:sync によるファイルの管理を説明します。
bunx guren graph は、アプリのルート、コントローラー、モデル、Inertia ページ、ミドルウェア、バリデーター、ポリシー、テストと、それらを結ぶ根拠を出力します。bunx guren runtime:errors は、開発中のアプリで最近起きたサーバーエラーを一覧します。コーディングエージェントは同じデータを MCP で読めて、Dev Center ではどちらもブラウザで確認できます。
このガイドでは、ユーザー登録とログイン、ログインしないと見られないルートを持つアプリを作ります。空のディレクトリから始めて、認証の流れができあがるまで 10 分もかかりません。
このガイドでは、Guren で JSON API を作って公開するまでの手順を説明します。API 専用プロジェクトを作成し、データベースのスキーマを定義して、バリデーション付きのコントローラーを書き、最後にエンドポイントを試します。
このガイドでは、ローカルで開発してきた Guren アプリケーションを本番環境に載せるまでの手順を、Bun を使った Docker ベースのデプロイを例に説明します。
Guren で開発しているとよく出会う問題と、その解決方法をまとめました。問題が起きたら、各パッケージのドキュメントを読む前に、まずこのページを確認してください。
Guren には CLI が 2 つ付いています。
check、audit、gate、introspect、doctor の一覧は CLI リファレンスにあります。このページには、その裏にある規則をまとめています。audit の Policy ルールが見るもの、audit の指摘の抑制方法、introspect が実行するもの、エージェント向けのルートとインプロセスエージェントに追加される規則、アーキテクチャ境界、チェックが登録済み(起動はしていない)アプリから読む事実です。
このガイドでは、Guren プラグインを作り、テストして公開するまでの手順を説明します。
| ランタイム | バージョン | ステータス |
アプリを新しいバージョンに上げるときは、このガイドを使います。下の手順に沿って進めてください。移行メモはリリース(GitHub のリリースに付いたバージョン)ごとに、新しいものから順に並んでいます。またいだリリースの分を、古いものから順に当てはめます。
本番で使ってもらうために、リリースについて最低限守る約束をまとめます。
Guren のドキュメントによく出てくる言葉を、初めての人向けに短く説明します。ここにない用語は、それぞれのガイドの中で補足しています。
この章では、Guren アプリを雛形から作り、雛形に何が用意されているかを読んでいきます。次に、テストを先に書いてから変更をひとつ手で加えます。その次の変更はコーディングエージェントに任せ、ハーネスがその作業をどう検査するかを確認します。最後に、どこでも動かせるコンテナイメージを作ります。以降の章もすべて、ゲートが通り、コミットが済み、いつでもリリースできる状態で終わります。
第 1 章で作ったアプリには、自分で書いていないページが 1 つだけありました。この章では、次のページを空のファイルから書いていきます。書く順序は、このコースでこの先ずっと使うもので、失敗するテスト、ルート、コントローラー、ページの順です。そのあと 2 つ目のページのテストを先に書いてエージェントに任せ、編集中のファイルに合ったルールをハーネスが読み込ませる動きを確認します。
ブログには投稿が必要で、投稿にはそれを保存する場所が必要です。この章では最初のテーブルを定義し、マイグレーションを生成して適用したうえで、テーブルを読むモデルと、投稿を表示する 2 つのページを作ります。そのあと作成フォームのテストを先に書いてエージェントに任せ、scaffold スキルのおかげでエージェントがファイルを手で書かずにジェネレーターを使う流れを確認します。
第 3 章では、スキーマをコントローラーの中に書き、ページにはフィールドをそのまま詰めたオブジェクトを渡していました。この章では、そのどちらにも決まった置き場所を用意します。1 つはバリデーターファイルで、人が読んで分かるエラーメッセージを持たせ、ルート・コントローラー・フォームの 3 か所で共有します。もう 1 つはリソースクラスで、ブラウザから投稿がどう見えるかをここで決めます。
ここまでのブログには、誰が操作しているかという区別がありませんでした。この章でユーザーを追加します。用意するのは、パスワードハッシュを保存するテーブル、ハッシュ化を受け持つモデル、セッションとそれに伴う CSRF 保護、そして手で組み立てる登録・ログイン・ログアウトです。そのあとプロフィールページをテストで仕様にしてエージェントに任せ、エージェントがモデルに手を付ける前に guren context User から何を受け取るのかも確認します。
ブログにユーザーはできましたが、サインインしているかどうかを確かめている箇所はまだありません。ゲストでも投稿を書き、編集し、削除できてしまい、guren audit も第 3 章からずっとそれを指摘しています。
第 6 章では、投稿を変更するにはサインインが必要という壁を作りました。ただ、扉はまだありません。サインインさえしていれば、誰でも他人の投稿を編集したり削除したりできます。これが認証(誰であるか)と認可(何を許されているか)の違いです。
第 6 章では、著者の id を集めて IN クエリを 1 本実行するヘルパー authorsOf を作りました。これでも動きますし、リレーションシップが内部でしていることもこれと同じです。この章では、このヘルパーを本来の仕組みに置き換えます。モデルに一度だけ宣言し、with() で読み込む belongsTo と hasMany です。
ブログには画像が欲しくなります。この章では Guren の attachments レイヤーを導入し、すべての投稿にカバー画像を付けます。画像は公開ディレクトリの外に保存し、署名付き URL で配信します。そのあとギャラリーの実装をエージェントに任せます。途中で guren check の検査項目がいくつか増え、「プライベート」を「公開」にしてしまう間違いをそのチェックが捕まえるところも確認します。
ここまでの処理は、検証して行を書き込み、リダイレクトするところまで、すべてリクエストの中で完結していました。この章では、リクエストの中で済ませるべきでない仕事を扱います。Bob が Ada の投稿にコメントすると Ada にメールが届きますが、メールサーバーの応答を待ってから Bob のブラウザにページを表示するようでは困ります。
計画とは、変更の設計をコードより先に JSON で書いたものです。この章では、勉強会を主催する機能について最初の計画をエージェントに書いてもらい、Guren が計画から描画するレビューページで中身を読みます。
第 2 章の終わりには、未決の質問が 1 つと足りない振る舞いが 5 つという、直すものの一覧が残りました。この章では、このレビュー結果をエージェントに渡して計画を直してもらい、変更を確かめてから承認します。ループの中で、承認だけは読者が自分で行うステップです。
承認した計画を、この章でエージェントに実装してもらいます。Guren が計画をステップに分け、エージェントはステップを 1 つずつ実装して、検証が通ったらコミットします。読者は、次のコミットが届く前にそれぞれのコミットを読んでいきます。
実装が終わると、plan.json は更新されなくなります。できあがったコードに合わせて、承認済みの計画を書き直す人はいないからです。それでも、計画に書かれていたこと (機能がある理由、守るべきルール、あえて外したこと) は、この先も必要になります。計画をクローズすると、その内容が次のエージェントが読むドキュメントに書き出されます。
1 本目の計画は追加だけで済みましたが、参加登録はそうはいきません。勉強会が自身への登録を把握し、勉強会のページに空き席を表示するには、すでに受け入れたコードに手を入れる必要があります。この章ではその変更を計画し、承認します。今回は「内容が正しいか」に加えて「ほかにどこへ影響するか」も確かめるので、レビューは一段難しくなります。
計画は、特定のコミットの時点のアプリを前提に承認されます。しかし実際の開発はそこで止まらず、同僚がリファクタリングをマージして、計画が前提にしていた名前が消えることもあります。この章では参加登録の計画を実装しながら、途中でわざとそうした変更を起こします。そして、設計が合わなくなったまま作業を続けようとするエージェントを、Guren がどう止めるかを確認します。