### Install Bun with curl Source: https://guren.dev/docs/guides/getting-started Installs Bun 1.1 or later, the only prerequisite for the quickstart. Run this in a terminal on macOS, Linux, or Windows with WSL2. ```bash curl -fsSL https://bun.sh/install | bash ``` -------------------------------- ### queue:work command example Source: https://guren.dev/docs/guides/cli Example of starting the queue worker with the `queue:work` command. ```bash bunx guren queue:work ``` -------------------------------- ### agent:init example Source: https://guren.dev/docs/guides/cli Example of the agent:init command targeting codex and cursor agents. Installs the agent harness for the selected agents into an existing app, skipping files that already exist unless --force is used. ```bash bunx guren agent:init --target codex,cursor ``` -------------------------------- ### Scaffold and run a new Guren app with bunx create-guren-app Source: https://guren.dev/docs/guides/overview Run these four commands in order to scaffold a new Guren app with the default prompts (SSR and SQLite), move into the project directory, install dependencies (usually a no-op because the scaffolder already installed them), and start the development server. Afterward, open http://localhost:3333 to see the running app. ```bash bunx create-guren-app my-app # scaffold — accept the default prompts (SSR, SQLite) ``` ```bash cd my-app ``` ```bash bun install # usually a no-op: the scaffolder installs for you ``` ```bash bun run dev # start the dev server ``` -------------------------------- ### Install prototype mode with bunx guren add prototype or scaffold with create-guren-app --prototype Source: https://guren.dev/docs/guides/prototype-first Install the prototype fixture into an existing project, or scaffold a new app with prototype mode enabled from the start. The first command writes the fixture module, adds two scripts to package.json, and wires two options; the second creates a new app with the prototype setup included. ```bash bunx guren add prototype ``` ```bash bunx create-guren-app my-app --prototype ``` -------------------------------- ### Manual auth setup with bunx guren make:auth Source: https://guren.dev/docs/guides/authentication Manually sets up auth without the --install flag. Then register AuthProvider in src/app.ts, add createSessionMiddleware to your middleware stack (auto-added by AuthServiceProvider unless you opt out), and register registerAuthRoutes(router) from routes/web.ts. The --install flag is safe and idempotent. ```bash bunx guren make:auth ``` -------------------------------- ### Start the dev server with bun run dev Source: https://guren.dev/docs/guides/build-auth-app Starts the development server. Visit http://localhost:3333/register to create an account, then http://localhost:3333/login to sign in. ```bash bun run dev ``` -------------------------------- ### Start the database with bun run db:up Source: https://guren.dev/docs/guides/build-auth-app Starts the Postgres database using Docker Compose. ```bash bun run db:up ``` -------------------------------- ### systemd unit for Guren application Source: https://guren.dev/docs/guides/deployment Example systemd unit to run the Bun server as a service. Reload systemd, enable, and start with 'sudo systemctl enable --now my-app'. ```ini [Unit] Description=Guren Application After=network.target [Service] EnvironmentFile=/etc/guren/my-app.env WorkingDirectory=/var/www/my-app ExecStart=/usr/local/bin/bun run bin/serve.ts Restart=always [Install] WantedBy=multi-user.target ``` -------------------------------- ### Install @guren/plugin-mcp with bun Source: https://guren.dev/docs/guides/agent-interface Install and register the @guren/plugin-mcp package. The first command runs the plugin installer, the second adds it as a dependency. ```bash bunx guren plugin @guren/plugin-mcp bun add @guren/plugin-mcp ``` -------------------------------- ### Install @guren/plugin-markdown with bun Source: https://guren.dev/docs/guides/markdown Install the plugin with bunx and add it as a dependency. Run these commands in your project root. ```bash bunx guren plugin @guren/plugin-markdown bun add @guren/plugin-markdown ``` -------------------------------- ### queue:work options examples Source: https://guren.dev/docs/guides/cli Examples showing how to use the `queue:work` command with various options: `--queue`, `--max-jobs`, and `--stop-when-empty`. ```bash # Process jobs from default queue bunx guren queue:work # Process specific queue bunx guren queue:work --queue emails # Limit number of jobs bunx guren queue:work --max-jobs 100 # Stop when queue is empty bunx guren queue:work --stop-when-empty ``` -------------------------------- ### bunx guren --help Source: https://guren.dev/docs/guides/cli Shows CLI help. Run from project root; no global install required. ```bash bunx guren --help ``` -------------------------------- ### Running the Scheduler: Configure and start in app bootstrap Source: https://guren.dev/docs/guides/scheduling Shows how to configure the Scheduler with timezone, check interval, and logger, define a simple every-minute task, start it on app boot, and stop it on SIGTERM. ```TypeScript // app.ts import { Scheduler } from '@guren/core' const scheduler = new Scheduler({ timezone: 'Asia/Tokyo', checkInterval: 60000, // Check every 60 seconds logger: console.log, }) // Define schedules scheduler.schedule((schedule) => { schedule.call(() => console.log('Hello!')).everyMinute() }) // Start when app boots scheduler.start() // Stop on shutdown process.on('SIGTERM', () => { scheduler.stop() }) ``` -------------------------------- ### Start Bun server directly Source: https://guren.dev/docs/guides/deployment Starts the Bun server in production. Wrap with a process manager for reliability. ```bash NODE_ENV=production bun run bin/serve.ts ``` -------------------------------- ### Install the attachments layer Source: https://guren.dev/docs/tutorials/10-files Installs the attachments layer, adding storage providers, the attachments table, configuration, and the delivery route. ```bash bunx guren add attachments ``` -------------------------------- ### Scaffold authentication with bunx guren make:auth Source: https://guren.dev/docs/guides/authentication Scaffold the authentication stack with the CLI. The first command generates the full auth flow and installs dependencies; the second runs migrations, seeds, and starts the dev server. Use --minimal to skip registration and password reset, or --verify to add email verification. ```bash bunx guren make:auth --install ``` ```bash bun run db:migrate bun run db:seed bun run dev ``` ```bash bunx guren make:auth --install --minimal ``` ```bash bunx guren make:auth --install --verify ``` -------------------------------- ### Full Configuration Example Source: https://guren.dev/docs/guides/rate-limiting Complete example using MemoryRateLimitStore with custom keyGenerator, skip, and onRateLimited. Key is based on authenticated user ID or forwarded IP, skips admin users, and returns a custom JSON response with retryAfter. ```TypeScript import { createRateLimitMiddleware, MemoryRateLimitStore } from '@guren/core' const store = new MemoryRateLimitStore() const rateLimiter = createRateLimitMiddleware({ limit: 100, windowMs: 60 * 1000, // 1 minute store, keyPrefix: 'api:', headers: true, message: 'Rate limit exceeded. Please slow down.', statusCode: 429, // Key based on authenticated user or IP keyGenerator: async (ctx) => { const user = ctx.get('user') if (user?.id) { return `user:${user.id}` } return ctx.req.header('x-forwarded-for')?.split(',')[0] ?? 'unknown' }, // Skip for admin users skip: async (ctx) => { const user = ctx.get('user') return user?.role === 'admin' }, // Custom response onRateLimited: (ctx, retryAfter) => { return ctx.json({ error: 'Too many requests', retryAfter, documentation: 'https://api.example.com/docs/rate-limits', }, 429) }, }) ``` -------------------------------- ### Install plugin with bunx guren plugin Source: https://guren.dev/docs/guides/plugins Install a plugin via the Guren CLI. The `plugin` command installs the package with `bun add` when missing (use `--no-install` to skip), verifies compatibility (`--ignore-compatibility` to bypass), adds the provider import, registers it in `createApp({ providers })`, and applies `env` and `publishes` entries from the plugin's `gurenPlugin` manifest. `--force` overwrites already-published files. ```bash bunx guren plugin @guren/plugin-vercel ``` -------------------------------- ### Install @guren/plugin-cloudflare Source: https://guren.dev/docs/guides/cloudflare Installs the Cloudflare plugin and registers the `cloudflare:build` command. The plugin also scaffolds `wrangler.jsonc` on the first build. ```bash bunx guren plugin @guren/plugin-cloudflare bun add @guren/plugin-cloudflare ``` -------------------------------- ### Install and generate OpenAPI document Source: https://guren.dev/docs/guides/routing Installs the optional @guren/openapi package and generates an OpenAPI 3.1 JSON document to .guren/openapi.gen.json from route definitions. ```bash bun add @guren/openapi bunx guren openapi:generate ``` -------------------------------- ### Launch the Guren interactive console Source: https://guren.dev/docs/guides/cli Starts the framework-aware REPL, booting the application and preloading globals like `app`, `auth`, and models. Use `:help` for shortcuts and `:editor` for multiline input. ```bash bunx guren console ``` -------------------------------- ### Dockerfile for production deployment with Bun Source: https://guren.dev/docs/guides/deploy-production Multi-stage Dockerfile for a Bun-based Guren application. It installs production dependencies, builds the app, and creates a minimal production image that runs the start command. The production image copies node_modules, dist, public, and package.json from the build stages. ```dockerfile FROM oven/bun:1 AS base WORKDIR /app # Install dependencies FROM base AS deps COPY package.json bun.lock ./ RUN bun install --frozen-lockfile --production # Build the application FROM base AS build COPY package.json bun.lock ./ RUN bun install --frozen-lockfile COPY . . RUN bun run build # Production image FROM base AS production COPY --from=deps /app/node_modules ./node_modules COPY --from=build /app/dist ./dist COPY --from=build /app/public ./public COPY --from=build /app/package.json ./ ENV APP_ENV=production ENV PORT=3333 EXPOSE 3333 CMD ["bun", "run", "start"] ``` -------------------------------- ### Quick Start: Configure StorageManager and perform basic file operations Source: https://guren.dev/docs/guides/storage Sets up a StorageManager with a local disk and demonstrates storing, retrieving, checking existence, and deleting a file. ```TypeScript import { StorageManager } from '@guren/core' const storage = new StorageManager({ default: 'local', disks: { local: { driver: 'local', root: './storage/app', url: '/storage', }, }, }) // Store a file await storage.disk().put('avatars/user-1.jpg', imageBuffer) // Retrieve a file const content = await storage.disk().get('avatars/user-1.jpg') // Check if file exists const exists = await storage.disk().exists('avatars/user-1.jpg') // Delete a file await storage.disk().delete('avatars/user-1.jpg') ``` -------------------------------- ### Install and register guren-plugin-analytics Source: https://guren.dev/docs/guides/plugins Install the plugin with bun, then register it in the app's providers array. The plugin requires an API key and endpoint, which can be read from environment variables. ```bash bun add guren-plugin-analytics ``` ```typescript // src/app.ts import { createApp } from '@guren/core' import { analyticsPlugin } from 'guren-plugin-analytics' import { registerWebRoutes } from '@/routes/web' export const app = createApp({ routes: registerWebRoutes, providers: [ analyticsPlugin({ apiKey: process.env.ANALYTICS_API_KEY!, endpoint: 'https://analytics.example.com', }), ], }) ``` -------------------------------- ### Install prototype mode with bunx guren add prototype Source: https://guren.dev/docs/tutorials/15-prototype-first Run from your project root to install prototype mode. Writes one fixture file and patches three (resources/js/app.tsx, src/app.ts, package.json). None of the prototype code reaches a production bundle. ```bash bunx guren add prototype ``` -------------------------------- ### Install AWS SDK for DynamoDB Source: https://guren.dev/docs/guides/serverless Install the AWS SDK for DynamoDB to use the DynamoDB session driver provided by @guren/plugin-lambda. ```bash bun add @aws-sdk/client-dynamodb ``` -------------------------------- ### Install and deploy with @guren/plugin-vercel Source: https://guren.dev/docs/guides/deployment Install the Vercel plugin and scaffold the required files, then build and deploy the SSR app. The plugin targets SSR apps only; API-only apps should use Docker or Lambda instead. ```bash bunx guren plugin @guren/plugin-vercel bun add @guren/plugin-vercel ``` ```bash bun run vercel:build vercel deploy --prebuilt ``` -------------------------------- ### agent:sync example Source: https://guren.dev/docs/guides/cli Example of the agent:sync command. Refreshes framework-managed files (rules, skills, subagents, hooks) for every agent detected on disk, without overwriting user-owned files. ```bash bunx guren agent:sync ``` -------------------------------- ### Generate production Dockerfile with bunx guren deploy Source: https://guren.dev/docs/tutorials/01-zero-to-deployed Generates a production Dockerfile for the Guren app. The generated Dockerfile is a two-stage build: the first stage installs everything and runs `bun run build`; the second copies only runtime directories (`bin/`, `src/`, `app/`, `config/`, `routes/`, `public/`, `db/`, `.guren/`) into a slim image and starts `bun bin/serve.ts` with `NODE_ENV=production`. ```bash bunx guren deploy --target docker ``` -------------------------------- ### Install production dependencies with Bun Source: https://guren.dev/docs/guides/deployment Install only runtime dependencies on the deployment host. Omit --production if your environment builds assets during deployment and needs dev tooling. ```bash bun install --production ``` -------------------------------- ### Manual queue manager setup Source: https://guren.dev/docs/guides/queue Creates a queue manager with a memory driver and accesses the default driver. ```ts import { createQueueManager, MemoryDriver } from '@guren/core' const queue = createQueueManager({ default: 'memory', drivers: { memory: () => new MemoryDriver(), }, }) queue.driver() ``` -------------------------------- ### Quick Start: Schedule a daily callback Source: https://guren.dev/docs/guides/scheduling Creates a Scheduler instance and schedules a callback to run daily at 3 AM. The schedule is defined using the fluent API and the scheduler is started immediately. ```TypeScript import { Scheduler } from '@guren/core' const scheduler = new Scheduler() scheduler.schedule((schedule) => { // Run a callback every day at 3 AM schedule.call(async () => { await cleanupOldSessions() }).daily().at('03:00').name('cleanup-sessions') }) scheduler.start() ``` -------------------------------- ### Install Guren Lambda plugin Source: https://guren.dev/docs/guides/deployment Installs and registers the official AWS Lambda plugin. The CLI scaffolds src/lambda.ts (whose exports become Lambda handlers) and registers a lambda:build command. ```bash bunx guren plugin @guren/plugin-lambda bun add @guren/plugin-lambda ``` -------------------------------- ### Create a new plugin package with bun init Source: https://guren.dev/docs/guides/plugins Initializes a new npm package for a Guren plugin. Run these commands in a terminal to create the directory and start a new project. ```bash mkdir guren-plugin-analytics cd guren-plugin-analytics bun init ``` -------------------------------- ### Run test suite commands Source: https://guren.dev/docs/guides/testing Commands to run the full test suite, framework packages with Bun's test runner, example apps with Vitest, a single test file, and generate a test file. Framework packages use bun:test, while example apps and React components use Vitest with jsdom. ```bash # Full test suite bun run test # Framework packages (Bun test runner) bun run test:bun # Example apps (Vitest) bun run test:examples # Single file bun test path/to/file.test.ts # Generate a test file bunx guren make:test posts/PostController --runner bun ``` -------------------------------- ### Install Guren agent skills from catalog Source: https://guren.dev/docs/guides/cli Commands to install the Guren on-ramp skills from the gurenjs/agent-skills repository. Use the Claude Code plugin commands for Claude Code, and the Agent Skills CLI for other clients. Install at user scope to avoid writing into a project repository. ```bash # Claude Code claude plugin marketplace add gurenjs/agent-skills claude plugin install guren@gurenjs --scope user # Cursor, Codex, Copilot, OpenCode, Gemini CLI and others (Agent Skills CLI) npx skills add gurenjs/agent-skills ``` -------------------------------- ### Install @guren/plugin-agents and @guren/plugin-cloudflare with bun Source: https://guren.dev/docs/guides/durable-agents Use this command to install the agents and cloudflare plugins. The package must be in dependencies, not devDependencies, because the generated worker imports it and wrangler resolves it at deploy time. The guren cloudflare:build command refuses an app that hosts agents and only depends on it for development. ```bash bun add @guren/plugin-agents @guren/plugin-cloudflare ``` -------------------------------- ### Create Encrypter with generateKey Source: https://guren.dev/docs/guides/encryption Shows how to generate a 32-byte key and create an Encrypter instance. Includes an example with key rotation support using previousKeys. ```typescript import { Encrypter, generateKey } from '@guren/core' // Generate a new key const key = generateKey() console.log(key) // base64:... (32-byte key) // Create encrypter const encrypter = new Encrypter({ key }) // With key rotation support const rotatedEncrypter = new Encrypter({ key: newKey, previousKeys: [oldKey], }) ``` -------------------------------- ### Deploy with docker compose -f docker-compose.production.yml up -d Source: https://guren.dev/docs/guides/deploy-production Starts the production stack defined in `docker-compose.production.yml` in detached mode. ```bash docker compose -f docker-compose.production.yml up -d ``` -------------------------------- ### Sliding Window Store Setup Source: https://guren.dev/docs/guides/rate-limiting Uses a sliding window store for smoother rate limiting. ```ts import { SlidingWindowRateLimitStore } from '@guren/core' const store = new SlidingWindowRateLimitStore() const rateLimiter = createRateLimitMiddleware({ limit: 100, windowMs: 60 * 1000, store, }) ``` -------------------------------- ### Redis Store Setup Source: https://guren.dev/docs/guides/rate-limiting Configures Redis-backed rate limit stores for distributed applications. ```ts import { createRateLimitMiddleware } from '@guren/core' import { createRedisClient, RedisRateLimitStore, RedisSlidingWindowRateLimitStore } from '@guren/core/redis' const redis = createRedisClient({ url: process.env.REDIS_URL }) const limiter = createRateLimitMiddleware({ max: 60, windowMs: 60_000, store: new RedisRateLimitStore(redis), }) // Sliding-window variant for smoother limiting const sliding = createRateLimitMiddleware({ max: 60, windowMs: 60_000, store: new RedisSlidingWindowRateLimitStore(redis), }) ``` -------------------------------- ### Setup NotificationManager with channels Source: https://guren.dev/docs/guides/notifications Imports NotificationManager, MailChannel, and DatabaseChannel from '@guren/core', creates a NotificationManager instance, and registers 'mail' and 'database' channels. ```typescript import { NotificationManager, MailChannel, DatabaseChannel, } from '@guren/core' const notifications = new NotificationManager() // Register channels notifications .registerChannel('mail', new MailChannel(mailManager)) .registerChannel('database', new DatabaseChannel()) ``` -------------------------------- ### Register GitHub OAuth routes Source: https://guren.dev/docs/guides/oauth Registers the GitHub OAuth routes: GET /auth/github maps to the start action and GET /auth/github/callback maps to the callback action. ```ts import { Router } from '@guren/core' import GitHubOAuthController from '@/app/Http/Controllers/Auth/GitHubOAuthController' export function registerWebRoutes(router: Router): void { router.get('/auth/github', [GitHubOAuthController, 'start']) router.get('/auth/github/callback', [GitHubOAuthController, 'callback']) } ``` -------------------------------- ### Memory Store Setup Source: https://guren.dev/docs/guides/rate-limiting Configures a memory-based rate limit store with cleanup on shutdown. ```ts import { MemoryRateLimitStore } from '@guren/core' const store = new MemoryRateLimitStore(60000) // Cleanup every 60 seconds const rateLimiter = createRateLimitMiddleware({ limit: 100, store, }) // Cleanup on shutdown process.on('SIGTERM', () => { store.destroy() }) ``` -------------------------------- ### Programmatic worker setup Source: https://guren.dev/docs/guides/queue Creates a worker programmatically with custom queues, settings, and event handlers, then starts and stops it. ```ts import { Worker, MemoryDriver, createQueueManager, registerJob } from '@guren/core' import { SendWelcomeEmailJob } from '@/app/Jobs/SendWelcomeEmailJob' // Setup const queue = createQueueManager({ default: 'memory', drivers: { memory: () => new MemoryDriver(), }, }) const driver = queue.driver() // Register job classes (required for worker to find them) registerJob(SendWelcomeEmailJob) // Create and start worker const worker = new Worker(driver, { queues: ['high-priority', 'default', 'emails'], sleep: 1000, timeout: 60000, maxJobs: 0, // 0 = unlimited stopWhenEmpty: false, }, { // Optional event handlers jobProcessed: (job) => console.log(`Processed: ${job.name}`), jobFailed: (job, error, willRetry) => { console.error(`Failed: ${job.name}`, error.message, willRetry ? '(will retry)' : '') }, workerStarted: () => console.log('Worker started'), workerStopped: () => console.log('Worker stopped'), }) // Start processing await worker.start() // Graceful shutdown (waits for current job) await worker.stop() ``` -------------------------------- ### Change into the app directory Source: https://guren.dev/docs/tutorials/01-zero-to-deployed Step into the newly scaffolded app directory to continue with the tutorial. ```bash cd guren-blog ``` -------------------------------- ### bunx guren add commands for standard scaffolds Source: https://guren.dev/docs/guides/cli High-level scaffolds for common features. The golden path starts with auth and resource, then adds more as the app grows. ```bash bunx guren add auth bunx guren add admin bunx guren add resource posts --fields "title:string,body:text,published:boolean" bunx guren add queue bunx guren add mail bunx guren add events bunx guren add cache bunx guren add notifications bunx guren add storage bunx guren add attachments bunx guren add session bunx guren add broadcasting bunx guren add schedule bunx guren add lint bunx guren add prototype ``` -------------------------------- ### Scaffold an API project with create-guren-app Source: https://guren.dev/docs/guides/ship-api Scaffolds a new Guren API-only project named my-api with the api blueprint and Postgres database, then installs dependencies. ```bash bunx create-guren-app my-api --blueprint api --db postgres cd my-api bun install ``` -------------------------------- ### Test Endpoints with curl Source: https://guren.dev/docs/guides/ship-api Example curl commands for CRUD operations on the /api/tasks endpoint. Use these to create, list, show, update, and delete tasks after starting the dev server. ```bash # Create a task curl -X POST http://localhost:3333/api/tasks \ -H "Content-Type: application/json" \ -d '{"title": "Write docs"}' # List tasks curl http://localhost:3333/api/tasks # Show a task curl http://localhost:3333/api/tasks/1 # Update a task curl -X PUT http://localhost:3333/api/tasks/1 \ -H "Content-Type: application/json" \ -d '{"completed": true}' # Delete a task curl -X DELETE http://localhost:3333/api/tasks/1 ``` -------------------------------- ### Example Response Headers Source: https://guren.dev/docs/guides/rate-limiting Shows the rate limit headers returned when the limit is exceeded. ```http X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1705312800 ``` -------------------------------- ### Quick Start with LogManager facade Source: https://guren.dev/docs/guides/logging Use app.container.make('log') to resolve the default logger. Supports info, error, and channel-specific logging. ```ts // Resolve the logger from the container const Log = app.container.make('log') Log.info('Application started') Log.error('Something went wrong', { error: 'Connection failed' }) Log.channel('daily').warning('Disk space low') ``` -------------------------------- ### Running commands with bun run console Source: https://guren.dev/docs/guides/console Scaffolded apps expose the console as a `console` script. Examples show running a custom command and a command with arguments and options. ```bash bun run console send-digest bun run console users:create ada@example.com --admin ``` -------------------------------- ### Create Cache Facades from Container Source: https://guren.dev/docs/guides/cache Creates cache facades from an application container, enabling direct access to cache operations without passing a manager. Use this when you have an app container and want a convenient global cache interface. The example shows setting, getting, checking, and deleting a value with a TTL of 3600 seconds. ```ts import { createFacades } from '@guren/core' const { Cache } = createFacades(app.container) // Store a value (TTL in seconds) await Cache.store().set('user:1', { name: 'John' }, 3600) // Retrieve a value const user = await Cache.store().get<{ name: string }>('user:1') // Check if key exists const exists = await Cache.store().has('user:1') // Delete a value await Cache.store().delete('user:1') ``` -------------------------------- ### Create app and listen with port fallback Source: https://guren.dev/docs/guides/architecture Bootstraps the application by creating the app instance with routes and providers, then starts the HTTP server. The listen() call resolves to the actual bound address, which may differ from the requested port (e.g., when port 0 is used or a busy port triggers fallback). Read the returned port rather than assuming the requested one. ```ts const app = createApp({ routes: registerWebRoutes, providers: [DatabaseProvider, AuthProvider, EventServiceProvider], }) ``` ```ts const { url, port } = await app.listen({ port: 3333 }) console.log(`listening on ${url}`) // the port that is actually bound ``` -------------------------------- ### Production build and preview with bun run build and bun run preview Source: https://guren.dev/docs/guides/getting-started Builds the production bundle (emitting hashed client and server assets under public/assets/ plus manifests) and starts the production server locally to verify the build. ```bash bun run build bun run preview ``` -------------------------------- ### Install React Email dependencies Source: https://guren.dev/docs/guides/mail Install the required packages for using React Email with Guren. ```bash bun add @react-email/render react ``` -------------------------------- ### Install AWS SDK for Data API Source: https://guren.dev/docs/guides/database Adds the required driver package for the AWS Data API adapter. Run this when using the Aurora Serverless adapter. ```bash bun add @aws-sdk/client-rds-data ``` -------------------------------- ### Manual boot and fromFetch alternative Source: https://guren.dev/docs/guides/testing Shows the longer form of booting and using fromFetch. The arrow function is required because fetch reads instance state; unbound app.fetch throws. ```ts await app.boot() http = TestApp.fromFetch((request) => app.fetch(request)) ``` -------------------------------- ### Scaffold a new Guren app with create-guren-app Source: https://guren.dev/docs/guides/build-auth-app Scaffolds a new Guren application named my-auth-app with SSR mode and Postgres database, then installs dependencies. ```bash bunx create-guren-app my-auth-app --mode ssr --db postgres cd my-auth-app bun install ``` -------------------------------- ### Apply D1 migrations and run wrangler dev Source: https://guren.dev/docs/guides/cloudflare Run these commands to apply local D1 migrations and start the wrangler dev server. This catches runtime differences that a Bun dev server cannot. ```bash bunx wrangler d1 migrations apply my-app --local bunx wrangler dev ``` -------------------------------- ### Show what prototyping changed: git status --short Source: https://guren.dev/docs/tutorials/15-prototype-first Typical next step after installing prototype mode. It lists the new resources/js/prototype/index.ts fixture and the three patched files. ```bash git status --short ``` -------------------------------- ### Set up shiki code highlighting Source: https://guren.dev/docs/guides/markdown Install shiki as an optional peer dependency and configure it for code highlighting. Builds a fine-grained shiki/core highlighter with only the listed grammars and emits dual-theme output. Fences in unloaded languages fall back to plain text instead of throwing. ```bash bun add shiki ``` ```ts import { createMarkdownRenderer } from '@guren/plugin-markdown' import { createShikiHighlight } from '@guren/plugin-markdown/shiki' const renderer = createMarkdownRenderer({ highlight: createShikiHighlight({ themes: { light: 'github-light', dark: 'github-dark' }, langs: ['typescript', 'tsx', 'bash', 'json'], }), }) ``` -------------------------------- ### Log levels RFC 5424 example Source: https://guren.dev/docs/guides/logging Examples of all severity levels from emergency to debug, with warning also available as warn(). ```ts log.emergency('System is unusable') log.alert('Action must be taken immediately') log.critical('Critical conditions') log.error('Error conditions') log.warning('Warning conditions') // or log.warn() log.notice('Normal but significant conditions') log.info('Informational messages') log.debug('Debug-level messages') ``` -------------------------------- ### Scaffold a Guren app with create-guren-app Source: https://guren.dev/docs/tutorials/01-zero-to-deployed Run this command to scaffold a new Guren app named guren-blog with SSR mode, SQLite database, Claude agent harness, and Git initialization. The --mode ssr flag renders pages on the server first; --db sqlite creates a file under ./data/ on first open; --agents claude installs the harness for Claude Code; --git initializes a repository and makes the first commit. ```bash bunx create-guren-app guren-blog --mode ssr --db sqlite --agents claude --git ``` -------------------------------- ### Wrap real application with TestApp.fromApp Source: https://guren.dev/docs/guides/testing Boots the actual app exported from src/app.js, exercising real configuration. fromApp() is idempotent and reuses the first boot. ```ts import { TestApp } from '@guren/testing' import app from '../src/app.js' let http: TestApp beforeAll(async () => { http = await TestApp.fromApp(app) }) test('serves the home page', async () => { await http.get('/').assertOk() }) ``` -------------------------------- ### JSON log format example Source: https://guren.dev/docs/guides/logging Shows the JSON log format with structured fields. The example includes an info and an error log entry. ```json {"timestamp":"2024-01-15T10:30:00.000Z","level":"info","message":"User logged in","userId":123,"ip":"192.168.1.1"} {"timestamp":"2024-01-15T10:30:01.000Z","level":"error","message":"Database connection failed","error":"ECONNREFUSED"} ``` -------------------------------- ### Russian plural forms example (lang/ru/messages.json) Source: https://guren.dev/docs/guides/i18n JSON example for a language with three plural forms (one, few, many). Forms are listed in rule order. ```json // lang/ru/messages.json — one | few | many { "apple": "яблоко|яблока|яблок" } ``` -------------------------------- ### Text log format example Source: https://guren.dev/docs/guides/logging Shows the text log format with timestamp, level, message, and context. The example includes an INFO and an ERROR log line. ```text [2024-01-15T10:30:00.000Z] INFO User logged in {"userId":123,"ip":"192.168.1.1"} [2024-01-15T10:30:01.000Z] ERROR Database connection failed {"error":"ECONNREFUSED"} ``` -------------------------------- ### URLs: Get public URL and temporary signed URL Source: https://guren.dev/docs/guides/storage Shows how to get a public URL for a file and a temporary signed URL (S3 only) with an expiration date. ```TypeScript const disk = storage.disk() // Get public URL const url = disk.url('avatars/user-1.jpg') // e.g., '/storage/avatars/user-1.jpg' (local) // e.g., 'https://bucket.s3.region.amazonaws.com/avatars/user-1.jpg' (S3) // Get temporary signed URL (S3 only) const expiration = new Date(Date.now() + 3600 * 1000) // 1 hour const signedUrl = await disk.temporaryUrl('private/report.pdf', expiration) ``` -------------------------------- ### GitHub OAuth controller with start and callback actions Source: https://guren.dev/docs/guides/oauth Controller with start and callback actions for GitHub OAuth. The start action initiates authorization, passing the session to bind the flow to the browser. The callback validates the code and state, fetches the profile, finds or creates the user, logs them in, and redirects to the original redirect_to or '/dashboard'. ```ts import { Controller } from '@guren/core' import { z } from 'zod' import { oauth } from '@/config/oauth' import { User } from '@/app/Models/User' const CallbackQuerySchema = z.object({ code: z.string(), state: z.string(), }) export default class GitHubOAuthController extends Controller { async start() { // Passing the session ties the flow to this browser — see // "Binding State to the Browser" below. const { url } = await oauth.authorize('github', { redirectTo: this.query('redirect_to'), session: this.auth.session(), }) return this.redirect(url) } async callback() { const { code, state } = this.validateQuery(CallbackQuerySchema) const { profile, redirectTo } = await oauth.handleCallback('github', { code, state, session: this.auth.session(), }) let user = await User.where('githubId', profile.id).first() if (!user) { user = await User.create({ email: profile.email, name: profile.name, githubId: profile.id }) } await this.auth.login(user) return this.redirect(redirectTo ?? '/dashboard') } } ``` -------------------------------- ### Update dependencies and regenerate artifacts with bun install and bunx guren codegen Source: https://guren.dev/docs/guides/upgrading Run these commands to install dependencies and regenerate code artifacts as part of the upgrade workflow. ```bash bun install bunx guren codegen ``` -------------------------------- ### Call an agent tool with arguments, preflight, and user authentication Source: https://guren.dev/docs/guides/cli Shows how to invoke a tool with `bunx guren tool:call`, including passing arguments, using `--preflight` to stop before the handler, and authenticating as a user with `--as`. ```bash # Call a tool with arguments bunx guren tool:call posts.store --input '{"title":"Hello agents"}' # Rehearse it: run the middleware and validate the contract, stop before the handler bunx guren tool:call posts.store --input '{"title":"Hello"}' --preflight # Call as a user, and read the result as JSON bunx guren tool:call posts.index --as user:42 --json ``` -------------------------------- ### Run specific checks and get single check result Source: https://guren.dev/docs/guides/health-checks Shows how to run only specific checks by name using checkOnly, and how to get a single check result with getCheck. ```typescript // Run only specific checks const report = await health.checkOnly(['database', 'redis']) // Get a single check result const dbResult = await health.getCheck('database') ``` -------------------------------- ### Example translation file (lang/en/messages.json) Source: https://guren.dev/docs/guides/i18n Example JSON catalog with nested objects that become dot-notation keys. Dots in property names are not allowed and are reported by 'guren check --i18n'. ```json // lang/en/messages.json { "hello": "Hello", "user": { "profile": "Profile", "settings": "Settings" } } ``` -------------------------------- ### Generate project guidelines with guren guidelines Source: https://guren.dev/docs/tutorials/08-teach-the-agent Generates project guidelines from the codebase and writes them to `.claude/rules/project-guidelines.md`. The file lists models, relationships, validators, policies, security rules, and feature steps, all derived from reading the app. ```bash bunx guren guidelines -o .claude/rules/project-guidelines.md ``` -------------------------------- ### Verify upgrade with bun run typecheck and test Source: https://guren.dev/docs/guides/upgrading Run these commands to verify the upgrade after applying migration notes. ```bash bun run typecheck && bun run test ``` -------------------------------- ### Add auth and resource with bunx guren add Source: https://guren.dev/docs/guides/getting-started Scaffolds authentication (registration, login, logout, session middleware) and a full resource (model, migration, controller, validator, resource, Inertia pages) for the given fields. Run `bunx guren add --help` for all generators. ```bash bunx guren add auth bunx guren add resource posts --fields "title:string,body:text,published:boolean" ``` -------------------------------- ### Console entry point (bin/console.ts) Source: https://guren.dev/docs/guides/console Boots the application and hands `argv` to the kernel. `kernel.handle()` resolves to the exit code rather than terminating the process, making it testable. ```ts import { ready } from '../src/main.js' import { kernel } from '../src/console.js' await ready process.exit(await kernel.handle(process.argv.slice(2))) ``` -------------------------------- ### Zod Schema Validation in a Controller Source: https://guren.dev/docs/guides/controllers Complete controller example using validateBody, validateQuery, and validateParams with Zod schemas. These helpers throw ValidationException (422) on failure, and the example shows handling pagination, finding records, and creating posts. ```typescript import { Controller } from '@guren/core' import { z } from 'zod' import { Post } from '@/app/Models/Post' const PostIdParamSchema = z.object({ id: z.coerce.number().int().positive() }) const StorePostSchema = z.object({ title: z.string().min(1), content: z.string().min(10) }) const PageQuerySchema = z.object({ page: z.coerce.number().int().min(1).default(1) }) export default class PostsController extends Controller { async index() { const { page } = this.validateQuery(PageQuerySchema) // throws 422 const result = await Post.paginate({ page, perPage: 10 }) const paginator = paginate(result, { path: this.request.path ?? '/posts' }) return this.inertia(pages.posts.Index, { data: result.data.map((post) => new PostResource(post).toJSON()), pagination: { meta: paginator.meta(), links: paginator.links(), }, }) } async show() { const { id } = this.validateParams(PostIdParamSchema) // throws 422 const post = await Post.findOrFail(id) // throws 404 return this.inertia(pages.posts.Show, { post: new PostResource(post).toJSON() }) } async store() { const data = await this.validateBody(StorePostSchema) // throws 422 const user = await this.auth.userOrFail() // throws 401 const post = await Post.create({ ...data, authorId: user.id }) return this.redirect('/posts') } } ``` -------------------------------- ### Attach file, inline content, and inline image Source: https://guren.dev/docs/guides/mail Three examples showing how to attach a file from a path, attach inline content with a content type, and attach an inline image using a CID reference in HTML. ```ts // File attachment await mail(mailManager) .to('user@example.com') .subject('Your Report') .text('Please find your report attached.') .attach({ filename: 'report.pdf', path: './storage/reports/monthly.pdf', }) .send() // Inline content await mail(mailManager) .to('user@example.com') .subject('Data Export') .text('Your data export is ready.') .attach({ filename: 'data.json', content: JSON.stringify(exportData, null, 2), contentType: 'application/json', }) .send() // Inline images (CID) await mail(mailManager) .to('user@example.com') .subject('Newsletter') .html('Logo

