Download the PHP package weeklify/ez-knowledge-base without Composer
On this page you can find all versions of the php package weeklify/ez-knowledge-base. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download weeklify/ez-knowledge-base
More information about weeklify/ez-knowledge-base
Files in weeklify/ez-knowledge-base
Package ez-knowledge-base
Short Description A self-contained, configurable knowledge base package for Laravel
License MIT
Informations about the package ez-knowledge-base
EzKnowledgeBase
A self-contained Laravel package that provides a fully themed knowledge base with categorised articles, full-text search, support tickets, and a REST API — all configurable via a single config file.
Features
- Responsive landing page with hero search, category grid, and featured articles
- Category and article browsing with sidebar navigation
- Full-text fuzzy search powered by Laravel Scout + TNTSearch
- Markdown article bodies rendered to HTML with auto-generated table of contents
- Session-based unique view counting
- Article feedback (helpful yes/no)
- Support ticket submission form with Cloudflare Turnstile spam protection
- Email notifications on admin/staff ticket replies with direct email reply support
- Inbound email processing via Brevo webhook for customer replies
- Trait-based user integration (customer, staff, and admin roles)
- REST API with dual authentication (API key or Sanctum)
- Fully configurable branding: logo, colours, fonts, copy, footer links
- Built-in caching with automatic invalidation
- Dark mode support
Requirements
- PHP 8.1+
- Laravel 10, 11, or 12
- Laravel Scout + TNTSearch driver (for search)
- Laravel Sanctum (optional, for token-based API auth)
Installation
1. Install via Composer
The service provider is auto-discovered via Laravel's package discovery. If you need to register it manually, add to config/app.php providers array:
2. Publish config and assets
3. Run migrations
This creates the kb_categories, kb_articles, kb_tags, kb_article_tag, kb_tickets, and kb_ticket_replies tables, along with a user_id foreign key on kb_tickets.
4. Seed sample data (optional)
5. Set up search (optional but recommended)
Add to .env:
The host app should extend the package's base KbArticle model and add the Searchable trait:
Import existing articles into the search index:
6. Set up user integration
Add the KB traits to your User model depending on the roles you need:
Configure admin email addresses in config/kb.php:
7. Set up email ticket replies (optional)
When enabled, admin/staff replies to support tickets automatically email the customer. Customers can reply directly to those emails, which are processed via Brevo's inbound parse webhook and stored as ticket replies.
Add to your .env:
Brevo inbound parse setup:
- In your Brevo account, go to Transactional → Settings → Inbound Parse
- Add a new inbound rule for your reply domain (e.g.
parse.yourdomain.com) - Set the webhook URL to
https://yourdomain.com/webhook/kb/inbound - Ensure your DNS MX record for the reply domain points to Brevo's inbound servers
Webhook authentication: The webhook is secured via the X-Brevo-Secret header. You must set KB_REPLY_WEBHOOK_SECRET — the webhook will return 403 if no secret is configured. The secret is only accepted via the X-Brevo-Secret header (query parameters are not supported).
Brevo dependency: The getbrevo/brevo-php package is suggested but not required. Install it if you need Brevo API integration beyond inbound webhooks:
CSRF exemption: The webhook route is registered outside the web middleware group, but you should also add webhook/kb/inbound to your VerifyCsrfToken middleware's $except array if your app applies CSRF globally.
How it works:
- Admin/staff replies to a ticket in the admin panel
- The
KbTicketRepliedevent fires, triggering theSendTicketReplyNotificationqueued listener - An email is sent to the customer with a
Reply-Toaddress containing an HMAC-signed token (e.g.ticket+{token}@parse.yourdomain.com) - When the customer replies, Brevo's inbound parse POSTs the email to your webhook
- The webhook verifies the token (valid for 30 days by default), validates the sender email matches the ticket, checks spam score, sanitizes the HTML body, and stores the reply
The feature degrades gracefully — when KB_REPLY_ENABLED=false (the default), admin replies work normally with no emails sent.
8. Set up Cloudflare Turnstile (optional but recommended)
The ticket submission form supports Cloudflare Turnstile for spam protection. Add your Turnstile keys to config/services.php:
And in your .env:
When configured, the Turnstile widget is automatically rendered on the ticket form and verified server-side on submission. When not configured, the form works without it.
User Traits
The package provides three traits for integrating the ticket system with your User model:
CanKbTicket (Customer)
| Method | Description |
|---|---|
kbTickets() |
HasMany relationship to the user's tickets |
createKbTicket(array $data) |
Create a ticket, auto-fills name/email from user |
replyToKbTicket(KbTicket $ticket, string $body) |
Reply to own ticket (guards ownership) |
ownsKbTicket(KbTicket $ticket) |
Check if user owns the ticket |
ManageKbTicket (Staff/Agent)
| Method | Description |
|---|---|
replyToKbTicketAsStaff(KbTicket $ticket, string $body) |
Reply as staff, auto-transitions open → in_progress, fires KbTicketReplied event |
AdminKbTicket (Admin)
| Method | Description |
|---|---|
replyToKbTicketAsAdmin(KbTicket $ticket, string $body) |
Reply as admin, auto-transitions open → in_progress |
changeKbTicketStatus(KbTicket $ticket, string $status) |
Validate and update ticket status |
resolveKbTicket(KbTicket $ticket) |
Convenience wrapper to set status to resolved |
isKbAdmin() |
Check if user's email is in config('kb.users.admins') |
Ticket Submission (Guests & Authenticated Users)
The ticket form supports both guest and authenticated submissions:
- Guest: must provide name and email in the form
- Authenticated user: name and email are auto-filled from the user model, and the ticket is linked via
user_id
Web Routes
All web routes are prefixed with /help-center and use the web middleware group.
| Method | URI | Name | Description |
|---|---|---|---|
| GET | /help-center |
kb.landing |
Landing page with categories + featured articles |
| GET | /help-center/categories |
kb.categories |
All categories with top articles |
| GET | /help-center/category/{slug} |
kb.category |
Single category with paginated articles |
| GET | /help-center/{category}/{article} |
kb.article |
Single article (tracks views) |
| GET | /help-center/search |
kb.search |
Search results page |
| GET | /help-center/ticket |
kb.ticket.create |
Support ticket form |
| POST | /help-center/ticket |
kb.ticket.store |
Submit support ticket |
| POST | /help-center/article/{id}/feedback |
kb.article.feedback |
Article helpfulness vote |
| POST | /webhook/kb/inbound |
kb.webhook.inbound |
Brevo inbound email webhook |
API Endpoints
All API routes are prefixed with /api/kb, rate-limited, and require authentication.
| Method | URI | Name | Description |
|---|---|---|---|
| GET | /api/kb |
kb.api.home |
Categories with counts + featured articles |
| GET | /api/kb/categories/{slug} |
kb.api.category |
Category detail + paginated articles |
| GET | /api/kb/categories/{slug}/{article} |
kb.api.article |
Full article with HTML body + TOC |
| GET | /api/kb/search?q=&category= |
kb.api.search |
Full-text search with optional category filter |
API Authentication
The API accepts either of these authentication methods:
Option 1 — Static API Key (simplest)
Set a key in .env:
Then pass it via header:
Option 2 — Sanctum Bearer Token
Use a standard Sanctum personal access token:
Example API Responses
GET /api/kb
GET /api/kb/categories/{slug}/{article}
Configuration
After publishing (php artisan vendor:publish --tag=kb-config), edit config/kb.php to customise your knowledge base.
Environment Variables
| Variable | Default | Description |
|---|---|---|
KB_BRAND_NAME |
Weeklify |
Brand name in header, footer, page titles |
KB_BRAND_TAGLINE |
Helping you make the most... |
Footer tagline |
KB_BRAND_COPYRIGHT |
Weeklify Inc. |
Copyright holder |
KB_LOGO_URL |
null |
Custom logo URL (null = bundled logo) |
KB_LOGO_ALT |
Knowledge Base |
Logo alt text |
KB_COLOR_PRIMARY |
#0EA5E9 |
Primary brand colour |
KB_COLOR_BG_LIGHT |
#f6f6f8 |
Light mode background |
KB_COLOR_BG_DARK |
#101622 |
Dark mode background |
KB_FONT_FAMILY |
Inter |
Google Font family name |
KB_FONT_URL |
Google Fonts URL | Font stylesheet URL |
KB_SUPPORT_EMAIL |
[email protected] |
Support contact email |
KB_SUPPORT_WEBSITE |
weeklify.cloud |
Support website |
KB_API_KEY |
null |
Static API key (null = disabled) |
KB_API_RATE_LIMIT |
60 |
API requests per minute |
KB_USER_MODEL |
App\Models\User |
Fully-qualified User model class |
KB_REPLY_ENABLED |
false |
Enable outbound ticket reply emails |
KB_REPLY_DOMAIN |
(empty) | Domain for reply-to addresses (e.g. parse.yourdomain.com) |
KB_REPLY_FROM_ADDRESS |
[email protected] |
From address for ticket reply emails |
KB_REPLY_FROM_NAME |
Weeklify Support |
From name for ticket reply emails |
KB_REPLY_TOKEN_SECRET |
null |
HMAC secret for reply tokens (falls back to APP_KEY) |
KB_REPLY_WEBHOOK_SECRET |
null |
Secret for Brevo inbound webhook verification (required — webhook returns 403 if unset) |
KB_REPLY_TOKEN_TTL |
2592000 |
Reply token expiry in seconds (default 30 days) |
KB_BRAND_ADDRESS |
(empty) | Physical address shown in email footer (hidden when empty) |
TURNSTILE_SITE_KEY |
null |
Cloudflare Turnstile site key |
TURNSTILE_SECRET_KEY |
null |
Cloudflare Turnstile secret key |
Config Sections
The config/kb.php file is organised into these sections:
- brand — name, tagline, copyright, address
- logo — url, alt text, height classes
- colors — primary, background light/dark
- font — family, Google Fonts URL
- search — placeholder text
- hero — landing page title and subtitle
- support — enabled toggle, label, email, website
- footer — configurable link columns
- api — key, rate limit
- reply — email reply feature: enabled toggle, domain, from address/name, token/webhook secrets, spam threshold, token TTL
- users — user model class, admin email list
Package Structure
Models
The package provides five Eloquent models in the EzKnowledgeBase\Models namespace:
- KbCategory —
kb_categoriestable. Has many articles. Supportsis_activeflag andsort_order. - KbArticle —
kb_articlestable. Belongs to a category, has many tags. Supportsis_published,is_featured, view counting, and helpfulness votes. The host app can extend this model to add Laravel Scout. - KbTag —
kb_tagstable. Many-to-many with articles viakb_article_tagpivot. - KbTicket —
kb_ticketstable. Stores support ticket submissions. Optionally linked to a user viauser_id. - KbTicketReply —
kb_ticket_repliestable. Stores replies to tickets withis_adminflag and optionaluser_id.
Caching
The package caches expensive queries with automatic invalidation:
| Cache Key | TTL | Invalidated On |
|---|---|---|
kb_categories_with_counts |
1 hour | Category or article save/delete |
kb_all_categories_with_top_articles |
1 hour | Category or article save/delete |
kb_featured_articles |
1 hour | Category or article save/delete |
kb_article_{slug} |
30 min | That article's save/delete |
Cache invalidation is handled via Eloquent model event listeners registered in the service provider.
Customising Views
To override any Blade view, publish them to your app:
Views will be copied to resources/views/vendor/kb/ where you can edit them freely. The package will use your custom views over its built-in ones.
Adding Articles
Articles are stored in database/seeders/data/kb/ as PHP arrays with markdown bodies using nowdoc syntax:
After adding articles to the seeder data files, run:
Articles can also be managed through the Filament admin panel.