内置密码登录、验证码重置、邮箱验证、免密码登录、TOTP 双因素、恢复码、社交登录和通行密钥等认证流程
ezehstart — Laravel 启动器模板
作者 ezehky
Ezeh Start 是一个基于 Laravel 与 Livewire 的启动器模板,内置认证、图片与视频库、博客、交易账本、角色工作区、数据表格、管理后台、邮件营销和法务页面等模块,并附带一套成文的代码风格约定。
看看你的网站会是什么样
浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。
全部页面与视图 2
截图用于了解视觉与布局,交互效果请以实际项目为准。
值得关注的模板亮点
从已有项目资料中,快速了解它的特点。
图片库与视频库共用同一套管理形态,图片删除受引用表外键保护,视频仅允许白名单提供商
博客使用 tiptap 编辑器,支持从媒体库插入内容、多态分类标签、定时发布和 HTML 净化
交易账本以整数最小货币单位存储,余额由已确认记录在行锁下推导,管理员可审核和手动调整
角色为后台可创建的数据行,通过中间表赋予任意数量角色,权限合并取最高值
账户删除采用计划窗口机制,包含提醒邮件、签名取消链接和每日清理任务
模板详细介绍
Ezeh Start 是一个 Laravel + Livewire 启动器模板,面向需要从第一天就具备完整后台与账户体系的项目。它把认证、账户安全、内容管理、交易记录和站点配置等常见模块预先搭好,并用一套写下来的“house style”约束后续新增代码的写法。
认证方面包含密码登录、注册、邮件验证码重置密码、六位验证码邮箱验证,以及免密码的验证码注册与登录流程。邮件验证码设有两次尝试上限和 60 秒重发间隔。登录限流同时基于邮箱和 IP 地址,支持可配置的密码强度、密码历史检查、TOTP 双因素、恢复码、记住设备令牌、Socialite 社交登录和 Cloudflare Turnstile 验证码,且这些功能都通过站点配置开关控制路由是否开放。
内容与媒体方面,图片库支持批量上传、文件夹树、按名称搜索、标题重命名而不改变存储 URL,以及私有、角色可见或公开三种可见性;删除受 image_usages 表的外键约束保护。视频库以“提供商 + 提供商 id”的引用形式存储,播放器 URL 每次渲染时重建,仅允许 YouTube 和 Vimeo。博客使用 tiptap 编辑器,可从媒体库插入图片和视频,分类和标签为多态结构,文章支持定时发布、精选和归档,HTML 在写入时净化。
账户与权限方面,角色是管理员在后台创建的数据行而非枚举,通过 role_user 中间表可赋予任意数量角色,权限合并时取最高权限。users.user_type 是固定的登录工作区(Admin 与 Member),各自有独立中间件和路由文件。交易账本使用整数最小货币单位,余额由已确认记录在行锁下推导而非直接存储,管理员可进行审核和手动调整。
后台功能包括仪表盘、管理员与会员列表、角色页、可搜索的活动日志、单账户视图、已删除账户页、博客管理、交易账本与审核队列,以及跨四个屏幕的站点配置。会员工作区包含仪表盘、个人资料、偏好设置、安全设置、个人媒体库、交易流水、数据下载和账户删除。
账户生命周期方面,删除请求会先安排计划并发送邮件,提供五天和一天提醒,邮件中的签名链接可取消删除;窗口结束后由每日任务执行匿名化或彻底删除。未验证账户会先警告后移除,长期未登录会员会收到召回邮件,两者都有独立开关和天数配置。
其他横切功能包括审计追踪、数据库通知类型以数据行存储、250 个国家种子数据、破坏性操作前的确认弹窗、基于 spatie/laravel-passkeys 的 WebAuthn 通行密钥、块式邮件模板构建器与营销活动、以用户通知开关代替订阅表的公告机制、货币汇率与显示转换,以及基于 LocaleEnum 和 lang/{code}.json 的多语言支持。
限制方面,模板的完整文档位于独立的 ezehstart-doc 站点;演示种子数据中的法务政策为样板文本,不构成法律建议;已发布政策版本只能被新版本取代而不能直接编辑;定时任务需要运行调度器;Turnstile 验证码需要同时配置站点密钥和密钥才生效。
适合你的项目吗?
适用场景
- 需要快速搭建带完整后台、账户体系和内容管理功能的 Laravel 项目
- 需要图片与视频库、博客、交易账本和邮件营销等模块同时就位的应用
- 需要多角色管理后台、会员工作区和细粒度权限控制的平台
- 需要账户删除计划、未验证账户清理和召回邮件等自动化生命周期管理的项目
- 需要多语言、多货币和可配置站点设置的面向国际用户的应用
适合人群
- 熟悉 Laravel 与 Livewire 并希望从成熟启动器开始开发的团队
- 需要内置认证、媒体库、博客和交易记录等常见模块的项目
- 需要管理员与会员双工作区及角色权限体系的平台
- 需要账户生命周期自动化与邮件营销能力的应用
上手与定制指南
结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。
- 1
运行 composer setup 完成安装、密钥生成、迁移、npm 安装与构建,再用 composer dev 同时启动服务器、队列和 Vite
- 2
执行 php artisan db:seed 生成角色、通知类型、国家、站点配置和管理员账户,默认管理员为 [email protected] / password,正式使用前需修改
- 3
如需演示数据可单独运行 php artisan db:seed --class=DemoSeeder,其法务政策为样板文本而非法律建议
- 4
有七个命令依赖调度器运行,包括账户删除提醒与清理、未验证账户清理、召回邮件、定时文章与邮件活动以及活动日志清理
- 5
Turnstile 验证码需同时配置 TURNSTILE_SITE_KEY 和 TURNSTILE_SECRET_KEY,LARAVEL_PDF_DRIVER 默认为 dompdf 且无需额外安装
授权与来源资料
使用条件与限制
免费使用 · 保留许可声明本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。
使用时需要遵守
- 允许免费使用、修改、商用和分发该版本代码。
- 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
- 代码按现状提供;担保与责任限制以原许可证及适用法律为准。
额外费用与待核对事项
- 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
- 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
- 完整文档位于独立的 ezehstart-doc 站点,需另行获取该配套文档站点才能查阅安装、配置、扩展与上线说明。
- DemoSeeder 发布的法务政策仅为展示政策形态的样板文本,不构成法律建议,不可直接作为合规依据使用。
- 已发布政策版本不能被直接编辑,只能通过后台起草并发布新版本(如 v2.0)来取代旧版本。
- 有七个命令依赖调度器运行,正式部署必须保持调度器常驻,否则账户清理、定时发布与邮件活动等不会执行。
- Cloudflare Turnstile 验证码需同时配置 TURNSTILE_SITE_KEY 与 TURNSTILE_SECRET_KEY 两个环境变量,缺少任一则该开关无效。
- 社交登录依赖 Laravel Socialite,需要自行配置各第三方提供商的应用凭据才能使用。
- 图片上传优化依赖 spatie/laravel-image-optimizer,且仅在其二进制文件已安装的环境中生效。
- lang:translate 的机器翻译仅在开发环境使用,绝不可在运行时执行。
- “Ezeh Start”名称与标识为商标,MIT 许可不授予商标权;以该名称命名产品、分支、公司、域名或付费服务需获得授权,仅“Built with Ezeh Start”表述可直接使用。
- 在分发该套件源码的副本时必须保留版权声明。
查看原文依据
Permission is hereby granted, free of charge
许可证原文
The full documentation (installation, configuration, every feature, extending the kit and going to production) is the companion `ezehstart-doc` site.
README 原文
The policies it publishes are boilerplate showing the *shape* of a policy, **not legal advice**
README 原文
a published version is superseded rather than edited, so replacing it means drafting v2.0 from Admin → Site configuration → Policies and publishing that.
README 原文
Seven commands run on the schedule, so a live install needs the scheduler running:
README 原文
Two optional environment keys: `TURNSTILE_SITE_KEY` and `TURNSTILE_SECRET_KEY` for the captcha — the switch does nothing without both
README 原文
Social sign-in through Socialite,
README 原文
Uploads run through `spatie/laravel-image-optimizer` where its binaries are installed.
README 原文
`lang:translate` machine-translates them in development — never at runtime.
README 原文
"Ezeh Start" and its logo are trademarks of Kingsley Uchenna Ezeh, and the MIT License doesn't grant them. "Built with Ezeh Start" is always fine; naming your product, fork, company, domain or paid service after the kit needs permission.
README 原文
https://github.com/ezehky/ezehstart/blob/main/LICENSEhttps://github.com/ezehky/ezehstart/blob/main/README.mdKeep the copyright notice in copies of the kit's source.
README 原文
DeepSeek 根据仓库许可证和 README 整理 ·2026-10-05。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。
项目核对记录与介绍依据
模板资料
- 来源平台
- GitHub
- 资料与维护参考分
- 资料较完整 · 83 / 100
- 技术栈
- Laravel
- 网站类型
- 启动器
这个分数如何计算
本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。
这个项目需要核对什么
- 记录的仓库更新时间
- 2026-10-05
- 截图检查日期
- 2026-10-05
已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。
目录记录的主要技术栈是 Laravel。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。
查看具体选型方法 →介绍的制作与核对状态
介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。
审核声明: [email protected] · 2026-10-06
查看当时使用的来源资料
SHA-256: 65afb764aa5566532ef0417b0d8d285f11c6d068237e2694196eff47d91ce993
2026-10-05T18:39:01.864Z
来源文件 / 仓库# Ezeh Start
A Laravel 13 + Livewire 4 starter kit with the batteries a project actually needs on
day one, and a written house style that keeps everything added after day one looking
like it was there from the start.
## What ships
**Authentication** — password sign-in, registration, password reset by emailed code,
email verification by six-digit code, and a passwordless flow that both registers and
signs in from a code. Every emailed code carries the same two bounds: five wrong
guesses destroy it, and another cannot be asked for inside 60 seconds. An expiry alone
is not a bound — six digits is a million guesses wide, and at an unlimited guess rate
the whole space fits inside the window. Password reset never says whether an address is
registered: every well-formed address gets the same reply, and only a real account gets
a code.
**Sign-in hardening** — a login throttle keyed on the email *and* the address together,
so nobody can lock out an address they know. Configurable password strength and a
password-history check that refuses one this account has already used. TOTP two-factor
with a QR code rendered locally, single-use recovery codes that download as a file, and
a "remember this device" token stored only as a hash. Social sign-in through Socialite,
matching on the provider id first so somebody who changes their Google email is not
stranded with a second account, and refusing to disconnect the last way into an account.
A Cloudflare Turnstile captcha on the guest forms, per form rather than in front of the
whole site. Every one of these is a site-config switch that closes its route, not just
its button.
**Image library** — upload several at once into a folder tree, search by name, rename
the title without ever changing the stored URL, and set who can see each image: private,
a role, or everybody. Deletion is guarded by an `image_usages` table with a restricting
foreign key, so an image on a published post refuses to go rather than leaving a broken
picture behind. Members have a configurable quota; administrators do not. Uploads run
through `spatie/laravel-image-optimizer` where its binaries are installed.
**Video library** — the same again for embeds, and deliberately the same shape. A row is
a *reference* — a provider and the provider's own id — never a file and never a URL, and
the player URL is rebuilt from the pair on every render. `VideoProviderEnum` is an
allowlist (YouTube, Vimeo); an iframe pointing anywhere else is dropped rather than
cleaned, because there is no version of it we can vouch for.
**Blog** — posts written in a tiptap editor that inserts images and videos straight from
the libraries, with polymorphic categories and tags: one `categories` table serves every
kind of category, separated by `CategoryGroupEnum`, so products can reuse it later
without a second table and a second admin screen. Posts can be scheduled, featured and
archived, and the scheduler publishes them to the minute and tells the subscribers. The
HTML is sanitised on the way in. A seeded **Author** role narrows an account to the
posts it wrote and gives it a public byline. Public index and post pages with related
reading.
**Transaction ledger** — `transactions` with gateway, meta, evidence, balance and charge
rows alongside. Balances are derived from confirmed rows rather than stored, under a row
lock, so a balance can never silently disagree with the ledger that explains it. Money
is integer minor units throughout. Administrators get a review queue and a manual
adjustment that records who moved what and why.
**Roles and workspaces** — a role is a row an administrator creates from the dashboard,
not an enum case, and it divides up the admin workspace only. An admin carries **any
number** of them through the `role_user` pivot, and their gate maps merge with the
highest access winning each key — so a second role only ever widens what somebody
reaches, and the personal override on top is the only thing that can narrow it.
**Type is not role.** `users.user_type` is the workspace an account signs in to, fixed
in code. Two of them, each behind its own middleware:
| Workspace | URL prefix | Route name | Route file |
| --- | --- | --- | --- |
| Admin | `/app-splash` | `admin.` | `routes/admin.php` |
| Member | `/app` | `user.` | `routes/user.php` |
| Public + auth | `/` | *(none)* | `routes/web.php` |
**Data tables** — one trait behind every listing: row selection, a bulk bar, a column
manager each account keeps for itself, sorting, a date range, and the whole listing as
CSV, XLSX or PDF. Imports read the same two spreadsheet formats, one row at a time, and
a bad row is reported rather than allowed to abandon the run. What can leave is what the
account can already see — the gate and the column list decide the file.
**Admin workspace** — dashboard with live metrics, sparklines and a "waiting on you"
queue; admin and member listings with search, filters and exports; a roles page; a
searchable activity log with an optional retention window; a single-account view; a
deleted-accounts screen; and a manage-roles modal with guards (you cannot revoke your
own admin role, or the last one). Blog posts, categories and tags. The transaction
ledger and its review queue. Site configuration across four screens — branding, security
switches, preferences, social handles, the legal pages, the FAQs and notification types
— plus a raw JSON editor for the key no screen has grown a field for yet.
**Member workspace** — dashboard with a next-steps checklist, profile, preferences,
security settings (password, email, sessions, two-factor, connected accounts), their own
image and video libraries, their transaction statement, a download of everything held
about them, and account deletion.
**Account deletion is a window, not an event** — asking to be deleted schedules the
account and mails the date. Reminders go at five days and one day, a signed link in the
email cancels without signing in, and only when the window runs out does the nightly
sweep act: anonymize where there is history worth keeping, remove outright where there is
not. Anonymized rows are soft-deleted, so they surface only on **Deleted accounts**,
where they can be restored or purged for good.
**Accounts that look after themselves** — an account that never verifies its address
is warned once (day 2 by default) and removed after a grace period counted from the
warning (day 3), never while verification is off and never with ledger rows behind it.
A member not seen for 30 days gets one "we missed you", and another only after they have
been back. Both are switches with their own day counts on the Security screen, and both
emails are template-builder slots.
**Impersonation** — an administrator views the site as a member, because "the button
does not work" is unanswerable from the outside. Never admin to admin, the real identity
in the session rather than in a link, both ends logged as the administrator, an hour's
expiry, and every account-altering screen closed while it runs.
**Legal pages and consent** — `/terms`, `/privacy` and `/cookies`, written in markdown
from the admin and served as plain crawlable pages with a contents sidebar. A policy is
versioned: published text is superseded by a new draft rather than edited, and the old
version stays readable at `?version=`, because a consent record points at it. Terms and
privacy are marked as requiring consent, so registration asks for it and records the
version accepted, with timestamp, IP and user agent. Publish a replacement and everyone
is outstanding again until they accept it.
**Public site** — a landing page with an FAQ section whose questions and markdown
answers are editable from the admin, and a footer that links the legal pages straight
off the enum.
**Cross-cutting** — an audit trail that records what changed and what it changed from,
database notifications whose *types* are rows rather than code, so a new one can be
added without a deploy and every account picks up a switch for it on their next visit. A
site configuration editable from the admin rather than from a deploy, 250 countries
seeded from a file in the repository rather than a network call, and a styled
confirmation modal in front of every destructive write.
**Passkeys** — WebAuthn through `spatie/laravel-passkeys`, behind `security.passkeys`.
The package does the cryptography; `PasskeyService` does the signing in, so the status
check, the audit trail and the login alert run exactly as they do for a password.
**Email marketing** — a block-based template builder with saved headers, footers and
calls to action; campaigns sent to chosen addresses, every account, or everybody
subscribed to a notification type; test sends; scheduling in the sender's time zone with
daily-to-quarterly recurrence; and a sent history. `{{token | default: "…"}}` resolves
the same way in a subject as in a block. A builder template can also stand in for a
system mailable (`SystemEmailEnum`, `WithSystemTemplate`); unassigned, the Blade view is
sent as before.
**Newsletter and announcements** — no subscribers table: an address is a `users` row
and the subscription is the `ANNOUNCEMENTS` switch it already carries. The public popup
shows the latest live announcement, falling back to the plain sign-up.
**Currencies** — rates against one default. The ledger is stored in the default and
`kMoneyFormat()` converts for the viewer, so changing somebody's currency never touches
a stored row.
**Languages** — `LocaleEnum` plus `lang/{code}.json`, a case offered only once its file
exists. `lang:extract` collects the strings, and `lang:translate` machine-translates
them in development — never at runtime.
## Documentation
The full documentation (installation, configuration, every feature, extending the kit and
going to production) is the companion `ezehstart-doc` site. Run `npm install && npm run dev`
in that folder.
## Getting started
```bash
composer setup # install, key, migrate, npm install, npm run build
composer dev # server + queue + vite together
```
Then seed the roles, the notification types, the countries, the site configuration and
an admin:
```bash
php artisan db:seed
```
That creates `[email protected]` / `password`. **Change it** in
`database/seeders/UserSeeder.php` before this becomes a real project.
For a dashboard with something in it — invented people, a ledger, posts, FAQs, and v1.0
of the three legal pages — there is a separate seeder, deliberately not part of the one
above:
```bash
php artisan db:seed --class=DemoSeeder
```
Run it as often as you like: every seeder under it matches on a natural key, so a second
run refreshes rather than doubles. The policies it publishes are boilerplate showing the
*shape* of a policy, **not legal advice** — and a published version is superseded rather
than edited, so replacing it means drafting v2.0 from Admin → Site configuration →
Policies and publishing that.
Seven commands run on the schedule, so a live install needs the scheduler running:
account deletion reminders and the deletion sweep daily, the unverified-account sweep
and the "we missed you" reminders daily, scheduled posts and email campaigns every
minute, and the activity-log prune daily (which does nothing until somebody sets a
retention window). Each takes `--dry-run`.
Two optional environment keys: `TURNSTILE_SITE_KEY` and `TURNSTILE_SECRET_KEY` for the
captcha — the switch does nothing without both — and `LARAVEL_PDF_DRIVER`, which is
`dompdf` and needs nothing installed.
## Working on it
```bash
php artisan test --compact # the suite
php artisan test --compact --filter=X # one file or one test
vendor/bin/pint --dirty # after touching any PHP
vendor/bin/phpstan analyse --memory-limit=1G
composer test # all three, as CI runs them
```
## The house style
This kit is opinionated, and the opinions are written down in **`.agents/my-skills/`** —
44 files covering where code goes, how it is named, and what this project deliberately
does not use. Start at [`agent.md`](.agents/my-skills/agent.md), finish at
[`checklist.md`](.agents/my-skills/checklist.md), and use
[`README.md`](.agents/my-skills/README.md) as the index.
AI agents get the same rules automatically: [`CLAUDE.md`](CLAUDE.md) orients a session,
[`AGENTS.md`](AGENTS.md) carries the Laravel Boost guidelines, and the `house-style`
skill in `.claude/skills/` (mirrored to `.agents/` and `.github/`) routes into the
library on its own.
The short version:
- Every screen is a Livewire single-file component at
`resources/views/pages/**/⚡name.blade.php`, routed with `Route::livewire()`.
There is no `app/Livewire`, and no `render()` method.
- Every status is an enum using `WithEnumHelpers`, with one `is{CASE}()` per case.
- Every model is `#[Unguarded]` with a `casts()` method and `#[Scope]` scopes.
- Business logic lives in a `#[Singleton]` service, resolved with `app()`.
- Every admin write is logged through `ActivityLogService`.
- Every action button is gated twice: `<x-dashboard.gate.button>` hides it and the
method behind it re-checks with `kGate()`. Hiding a control is a courtesy; the method
check is the boundary.
- Every destructive action confirms through `<x-dashboard.confirm-modal>`, never
`wire:confirm` — the browser dialog cannot be styled, cannot carry a consequence, and
is suppressed outright in some in-app browsers.
- There is no `app/Actions`, `app/Repositories`, `app/Jobs`, `app/Events`,
`app/Policies`, or `app/Http/Requests` — each has a file in the library explaining
what this project does instead.
## Stack
Laravel 13 · PHP 8.3+ · Livewire 4 · Flux UI free v2 · Tailwind v4 · Alpine · Pest 5 ·
Pint · Larastan.
## Releases
[`CHANGELOG.md`](CHANGELOG.md) records what changed in each version, and what an
existing project has to do to take it.
## License and trademark
The code is open source under the [MIT License](LICENSE). Use it, change it, and sell
what you build with it. Keep the copyright notice in copies of the kit's source.
The **name** is a different matter. "Ezeh Start" and its logo are trademarks of Kingsley
Uchenna Ezeh, and the MIT License doesn't grant them. "Built with Ezeh Start" is always
fine; naming your product, fork, company, domain or paid service after the kit needs
permission. [`TRADEMARK.md`](TRADEMARK.md) has the details. It's adapted from the
[Cachet trademark policy](https://cachethq.io/trademark).
The legal pages and policies the kit *serves* (terms, privacy, cookies, and the ones
`DemoSeeder` publishes) are placeholders that show the shape of a policy. They're not
legal advice, and shipping the tools for consent and deletion doesn't by itself make an
application compliant with any law.
## Adding a third workspace
Three files and two `match` arms:
1. `app/Http/Middleware/{Type}Middleware.php` — a copy of `UserMiddleware` with the new
enum case.
2. `routes/{type}.php`.
3. A route group in `bootstrap/app.php`.
4. The case in `UserTypeEnum`, then the `match` in
`UserService::middlewareGeneralCheck()` and the branch in
`WithAuthWorker::userDashboardRedirect()`. Both are exhaustive, so PHP will tell you
if you miss one.
看看同类模板
对比同技术栈与用途的模板,找到更适合的视觉与内容结构。

sage
WordPress starter theme with Laravel Blade components and templates, Tailwind CSS, and block editor support
Laravel · 启动器

wave
Wave - The Software as a Service Starter Kit, designed to help you build the SAAS of your dreams 🚀 💰
Laravel · SaaS

filament-starter
A beautiful starting point for your next TALL stack project using Filament. ⚡
Laravel · 启动器

electrik
Laravel SaaS starter kit: auth, teams, Stripe billing, and Slate 3 — Composer package for Laravel 12
Laravel · SaaS

php-saas
The everything-included starter kit for your next idea
Laravel · SaaS

filament-jetstream
A Laravel starter kit built with Filament inspired by Jetstream.
Laravel · 启动器
