LaravelReact启动器

arzan — Laravel 启动器模板

作者 hammadzafar05

Arzan 是一个面向 Cloudflare 免费套餐的 Laravel 风格全栈启动器,前端用 React,后端用 Hono 与 D1,内置账号、数据库迁移、测试与一键部署。

看看你的网站会是什么样

浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。

2 个预览视图
桌面端首页1 / 2
桌面端截图首屏预览

由服务器浏览器实际访问页面后截取。

全部页面与视图 2

截图用于了解视觉与布局,交互效果请以实际项目为准。

采集于 2026-10-01查看来源

值得关注的模板亮点

从已有项目资料中,快速了解它的特点。

01

单个 Cloudflare Worker 同时提供静态前端与 /api/* 接口,页面作为静态资源不计入 Worker 请求数

02

内置完整账号流程:注册、登录、登出、记住我、忘记/重置密码、邮箱验证、修改密码、删除账号、会话管理

03

D1 数据库通过 Drizzle 定义类型化 schema,迁移在部署后首次请求时自动应用,无需单独迁移步骤

04

API 测试运行在真实的内存 D1 上,Playwright 端到端测试覆盖桌面与手机,并在出现 CSP 违规时失败

05

默认安全设置包括 PBKDF2 密码哈希、可撤销的 HttpOnly 会话、CSRF 防护、按 IP 速率限制与严格 CSP

06

提供 AGENTS.md 向编码代理说明架构与约定,并附有从 Laravel 迁移的对照表

模板详细介绍

Arzan 是一个部署在 Cloudflare Workers 上的全栈启动器,定位为“Laravel 风格”的约定式脚手架:账号体系、起始布局、设置页和测试在安装后即可使用,部署只需一条命令。它并非 PHP 项目,底层是 TypeScript:前端为 React + Vite + TanStack Router/Query + shadcn/ui,后端为 Hono + D1 + Drizzle + Better Auth,全部由单个 Cloudflare Worker 提供服务。

项目内置注册、登录、登出、记住我、忘记/重置密码、邮箱验证、修改密码、删除账号、查看并登出其他会话,以及按 IP 的速率限制。应用外壳提供侧边栏或顶部导航两种布局、三种登录页样式、仪表盘与设置页(个人资料、密码、会话、外观),支持浅色/深色/跟随系统主题并适配手机宽度。后端提供 Hono API 与 requireUser 中间件,D1 通过 Drizzle 管理带类型的 schema,迁移在部署后首次请求时自动应用;邮件在开发环境打印到终端,生产环境可接入 Resend。

质量工具包括严格 TypeScript、Biome、基于真实内存 D1 的 API 测试、桌面与移动端的 Playwright 端到端测试,以及 GitHub Actions CI。仓库还包含 AGENTS.md,向 Claude Code、Cursor、Codex 等编码代理说明架构与约定。

限制方面:邮件在 Cloudflare 上并非免费,未配置 Resend 等提供商时,已部署应用不会发送重置或验证邮件,界面会提示未设置密码重置邮件并隐藏邮箱验证提醒。免费套餐的 Worker CPU 限制为每请求 10 毫秒,项目使用 WebCrypto PBKDF2 替代默认的纯 JS scrypt 以适配该限制。预览部署默认不继承绑定,需要单独创建 D1 数据库。项目路线图中的请求辅助函数、示例 CRUD 功能、工作区与角色等尚未完成。

LaravelReact启动器

适合你的项目吗?

适用场景

  • 希望以零托管成本在 Cloudflare 免费套餐上搭建带账号体系的全栈应用
  • 需要一套约定清晰、包含认证、数据库迁移、测试与 CI 的 TypeScript 项目起点
  • 使用 Claude Code、Cursor 或 Codex 等编码代理开发功能,希望代理遵循既有架构与安全规则
  • 从 Laravel 或 Inertia 迁移,寻找路由、ORM、认证与测试的对应实现
  • 需要桌面与移动端端到端测试,并希望测试对 CSP 违规敏感

适合人群

  • 熟悉 TypeScript 与 React、愿意使用 Cloudflare Workers 与 D1 的开发者
  • 需要内置账号体系与设置页、不想从零搭建认证流程的全栈项目
  • 希望用编码代理辅助开发、需要明确架构约定的团队或个人
  • 有 Laravel 经验、想对照迁移到 TypeScript 全栈栈的开发者

上手与定制指南

结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。

  1. 1

    需要 Node 22 或更高版本,可用 npm create cloudflare@latest -- my-app --template=hammadzafar05/arzan 创建项目

  2. 2

    复制 .dev.vars.example 为 .dev.vars 并设置 BETTER_AUTH_SECRET(可用 openssl rand -hex 32 生成)

  3. 3

    本地运行 npm run dev 会同时启动应用、API 与本地 D1,验证与重置邮件会打印在终端

  4. 4

    部署前需执行 npx wrangler login 并通过 npx wrangler secret put BETTER_AUTH_SECRET 设置密钥,首次部署会自动创建 D1 数据库

  5. 5

    预览部署默认没有数据库,如需独立数据库应创建 arzan-preview 并在 wrangler.jsonc 的 previews 中配置

查看仓库使用说明

授权与来源资料

使用条件与限制

免费使用 · 保留许可声明

本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。

使用时需要遵守

  • 允许免费使用、修改、商用和分发该版本代码。
  • 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
  • 代码按现状提供;担保与责任限制以原许可证及适用法律为准。

额外费用与待核对事项

  • 邮件功能在 Cloudflare 上并非免费:本地开发时邮件及链接仅打印到终端;部署后需自行接入 Resend(免费额度每月 3000 封)或其他邮件服务商,否则已部署应用不会发送任何邮件。
  • 未配置邮件服务商时,已部署应用不会发送重置或验证邮件,界面会提示密码重置邮件未设置并隐藏邮箱验证提醒,相关账号流程不可用。
  • 预览部署(每个分支或 PR 一个)默认不继承绑定,开箱即用时没有数据库,其 API 会返回相应提示;如需数据库须单独创建并配置。
  • 一键部署按钮仅在仓库公开后可用。
  • 部署按钮需要仓库为公开状态,否则无法使用。
  • 运行与构建需要 Node 22 或更高版本。
  • 路线图中的请求辅助函数(zod 校验、fail()、id 辅助、批内竞态防护)尚未实现,属于计划功能。
  • 示例 CRUD 功能(服务端分页、URL 过滤、增改面板、空态与错误态、测试)尚未实现,属于计划功能。
  • 工作区与角色(注册即建私有工作区、角色权限、注册开关)尚未实现,属于计划功能。
  • 管理面板、文件上传(R2)、后台任务(Queues)、2FA 与 passkey、计费方案均为后续附加功能,当前不包含。
  • 社交登录、2FA、passkey 与组织功能需自行添加 Better Auth 插件、客户端插件与数据表并生成迁移,默认不内置。
  • 若自行添加其他分析或第三方脚本,需自行在 public/_headers 中补充其来源,否则会触发 CSP 错误。
  • 更换数据库或 BETTER_AUTH_SECRET 后旧会话 cookie 失效,需清除站点数据并重新注册;账号不会迁移到新数据库。
  • 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
  • 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
查看原文依据

Permission is hereby granted, free of charge

许可证原文

**Email** isn't free on Cloudflare. Locally, emails (with their links) print to the terminal. On a deployed site, add a [Resend](https://resend.com) key (free tier: 3,000 emails/month) or swap in another provider in `worker/email/index.ts`.

README 原文

Until then, a deployed app sends nothing and **never writes reset or verification links to your logs**. The UI tells users that password-reset email isn't set up, and hides the "verify your email" nag.

README 原文

**Preview deployments** (one per branch or pull request) don't inherit bindings. Out of the box a preview has no database, and its API says so.

README 原文

**Option C — Deploy button** (works once the repository is public)

README 原文

**The Deploy button doesn't work:** it needs the repository to be public.

README 原文

Requires Node 22+.

README 原文

- [ ] **Request helpers:** zod body validation with friendly errors, `fail()`, id helper, and in-batch guards that turn a race into a clear 409

README 原文

- [ ] **Example CRUD feature:** a list with server-side paging and filters kept in the URL, add/edit sheet, empty and error states, tests

README 原文

- [ ] **Workspaces & roles:** a private workspace per sign-up, roles and permissions, a sign-up on/off switch

README 原文

- [ ] Add-ons later: admin panel, file uploads (R2), background jobs (Queues), 2FA and passkeys, billing recipes

README 原文

**Social login, 2FA, passkeys, organizations:** add the Better Auth plugin in `worker/auth/index.ts` and its client plugin in `src/lib/auth-client.ts`, then add the tables it needs to `schema.ts` and run `npm run db:generate`.

README 原文

**CSP error for `cloudflareinsights.com`:** that's Cloudflare Web Analytics, and `public/_headers` allows it. If you add other analytics or third-party scripts, add their origins there too.

README 原文

**Signed out, or "something went wrong", after redeploying with a new database or `BETTER_AUTH_SECRET`:** old session cookies no longer match. Clear the site's data in your browser (or try a private window) and register again. Accounts don't carry over to a new database.

README 原文
https://github.com/hammadzafar05/arzan/blob/main/LICENSEhttps://github.com/hammadzafar05/arzan/blob/main/README.md

DeepSeek 根据仓库许可证和 README 整理 ·2026-10-01。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。

项目核对记录与介绍依据

模板资料

来源平台
GitHub
资料与维护参考分
资料较完整 · 85 / 100
技术栈
Laravel · React
网站类型
启动器
这个分数如何计算

本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。

这个项目需要核对什么

记录的仓库更新时间
2026-09-28
截图检查日期
2026-10-01

已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。

目录记录的主要技术栈是 Laravel。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。

查看具体选型方法 →

介绍的制作与核对状态

介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。

已完成服务器许可规则与 AI 来源核对;未经过人工编辑审核。

查看当时使用的来源资料

SHA-256: 891fe2b995721556ea233f1a0a16ec3e05786a2a8fce26a26ba8eaeb38b87c3d

2026-10-01T02:25:40.246Z

来源文件 / 仓库
<p align="center">
  <img src="docs/screenshots/hero.png" alt="The Arzan dashboard right after installing: desktop and phone, light and dark" width="900">
  <br><sub>The dashboard right after installing: desktop and phone, light and dark.</sub>
</p>

# Arzan

**A Laravel-style starter kit for full-stack apps on Cloudflare's free tier: auth, database, tests and one-command deploy, for $0/month.**

**Arzan** (ارزاں) means *affordable* in Urdu: real apps on $0/month hosting.

"Laravel-style" means the conventions, not PHP: accounts, starter layouts, settings and tests are ready on day one, there's one obvious place for everything, and deploying is one command. Underneath it's TypeScript: React + Vite + TanStack Router/Query + shadcn/ui on the front, Hono + D1 + Drizzle + Better Auth on the back, all served by **one Cloudflare Worker**. You own every line.

```sh
npm create cloudflare@latest -- my-app --template=hammadzafar05/arzan
```

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/hammadzafar05/arzan) · **[Live demo](https://arzan.softgrammer.com)** · [Quick start](#quick-start) · [Roadmap](#roadmap)

### Why Arzan

- **$0 hosting for real apps.** Pages are static assets (free and unlimited); only `/api/*` runs the Worker. Password hashing is tuned for the Free plan's 10 ms CPU limit.
- **Made for AI coding agents.** `AGENTS.md` gives Claude Code, Cursor or Codex the architecture and the rules, so "build me a feature" stays secure and on the free tier.
- **Tests against a real database.** API tests run against an in-memory D1 (not mocks), plus Playwright tests on desktop and phone that **fail on any CSP violation**.
- **Secure by default:** PBKDF2 passwords, revocable sessions, CSRF protection, per-IP rate limits, a strict CSP and safe redirects.
- **Migrations apply themselves.** Edit the schema, run `npm run db:generate`, deploy. The Worker migrates on its first request.

### What's included

| | |
|---|---|
| **Accounts** | Register, log in, log out, remember me, forgot / reset password, email verification, change password, delete account, see and sign out other sessions, per-IP rate limiting |
| **App shell** | Sidebar *or* header layout, three sign-in page styles, dashboard, settings (profile, password, sessions, appearance), light / dark / system theme, responsive to phone width |
| **Backend** | Hono API with a `requireUser` middleware, D1 via Drizzle (typed schema, generated migrations that apply themselves on deploy), pluggable email (console in dev, Resend in production) |
| **Quality** | Strict TypeScript, Biome, API tests on a real local D1, Playwright end-to-end tests (desktop + mobile), GitHub Actions CI |
| **AI-ready** | `AGENTS.md` explains the architecture and conventions to coding agents (Claude Code, Cursor, Codex…) |

## Built with Arzan

Built something with Arzan? Share it in [Discussions](https://github.com/hammadzafar05/arzan/discussions) and it can be featured here.

## Coming from Laravel or Inertia?

| Laravel | Arzan |
|---|---|
| `routes/web.php` + controllers | Pages: file routes in `src/routes/` (TanStack Router). API: Hono routers in `worker/routes/` |
| Blade / Inertia pages | A React app built once into static files; pages fetch JSON from `/api/*` with TanStack Query |
| Form Requests | Zod schemas; errors come back as `{ error: "…" }` and are shown as they are |
| Eloquent + migrations | Drizzle schema, `npm run db:generate`; migrations apply on the first request |
| `DB::transaction()` | `db.batch([...])` (one D1 transaction: validate first, then write in one go) |
| Breeze / Fortify | Better Auth; `requireUser` middleware is the `auth` middleware |
| `php artisan test` | `npm test` (Vitest + real in-memory D1), `npm run test:e2e` (Playwright) |
| A server to pay for | Cloudflare's free tier |

## Why it fits the free tier

| Free-plan limit | How Arzan stays inside it |
|---|---|
| 100,000 Worker requests / day | The app is a single-page app served as **static assets, which are free and unlimited**. Only `/api/*` calls run the Worker (`run_worker_first`). |
| 10 ms CPU per request | Better Auth's default password hashing on Workers is pure-JS scrypt (~150 ms) and can fail sign-ups with "exceeded CPU limit". Arzan plugs in **native WebCrypto PBKDF2** (~20 ms, already running in production on the Free plan) — only sign-up, sign-in and password changes hash; every other request is cheap. |
| D1: 5 M row reads, 100 k writes / day, 500 MB | Sessions are one indexed lookup per request; rate-limit state is a single row per IP and endpoint. Add indexes for anything you filter on. |
| Worker size 3 MB (gzipped) | The Worker bundle is ~370 KB gzipped. |

**Email** isn't free on Cloudflare. Locally, emails (with their links) print to the terminal. On a deployed site, add a [Resend](https://resend.com) key (free tier: 3,000 emails/month) or swap in another provider in `worker/email/index.ts`. Until then, a deployed app sends nothing and **never writes reset or verification links to your logs**. The UI tells users that password-reset email isn't set up, and hides the "verify your email" nag.

## Security defaults

| | |
|---|---|
| Passwords | PBKDF2-SHA256, 100,000 iterations (the Workers maximum), random salt. OWASP recommends more (600k), but Workers caps PBKDF2 at 100k; the iteration count is stored per hash so it can be raised later |
| Sessions | HttpOnly, Secure, SameSite cookies; server-side sessions you can list and revoke; password reset or change can sign out every device |
| CSRF | `csrf()` on every API route (blocks cross-site form posts, including login CSRF) plus no CORS headers (blocks cross-site JSON) |
| Rate limits | Per client IP (Cloudflare's `cf-connecting-ip`, not spoofable `X-Forwarded-For`): 5/min for sign-in and sign-up, 3/min for reset and verification emails |
| Headers | Strict Content-Security-Policy (no inline scripts), HSTS, X-Frame-Options, Referrer-Policy and Permissions-Policy on every page (`public/_headers`); secure headers and `no-store` on the API |
| Redirects | Post-login redirects must be same-site paths (`safeRedirect`) |

## Quick start

```sh
npm create cloudflare@latest -- my-app --template=hammadzafar05/arzan
cd my-app
cp .dev.vars.example .dev.vars   # then set BETTER_AUTH_SECRET (openssl rand -hex 32)
npm run dev                      # http://localhost:5173 — app, API and a local D1 in one process
```

Or clone the repo and run `npm install` first. Requires Node 22+.

Local emails (verification, password reset) are printed in the terminal running `npm run dev`; click the link there.

## Deploy

**Option A — CLI**

```sh
npx wrangler login
npx wrangler secret put BETTER_AUTH_SECRET   # paste a random 32+ character string
npm run deploy
```

The first deploy creates the D1 database automatically, and the Worker applies `drizzle/*.sql` on its first request. There's no separate migration step.

**Option B — Git (Workers Builds).** In the Cloudflare dashboard go to *Workers & Pages → Create → Import a repository*. The defaults work: `wrangler.jsonc` runs `npm run build` itself before `wrangler deploy` / `wrangler preview`, so no build command is needed. (Setting Build command to `npm run build` is fine too; wrangler then reuses that output.) Under *Settings → Variables and Secrets*, add `BETTER_AUTH_SECRET` (and optionally `RESEND_API_KEY`, `EMAIL_FROM`). The Worker `name` in `wrangler.jsonc` must match the dashboard.

**Preview deployments** (one per branch or pull request) don't inherit bindings. Out of the box a preview has no database, and its API says so. To give previews their own database, so they never touch production data:
```sh
npx wrangler d1 create arzan-preview
```
Then add it under `"previews"` in `wrangler.jsonc` (there's a commented example there). The Worker migrates it on the first request.

**Option C — Deploy button** (works once the repository is public)

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/hammadzafar05/arzan)

## Scripts

| Command | What it does |
|---|---|
| `npm run dev` | App + API + local D1 with hot reload (Vite + the Cloudflare plugin) |
| `npm run build` | Typecheck and build the app and the Worker |
| `npm run preview` | Build, then run the production bundle locally in workerd |
| `npm run deploy` | Build and deploy to Cloudflare |
| `npm test` | API and unit tests (Vitest, real in-memory D1) |
| `npm run test:e2e` | Playwright end-to-end tests against `npm run preview` |
| `npm run lint` / `format` | Biome check / fix |
| `npm run db:generate` | Create a migration in `drizzle/` from changes to `worker/db/schema.ts` |
| `npm run check` | Lint, typecheck, test and build (what CI runs) |

## Project layout

```
worker/                 Cloudflare Worker (Hono)
  app.ts                routes: /api/health, /api/auth/* (Better Auth), then protected routes
  auth/                 Better Auth config + free-tier-safe password hashing
  db/schema.ts          Drizzle schema (auth tables + yours)
  db/migrate.ts         applies drizzle/*.sql on first request
  email/                sendEmail() + templates
  middleware.ts         requireUser
  routes/               your API routes (dashboard.ts is an example)
src/                    React app
  config.ts             layout choice + navigation
  routes/               file-based routes (TanStack Router)
    _guest/             login, register, forgot/reset password (signed-out only)
    _app/               dashboard, settings/* (signed-in only)
  components/ui/        shadcn/ui components
  components/layouts/   app (sidebar/header) and auth (simple/card/split) layouts
  lib/auth-client.ts    Better Auth client + session query
shared/config.ts        app name, email verification, password rules (used by both sides)
drizzle/                generated SQL migrations
test/                   API tests    e2e/  Playwright tests
```

## Customize

- **Name and auth rules:** `shared/config.ts`. Set `requireEmailVerification: true` to block sign-in until the email is verified.
- **Layouts:** `src/config.ts`. Choose `app: "sidebar" | "header"` and `auth: "simple" | "card" | "split"`, and add navigation items.
- **Brand colours:** the CSS variables in `src/styles.css`, using the shadcn/ui theme tokens.
- **More components:** `npx shadcn@latest add <component>` (`components.json` is set up).
- **Social login, 2FA, passkeys, organizations:** add the Better Auth plugin in `worker/auth/index.ts` and its client plugin in `src/lib/auth-client.ts`, then add the tables it needs to `schema.ts` and run `npm run db:generate`.

## Add a feature, end to end

1. **Table:** add it to `worker/db/schema.ts`, then run `npm run db:generate`.
2. **API:** create `worker/routes/things.ts` (a Hono router; `c.get("user")` is the signed-in user), then mount it in `worker/app.ts` after `requireUser`.
3. **Page:** create `src/routes/_app/things.tsx`. Fetch with TanStack Query and `api("/things")`. Add it to `mainNav` in `src/config.ts`.
4. **Tests:** add them to `test/things.test.ts` using `createTestApp()`.

## Roadmap

Improvements coming next, drawn from building real client apps on Arzan. Progress is shared as it lands; ideas are welcome in Discussions.

- [ ] **Request helpers:** zod body validation with friendly errors, `fail()`, id helper, and in-batch guards that turn a race into a clear 409
- [ ] **Example CRUD feature:** a list with server-side paging and filters kept in the URL, add/edit sheet, empty and error states, tests
- [ ] **Workspaces & roles:** a private workspace per sign-up, roles and permissions, a sign-up on/off switch
- [ ] **Everyday helpers:** money and phone formatting, WhatsApp links, phone-first layout fixes, demo data in small steps
- [ ] Add-ons later: admin panel, file uploads (R2), background jobs (Queues), 2FA and passkeys, billing recipes

## Troubleshooting

- **`The package "@cloudflare/workerd-linux-64" could not be found`** when running tests: npm skipped the platform binary (this happens with some mirrors or cached installs). Run `rm -rf node_modules && npm install`, or install the matching version: `npm i --no-save @cloudflare/workerd-linux-64@$(node -p "require('workerd/package.json').version")`.
- **`npm run preview` shows old code after a rebuild:** stop and restart the preview server. Playwright reuses a running server locally (`reuseExistingServer`), so restart it before `npm run test:e2e` too.
- **The Deploy button doesn't work:** it needs the repository to be public.
- **The dashboard says "The API returned a web page instead of data":** requests to `/api/*` aren't reaching the Worker. Open `/api/health` on your site; it must return JSON. Check `run_worker_first: ["/api/*"]` in `wrangler.jsonc`, and that no route or Page Rule on your domain sends `/api/*` somewhere else.
- **Signed out, or "something went wrong", after redeploying with a new database or `BETTER_AUTH_SECRET`:** old session cookies no longer match. Clear the site's data in your browser (or try a private window) and register again. Accounts don't carry over to a new database.
- **CSP error for `cloudflareinsights.com`:** that's Cloudflare Web Analytics, and `public/_headers` allows it. If you add other analytics or third-party scripts, add their origins there too.

## License

[MIT](LICENSE)
反馈内容错误

看看同类模板

对比同技术栈与用途的模板,找到更适合的视觉与内容结构。