Welcome!

') .attach({ filename: 'logo.png', path: './public/logo.png', cid: 'logo', }) .send() ``` -------------------------------- ### TestApp basic test suite with bun:test Source: https://guren.dev/docs/guides/testing Boots a lightweight TestApp instance and uses fluent assertions to test list, create, and 404 responses. Requires bun:test and @guren/testing. ```ts import { describe, test, beforeAll } from 'bun:test' import { TestApp } from '@guren/testing' describe('Posts', () => { let app: TestApp beforeAll(async () => { app = await TestApp.create() }) test('lists all posts', async () => { await app.get('/posts').assertOk() }) test('creates a post', async () => { await app .post('/posts', { title: 'Hello', content: 'World' }) .assertStatus(201) .assertJsonPath('post.title', 'Hello') }) test('returns 404 for missing post', async () => { await app.get('/posts/999').assertNotFound() }) }) ``` -------------------------------- ### Request flow diagram for GET /posts Source: https://guren.dev/docs/guides/first-steps Mermaid flowchart showing the order of layers a GET /posts request passes through: route, controller, validation, model, database, resource, and Inertia page. The diagram is provided as an overview before the step-by-step tour. ```mermaid flowchart TD Browser["Browser
GET /posts"] Route["1. Route
routes/web.ts"] Controller["2. Controller
PostController.index()"] Validator["3. Validation
ListPostsQuerySchema"] Model["4. Model
Post.paginate()"] Database[("Database
posts table")] Resource["5. Resource
PostResource"] Page["6. Inertia page
posts/Index.tsx"] Browser --> Route --> Controller Controller --> Validator --> Model Model <--> Database Model --> Resource --> Page Page -- "rendered response" --> Browser ``` -------------------------------- ### Build prototype with bun run build:prototype Source: https://guren.dev/docs/guides/prototype-first Builds the prototype by regenerating manifests, running `guren check --prototype`, and producing `dist/prototype/`. The output directory contains the shell, a 404 copy, a `_redirects` file, hashed bundles, and public assets. ```bash bun run build:prototype ``` -------------------------------- ### Inspection and Audit Command Examples Source: https://guren.dev/docs/guides/cli Example invocations for the inspection and audit commands: check, audit, gate, doctor, context, docs:graph, and spec:generate. Each command supports --json for machine-readable output, and audit exits non-zero on failures. ```bash bunx guren check --json ``` ```bash bunx guren audit --json ``` ```bash bunx guren gate --changed ``` ```bash bunx guren doctor --next ``` ```bash bunx guren context User --json ``` ```bash bunx guren docs:graph --path app/Http/Controllers/PostController.ts ``` ```bash bunx guren spec:generate ``` -------------------------------- ### Upgrade harness and run gate with bunx guren upgrade --install Source: https://guren.dev/docs/tutorials/14-production Upgrade the harness and regenerate code. Aligns @guren/* versions and Drizzle pins, applies codemods, then syncs, regenerates, typechecks, and runs the gate. Run the gate after the upgrade, not before. ```bash bunx guren upgrade --install bunx guren agent:sync bunx guren codegen --force bun run typecheck bunx guren gate ``` -------------------------------- ### Extending HealthCheck class Source: https://guren.dev/docs/guides/health-checks Create a reusable check by extending the HealthCheck class. The example defines an ExternalServiceCheck that checks an external URL, measures latency, and returns degraded if the response is not OK or latency exceeds 1000ms. The usage example registers the check with a Stripe health endpoint. ```typescript import { HealthCheck, CheckResult } from '@guren/core' export class ExternalServiceCheck extends HealthCheck { readonly name: string constructor( private url: string, private serviceName: string ) { super() this.name = serviceName } async check(): Promise { try { const start = Date.now() const response = await fetch(this.url) const latency = Date.now() - start if (!response.ok) { return this.degraded(`Service returned ${response.status}`, { latency }) } if (latency > 1000) { return this.degraded('Service responding slowly', { latency }) } return this.healthy('Service is healthy', { latency }) } catch (error) { return this.unhealthy( error instanceof Error ? error.message : 'Service unreachable' ) } } } // Usage health.register(new ExternalServiceCheck( 'https://api.stripe.com/health', 'stripe' )) ``` -------------------------------- ### Create D1 Database and Configure wrangler.jsonc Source: https://guren.dev/docs/guides/cloudflare Initialize a new D1 database using the wrangler CLI and register the binding in the project configuration. ```bash bunx wrangler d1 create my-app ``` ```jsonc { "d1_databases": [ { "binding": "DB", "database_name": "my-app", "database_id": "", "migrations_dir": ".cloudflare/d1-migrations" } ] } ``` -------------------------------- ### Route-Specific Limits: Login and Authenticated API Source: https://guren.dev/docs/guides/rate-limiting Shows how to set different rate limits for specific routes. The login endpoint gets a stricter limit of 5 attempts per 15 minutes, while authenticated API routes get a higher limit of 1000 requests per hour. ```TypeScript import { Router, createRateLimitMiddleware } from '@guren/core' const router = new Router() // Stricter limit for login endpoint - 5 attempts per 15 minutes router.post('/login', [AuthController, 'login']).middleware( createRateLimitMiddleware({ limit: 5, windowMs: 15 * 60 * 1000, // 15 minutes }) ) // Higher limit for authenticated API routes router.middleware('auth').group((group) => { group.get('/api/*', [ApiController, 'handle']).middleware( createRateLimitMiddleware({ limit: 1000, windowMs: 60 * 60 * 1000, // 1 hour }) ) }) ``` -------------------------------- ### Scaffold new app with create-guren-app Source: https://guren.dev/docs/guides/cli Command to scaffold a new application using the dedicated bootstrapper. ```bash bunx create-guren-app my-app ``` -------------------------------- ### Apply the migration Source: https://guren.dev/docs/tutorials/03-the-posts-table Runs the migration against the development database at ./data/guren.db. Tests use a separate file and do not need a migration step. ```bash bun run db:migrate ```