Add a full-featured blog and news section to your LaraClassifier / JobClass site. Create posts with categories, tags, featured images, and a threaded comment system with moderation: all fully translatable.
Rich Post Editor
Create posts with translatable titles, slugs, content, excerpts, and SEO metadata. Give each post a featured image.
Categories & Tags
Organize content with nestable categories and a flexible tagging system.
Threaded Comments
Nested comment replies with configurable depth, moderation queue, auto-approval rules, and CAPTCHA support.
Live Posting & Self-Moderation
Comments, replies, edits and deletions are sent without reloading the page. Signed-in authors can edit and delete their own comments.
Multi-Language
All posts, categories, and tags support translations via Spatie Translatable. Localized front-end URLs with locale prefix.
Email Notifications
Admins are notified of new comments. Comment authors are notified when someone replies to their comment.
Reading Time & Views
Automatic reading time calculation (configurable WPM) and view count tracking for each post.
Use Cases
Company Blog
Publish company news, product updates, and industry insights. Organize posts by category (e.g. “Product Updates”, “Industry News”, “Tutorials”) and let visitors engage through comments.
Portfolio Blog
Complement your portfolio with behind-the-scenes articles, case studies, and project write-ups. Tag posts with relevant project names or technologies for easy cross-referencing.
Multi-Language Content Hub
Publish articles in multiple languages (English, French, etc.) with per-locale slugs and content. Each post can have fully independent translations managed through the admin panel.
News Section
Use the blog as a press/news section. Leverage the “published at” date for scheduling and the “draft/published” workflow for editorial control.
Requirements
- LaraClassifier / JobClass v19.0.0 or later
- PHP 8.3+
- The database server supported by LaraClassifier / JobClass (translatable fields are stored in JSON columns)
blog_posts, blog_categories, blog_post_tags,
blog_post_tag and blog_comments) and stores featured images through the core image pipeline.
Installation
Step 1: Upload the add-on
Go to Admin panel → Extensions → Add-ons, click Upload add-on and drop the add-on's .zip file into the upload area (50 MB maximum).
The archive is extracted into extensions/addons/blog/ and Blog & News appears in the list, deactivated.
extensions/addons/blog/ over FTP or SSH: its addon.json file must sit directly inside that folder.
Then open Admin panel → Extensions → Add-ons. The page scans extensions/addons/ every time it loads, so the add-on is listed straight away (the Sync button runs the same scan on demand).
Step 2: Activate the add-on
Click Activate on the Blog & News card. It is a paid add-on, so a dialog asks for its purchase code, which is verified before anything else happens: an invalid code is rejected in the dialog and nothing is changed.
Once the code is accepted, activation runs in one pass: it creates the add-on's database tables (its migrations), registers its permissions, runs its seeders and publishes its public assets. Reload the page to see its new entry in the Add-ons section of the admin sidebar.
Step 3: Configure
Open Admin panel → Blog from the Add-ons section of the sidebar and set the add-on up: see Configuration.
Purchase Code (License Key)
Blog & News is sold as a separate product, so it has its own purchase code (license key), distinct from the purchase code of the main application and from the one of every other add-on. You are asked for it when you activate Blog & News in Admin panel → Extensions → Add-ons.
Our products are sold on three platforms. The way you receive a purchase code depends on where you bought the product.
| Platform / Marketplace | How you get the purchase code | Where to find it again |
|---|---|---|
| bedigit.com Store In-site purchase (Shop) |
Generated automatically when the order is paid, then sent by email, either in its own license email, or inside the order confirmation email. | My Account → My Licenses on bedigit.com |
| Gumroad | Created as soon as Gumroad notifies us of the sale, then sent in a separate email, in addition to the Gumroad receipt. | The license email, your Gumroad Library, and My Account → My Licenses on bedigit.com |
| Envato Market CodeCanyon |
Issued by Envato, not by us, and never sent by email: you download it yourself from your Envato account. | Envato account → Downloads → License certificate & purchase code |
1. bedigit.com Store (in-site purchase)
- As soon as the order’s payment status becomes Paid, a license key is generated automatically for every licensed item in the order (one key per purchased unit: buying 3 units gives 3 distinct keys).
- It is emailed to the address used on the order, either in a dedicated license email or inside the order confirmation email. Check your inbox and your spam / junk folder.
- The key stays available in your account under My Account → My Licenses. Keys are masked in the list; open the license detail page to reveal and copy the full key, see the domains it is activated on, and deactivate a domain to free an activation slot.
- The matching invoice is under My Account → My Orders.
2. Gumroad
- A Gumroad purchase produces two separate emails: the Gumroad receipt (sent by Gumroad, giving access to the files) and a license key email (sent by bedigit.com) that contains your purchase code.
- The license key email is generated as soon as Gumroad notifies us of the sale, so it normally arrives within seconds of the payment. Here too, check your inbox and your spam / junk folder.
- When the Gumroad product uses Gumroad’s own license-key feature, the same key also appears in your Gumroad receipt and under Library → your purchase on gumroad.com.
- Use the same email address on bedigit.com as on Gumroad: your keys are then linked to your account automatically and listed under My Account → My Licenses, even if you register after the purchase. You can also add a Gumroad key manually from My Account → My Gumroad Licenses.
3. Envato Market (CodeCanyon)
- Envato purchase codes are issued and delivered by Envato Market, never emailed by us, so there is nothing to look for in your spam folder: you retrieve the code from your Envato account.
- Log in to your Envato / CodeCanyon account, open the Downloads page, find the item, and choose License certificate & purchase code from the Download dropdown. The code is written in that certificate.
- An Envato purchase code looks like
12345678-90ab-cdef-1234-567890abcdef(8-4-4-4-12 characters). It never changes, and renewing item support does not issue a new one. - Official Envato article: Where Is My Purchase Code?
Configuration
Every option is set from Admin panel → Blog → Settings (in the Add-ons section of the sidebar).
The values are saved in the settings table under the keys below. A key that was never saved falls back to the
default shown here, taken from the add-on's config/blog.php file or from its code.
| Setting | Description | Default |
|---|---|---|
blog_posts_per_page |
Number of posts displayed per page on the blog listing. | 10 |
blog_related_posts_count |
Number of related posts shown at the bottom of each post detail page. | 3 |
blog_words_per_minute |
Average reading speed used to calculate the “X min read” estimate (100–500). | 200 |
blog_show_post_author |
Display the post author on the post page. | true |
blog_show_post_date |
Display the publication date on the post page. | true |
blog_home_shows_listing |
Serve the plain post listing at /blog instead of the magazine home. /blog/posts then redirects to /blog. |
false |
blog_home_hero_enabled |
Show the hero banner at the top of the blog home page. The rest of the hero is stored in the other blog_home_hero_* settings (heading, subheading, button, height, alignment, background and text colours). |
false |
blog_home_trending_enabled |
Run the most-read headlines on one line under the header of the blog home page. | true |
blog_home_trending_limit |
How many headlines the trending bar carries (1–12). | 5 |
blog_home_sections |
The home page sections, as JSON: one entry per section with its content type, layout, post count, title / subtitle per language, and the category, tag or post IDs it targets. | Featured (lead) + Latest (grid) + Most read (spotlight) |
blog_comments_enabled |
Enable or disable the comment system globally. | true |
blog_comments_require_approval |
When enabled, guest comments must be approved by an admin before appearing. Comments from signed-in users are always auto-approved. | true |
blog_allow_guest_comments |
Allow non-logged-in visitors to leave comments (requires name and email). | false |
blog_comments_max_depth |
Maximum nesting level for threaded comment replies (1–5). | 2 |
blog_comments_per_page |
Number of top-level comments displayed per page on a post (5–100). | 10 |
blog_auto_approve_trusted_commenters |
Auto-approve comments from users who already have a previously approved comment (matched by email). | false |
blog_auto_approve_replies |
Auto-approve replies to an existing comment, so a thread keeps flowing without a moderator approving every answer. First-level comments still follow the normal moderation rules. | false |
blog_page_header_mode |
Header style of the blog front pages: simple (title + breadcrumb) or hero (a band with its own background). The rest of the header is stored in the other blog_page_header_* settings (visibility switches, height, alignment, background and text colours). |
simple |
blog_page_header_show_header |
Render the page header at all. blog_page_header_show_title, _show_subtitle and _show_breadcrumb switch its parts individually. |
true |
blog_page_header_show_subnav |
Show the blog sub-navigation bar (Blog / All Posts) under the page header. | true |
blog_captcha_enabled |
Require CAPTCHA verification when posting comments and replies. It uses the site-wide CAPTCHA selected in Admin panel → Configuration → Settings → Security, and the switch stays locked until one is selected there. | true |
Config File Defaults
Change these options from the settings page rather than by editing config/blog.php: a value saved in the admin
panel always takes precedence, and the file is replaced every time the add-on is updated.
Admin: Posts
The Posts page (Blog → All Posts) is the primary interface for managing blog content.
Posts List
A sortable, paginated table (20 per page) showing:
- Featured image thumbnail
- Title (translatable)
- Category
- Author
- Status (Draft / Published)
- View count
- Comments count
- Published at date
Filters & Search
The posts list supports three filter dimensions:
- Search: searches within post titles and slugs (in the current admin language and the fallback language)
- Status: filter by
draftorpublished - Category: filter by a specific category
Creating & Editing Posts
The post form includes the following fields, each supporting per-locale translations:
Content Fields (per locale)
| Field | Validation | Notes |
|---|---|---|
title |
Required (default locale), max 255 | Translatable. Used to auto-generate slug. |
slug |
Optional, max 255 | Translatable. Auto-generated from title if left empty. |
content |
Optional | Translatable. WYSIWYG editor content. |
excerpt |
Optional, max 500 | Translatable. Short summary for listing pages. |
meta_title |
Optional, max 70 | Translatable. SEO title tag. |
meta_description |
Optional, max 160 | Translatable. SEO meta description. |
Non-Translatable Fields
| Field | Validation | Notes |
|---|---|---|
category_id |
Optional | A blog category (from Blog → Categories) |
featured_image |
Optional, JPG, PNG, GIF or WebP, max 5 MB | Stored through the core image pipeline |
status |
Required, draft or published |
Uses the PostStatus enum |
published_at |
Optional, date | Auto-set to current time on first publish if empty |
is_featured |
Optional, boolean | Flags the post for the Featured posts sections of the blog home |
tags |
Optional, array of tag IDs | Multi-select from existing tags |
Str::slug().
Admin: Categories
Blog categories (Blog → Categories) are stored in the add-on's own blog_categories table,
separate from the listing categories of LaraClassifier / JobClass.
Category Fields
| Field | Notes |
|---|---|
name |
Translatable. Required for default locale. |
slug |
Translatable. Auto-generated from name if empty. |
description |
Translatable. Optional. |
parent_id |
Nullable. Supports one level of nesting (parent → child). |
position |
Integer for manual ordering. |
is_active |
Boolean. Inactive categories are hidden from front-end. |
Admin: Tags
Tags (Blog → Tags) are lightweight labels that can be attached to any post.
Unlike categories, tags are flat (no hierarchy) and are stored in the blog_post_tags table.
Tag Fields
| Field | Notes |
|---|---|
name |
Translatable. The display name of the tag. |
slug |
Translatable. URL-friendly identifier. |
The tags list shows each tag with its associated post count. Tags are searchable by name and paginated (20 per page).
detach()), but the posts themselves are not affected.
Admin: Comments
The Comments page (Blog → Comments) provides a moderation interface for all blog comments across all posts.
Comments List
A paginated table (20 per page) showing:
- Author: user name (if authenticated) or guest name/email
- Content: comment text preview
- Post: the blog post the comment belongs to
- Status: Approved / Pending badge
- Date
A pending count badge is shown in the header to quickly identify items needing attention.
Moderation
Per-comment actions:
- View: see full comment content, replies, and post context
- Approve (
PATCH): marks the comment as approved - Delete: permanently removes the comment
Filter by Status
Use the status query parameter to filter:
?status=pending: show only pending (unapproved) comments?status=approved: show only approved comments
Bulk Actions
Select multiple comments using checkboxes and apply bulk actions:
- Approve: approve all selected comments at once
- Delete: delete all selected comments
Bulk actions are sent as POST admin/blog/comments/bulk with action and
comma-separated ids.
Admin: Settings
The settings page (Admin panel → Blog → Settings) opens with the public address of the blog and is organized into five tabs:
Posts Display
- Posts Per Page: number of posts on the listing page (1–100)
- Related Posts: number of related posts shown on post detail pages (0–12, 0 disables them)
- Words Per Minute: reading speed for reading time calculation (100–500)
- Show Author: display the post author on the post page
- Show Date: display the publication date on the post page
A note at the bottom of the tab reminds you that comment emails are sent with the site mail settings.
Home Page
The tab opens on Home Page Layout, which decides what /blog serves:
- Magazine home (default): the front page built from the cards below. The post
listing stays at
/blog/posts. - Post listing: the plain paginated list of posts.
/blog/poststhen redirects to/blogso the two never compete for the same content, the listing takes the blog's own title and breadcrumb, and the sub-navigation is dropped (only one entry would be left). The cards below are hidden but keep their values, so switching back restores the magazine home as it was.
The remaining three cards build the magazine home page:
- Hero Banner: an optional masthead above the first section. The heading, subheading and button label are per language; the height, text alignment, background (solid colour, gradient or image with an overlay) and the title / subtitle / breadcrumb colours match the controls on the Page Header tab. Leave a colour empty to inherit it from the theme.
- Trending Bar: runs the most-read headlines on one line under the header, with a configurable number of headlines (1–12).
- Home Sections: the section builder. Add, reorder, rename per language,
and disable sections. Each section has a content source and a layout:
- Content: Featured posts (the posts flagged in the post editor, topped up with the most-read ones), Latest posts, Most read, From a category, From a tag, or Hand-picked posts (chosen one by one, shown in the order you pick them).
- Layout: Lead story, Grid, List, Spotlight, Headlines or Carousel.
The whole section list is stored as JSON in the blog_home_sections setting; the hero
and trending bar use the blog_home_hero_* and blog_home_trending_* settings.
Comments
- Enable Comments: global toggle for the comment system
- Require Approval: whether guest comments need admin approval (authenticated users are always auto-approved)
- Guest Comments: allow non-logged-in visitors to comment
- Reply Depth: maximum nesting level for threaded replies (1–5)
- Comments Per Page: number of top-level comments per page on a post (5–100)
- Auto-Approve Trusted: auto-approve comments from emails that already have an approved comment
- Auto-Approve Replies: auto-approve replies to an existing comment, without waiting for moderation. Useful to keep a discussion flowing while still moderating first-level comments
CAPTCHA Protection
- Enable CAPTCHA for Comments: require CAPTCHA verification when posting comments or replies (on by default)
Comments reuse the site-wide CAPTCHA chosen in Admin panel → Configuration → Settings → Security (Simple Captcha or Google reCAPTCHA), the same one as the login and contact forms. The tab shows the current provider; if none is selected, the switch is locked and a warning links to the Security settings.
Page Header
The header band of the blog front pages: the post listing and the category, tag, author and search archives. The home page hero keeps its own settings on the Home Page tab and still wins there; anything it leaves empty falls back to this tab. The article page paints its own masthead from the post’s featured image and is not affected.
- Header style: Simple title + breadcrumb (the default) keeps the theme’s own background and only takes the alignment and the text colours; Hero header paints a full band with its own height and background.
- Visibility: switch the whole header, its title, its subtitle, its breadcrumb and the blog sub-navigation bar on or off.
- Layout: header height (any CSS length) and content alignment (left, center, right, or the theme default).
- Background (hero style only): theme default, solid colour, gradient (two colours and an angle) or an image with an overlay opacity. A solid colour and a gradient can also carry a decorative overlay image.
- Text colours: title, subtitle, breadcrumb text and breadcrumb link. Leave a colour empty to inherit it from the theme.
The values are stored in the blog_page_header_* settings and resolved by
Addons\Blog\Support\PageHeader, which falls back to its own defaults for every key
that was never saved.
Front-end: Blog Home
The blog front page (/{locale}/blog) is a magazine-style home page assembled from the
Blog → Settings → Home Page tab. Top to bottom it renders:
- Hero banner (optional), painted by the addon's own page header
- Sub-navigation: Blog and All Posts (hidden when the listing is the main page, or when Show sub-navigation is off on the Page Header tab)
- Trending bar (optional): the most-read headlines on one scrollable line
- Content sections: in the order set in the admin, each in its chosen layout
- Topic rail: every category that has at least one post, with its post count
Section layouts
- Lead story: one dominant story whose headline block breaks the bottom edge of its image, beside a stack of secondary stories
- Grid: an even card grid, three across on desktop
- List: full-width rows, thumbnail left, story right
- Spotlight: one open story beside a compact panel of the rest
- Headlines: a dense, image-free headline list in up to three columns
- Carousel: a horizontal rail of cards with scroll buttons
Most read sections are numbered in the Spotlight and Headlines layouts, because the position carries real information there. Every other content source drops the numerals.
Featured posts
The Featured content source reads the Featured post toggle in the post
editor’s Publish card (blog_posts.is_featured), newest first. If fewer posts are
flagged than the section asks for, it is topped up with the most-viewed posts.
Styling
Every front-end blog page pulls one shared stylesheet
(blog::front.partials.styles), so the home page, the archives and the article page
read as one publication. It derives all of its colours from the active theme’s Bootstrap
tokens and inherits the theme’s heading font rather than declaring one, so the blog follows
the theme and its dark mode.
Front-end: Blog Listing
The blog listing page (/blog/posts) displays published posts with pagination.
The category, tag, author and search pages share this same layout.
Main Content
- Post cards: each showing: featured image thumbnail, title, excerpt, category badge, author name, published date, reading time, and view count
- Pagination: configurable posts per page
Sidebar
- Categories: list of active categories with post counts
- Recent Posts: the 5 most recently published posts
- Popular Posts: the 5 most viewed posts
- Tags: all tags that have at least one post
Front-end: Post Detail
The post detail page (/{locale}/blog/{slug}) renders the full post content.
Content
- Header: title, category, author, published date, reading time, view count
- Featured image: full-width hero image (via polymorphic media relation)
- Content body: rendered HTML content
- Tags: tag badges linked to tag filter pages
- Post navigation: previous / next post links
- Related posts: posts sharing the same category or tags (configurable count)
- Comments section: threaded comments with reply form (see Comments)
View Count Tracking
Each time the post detail page is loaded, PostService::incrementViewCount()
increments the view_count column. This drives the “Popular Posts” sidebar widget.
Related Posts Algorithm
Related posts are selected by matching:
- Posts in the same category
- Posts sharing any of the same tags
Results are ordered by published date (most recent first) and limited to the configured count.
Front-end: Category & Tag Pages
Category Page
URL: /{locale}/blog/category/{slug}
Displays all published posts in the specified category with the same pagination, sidebar widgets, and post card layout as the main listing. The category is resolved by its translatable slug (current locale first, then English fallback).
Tag Page
URL: /{locale}/blog/tag/{slug}
Displays all published posts tagged with the specified tag. Same layout as the category page. The tag is resolved by its translatable slug.
Front-end: Search
URL: /{locale}/blog/search?q={query}
Search across the title, content and excerpt of published posts, in the current language. Results are paginated and displayed with the standard blog listing layout.
Front-end: Comments
The comment system appears at the bottom of each post detail page (when enabled).
Comment Form
- Authenticated users: only need to enter the comment content. Auto-approved unless moderation overrides apply.
- Guest users (if enabled): must provide name, email, and content. Subject to approval moderation.
- Reply form: appears under a comment when clicking “Reply”, up to the configured max depth. A single reply form is shared by the whole page and moved to the comment being answered.
- Notify on reply: checkbox to opt in/out of reply notifications.
- CAPTCHA: displayed when CAPTCHA is enabled for blog comments, and refreshed after each submission.
Posting Without a Page Reload
Comments, replies, edits and deletions are all sent in the background: the page is never reloaded and the visitor stays where they were in the discussion.
- While a request is being sent, the form is dimmed, its buttons are disabled and the submit button shows a spinner. This prevents double submissions and makes the wait visible.
- On success, an approved comment is inserted straight into the list (a reply lands under its parent), the comment counter is updated and a confirmation message is shown above the form.
- If the comment still needs moderation, the confirmation says so and nothing is added to the list: the comment appears once an admin approves it.
- Validation errors are shown under the field concerned, without losing what was typed.
- If JavaScript is unavailable, the forms fall back to a normal submission and a page reload: nothing is lost.
Editing & Deleting Your Own Comments
Signed-in visitors get Edit and Delete actions on the comments they wrote. Both work in the background, like posting.
- Edit opens the comment text in place. Saving replaces the text immediately and marks the comment as “Edited” next to its date.
- Editing closes once somebody replies. The Edit action disappears as soon as the comment has a reply, so the answers below it can’t lose the context they were written for. It comes back if every reply is removed. Pending replies count too, even though they are not displayed yet.
- Delete asks for confirmation first, then removes the comment along with all of its replies. Deleted comments are kept in the trash rather than destroyed, so an admin can still review them.
- These actions never appear on somebody else’s comment, and are refused by the server as well as hidden in the page. They are not available on guest comments, which carry no reliable identity.
- Turning Enable Comments off also disables editing and deleting.
Comment Display
- Comments are displayed in threaded format (parent → replies).
- Only approved comments are shown to front-end visitors: a reply awaiting moderation stays hidden until it is approved.
- Each comment shows: author display name, date, an “Edited” marker if its author changed it, and the content.
- The comment counter next to the section title counts approved comments and replies.
Validation Rules
| Field | Validation |
|---|---|
content |
Required, 3–2000 characters |
parent_id |
Optional, must exist in blog_comments; depth check enforced |
author_name |
Required for guests, max 255 |
author_email |
Required for guests, valid email, max 255 |
notify_on_reply |
Optional boolean |
Auto-Approval Logic
- If Require Approval is off → all comments are auto-approved.
- If the commenter is authenticated → auto-approved.
- If the comment is a reply and Auto-Approve Replies is on → auto-approved.
- If Auto-Approve Trusted is on and the email has a previously approved comment → auto-approved.
- Otherwise → pending (requires admin approval).
Multi-Language Support
The blog add-on uses spatie/laravel-translatable for all content fields.
Translations are stored as JSON columns in the database.
Translatable Fields by Model
| Model | Translatable Fields |
|---|---|
Post |
slug, title, content, excerpt, meta_title, meta_description |
PostCategory |
slug, name, description |
PostTag |
slug, name |
Slug Resolution
Front-end controllers resolve slugs by searching in the current locale first, then falling back to English:
Featured Images
Each post has a single featured image, whose path is saved in the image_path column of blog_posts.
Upload Flow
- Admin uploads an image file (JPG, PNG, GIF or WebP, max 5 MB) via the post create/edit form.
- The
PostServicehands it to the core image pipeline, which stores it underapp/blog. - The same pipeline generates the resized versions used on the front end.
Image Removal
The edit form includes a “Remove featured image” checkbox. When checked, the stored image files are deleted and the post is left without an image. Uploading a new image automatically replaces the old one.
Email Notifications
The blog add-on sends two types of email notifications:
New Comment Notification
Sent to all admin users when a new comment or reply is posted.
- Subject: “New comment on {post title}” or “New reply on {post title}”
- Body: Author name, post title, content preview (200 chars)
- Action: “Moderate Comments” link (if pending) or “View Comment” link (if approved)
Controlled by: the blog_new_comment notification type.
Comment Reply Notification
Sent to the parent comment’s author when someone replies to their comment.
- Subject: “New reply to your comment on {post title}”
- Body: Reply author name, post title, content preview
- Action: “View Reply” link
Controlled by: the blog_comment_reply notification type.
Reply notifications respect the commenter’s notify_on_reply preference
and are not sent when someone replies to their own comment.
Both notification types are switched on or off in Admin panel → Configuration → Settings → Notifications, on the Notification Types tab (both are on by default). The emails go out with the site mail settings.
CAPTCHA Protection
When blog_captcha_enabled is on (the default), the comment and reply forms include
the site-wide CAPTCHA challenge and the submission is validated against it, exactly like the core forms.
The CAPTCHA provider itself (Simple Captcha in one of its styles, or Google reCAPTCHA) is chosen in Admin panel → Configuration → Settings → Security. Until one is selected there, the blog switch is locked.
Updating
An update only replaces the add-on's files. Its database tables and data, its settings, its activation state and its recorded purchase code are all kept, so do not deactivate or remove the add-on before updating it. Back up your database first all the same.
Method 1: Upload the new version (recommended)
- Download the latest
.zipfile of the add-on. - Go to Admin panel → Extensions → Add-ons and click Upload add-on.
- Drop the
.zipfile into the upload area. - Because Blog & News is already installed, a prompt shows the installed version and the new one. Click Replace: the
extensions/addons/blog/folder is swapped for the new files. Cancelling the prompt discards the upload.
Method 2: Replace the files by hand
- Over FTP or SSH, delete the
extensions/addons/blog/folder and upload the new one in its place. Replace the whole folder rather than copying over it, so files dropped by the new version do not linger. - Open Admin panel → Extensions → Add-ons: the page re-reads
addon.jsonand the card shows the new version number.
After the files are replaced
Apply the database update. Some versions of this add-on ship an update routine (database migrations and data fixes). When the new version has one, an Updates available banner appears in the admin panel. Go to Admin panel → System → Updates, find Blog & News under Paid add-on updates and click Apply updates. Every pending version is applied in order, and the page records it in the update history. The routine is only offered while the add-on is active: if you replaced the files of a deactivated add-on, activate it first.
If your installation caches its configuration or routes (php artisan config:cache, route:cache), run php artisan optimize:clear after the update.
Uninstallation
Switching an add-on off without losing anything is a deactivation: go to Admin panel → Extensions → Add-ons, click Deactivate on the Blog & News card and confirm.
- The add-on is no longer loaded: its routes, views, admin sidebar entry and front-end pages stop answering.
- Its database tables and all the data they hold are kept, and its files stay under
extensions/addons/blog/. Nothing is deleted. - Its permissions and its recorded purchase code stay in the database. Only Remove deletes them.
- Deactivation is refused while another active add-on depends on this one: deactivate that add-on first.
Click Activate on the same card to switch it back on. As for a first activation, the purchase code is asked for and verified again; then any pending migrations run, the assets are republished, and the add-on picks up exactly where it left off.
Removing
Removing is permanent and destroys the add-on's data. The Remove button only appears on a deactivated add-on, so removal is always two steps:
- Deactivate Blog & News (see Uninstallation).
- Click Remove on its card and confirm the prompt.
The admin panel then, in one pass:
- runs the add-on's uninstall hook, if it ships one, while its code is still on disk;
- revokes the permissions declared in its
addon.json; - rolls back its migrations (this drops its database tables and every row they hold) and purges its entries from the
migrationstable, so a later reinstall migrates from scratch; - deletes its published assets:
public/addons/blog/,public/vendor/blog/andstorage/app/public/addons/blog/; - deletes the add-on directory
extensions/addons/blog/; - deletes its row in the
addonstable (the recorded purchase code goes with it) and clears the application cache.
Removal is refused, with an explanatory message and before anything is destroyed, when the add-on is still active, when another active add-on depends on it, or when the web server (PHP) user cannot delete extensions/addons/blog/. In that last case, give that user write permission on the directory and on its parent, then try again.
Deleting the folder over FTP or SSH is not equivalent: the add-on is only switched off, and its tables, its entries in the migrations table and its addons row are all left behind. Use Remove in the admin panel instead.
Troubleshooting
Blog pages return 404
- Ensure the Blog add-on is activated in Admin panel → Extensions → Add-ons.
- Run
php artisan route:clearto clear the route cache.
Post shows “Not Found” despite being published
- Check that the post status is
published(notdraft). - Ensure
published_atis set and is in the past (future-dated posts are not visible). - Verify the slug matches the URL: slugs are locale-specific. The system tries the current locale first, then English.
Category page returns 404
- Ensure the category is active (
is_active = true). - Verify the slug in the URL matches the category’s translatable slug for the current locale.
Comments not appearing on posts
- Check that
blog_comments_enabledis set totruein settings. - If using moderation, comments must be approved first. Check the admin comments page for pending items.
- Guest comments require
blog_allow_guest_commentsto be enabled.
The “Edit” action is missing on my own comment
- A comment can no longer be edited once somebody has replied to it. Delete the replies (or ask an admin to) and the Edit action comes back.
- A reply awaiting moderation also locks editing, even though it is not displayed yet. Check
Blog → Comments filtered on
?status=pending. - Editing and deleting are only offered to signed-in authors. Comments posted as a guest cannot be edited, because there is no reliable way to prove who wrote them.
- Both actions are hidden when Enable Comments is off.
A reply was posted but does not show up
- If Require Approval is on and the reply came from a guest, it is pending: only approved replies are displayed. Approve it from Blog → Comments.
- To let replies through without moderating each one, enable Auto-Approve Replies in Blog → Settings.
Posting a comment reloads the whole page
- That is the fallback used when the page’s JavaScript did not run. The comment is still saved correctly: only the no-reload behaviour is lost.
- Check the browser console for a script error on the post page, and make sure the theme assets are built and loaded.
Comment form not showing for guests
- Enable
blog_allow_guest_commentsin Blog → Settings. - The
StoreCommentRequestchecks authorization: if guest comments are disabled, the form submission returns 403.
CAPTCHA not appearing on comment form
- Ensure
blog_captcha_enabledis set totruein blog settings. - A CAPTCHA provider must be selected in Admin panel → Configuration → Settings → Security.
Email notifications not being sent
- Check that mail is configured correctly in Admin panel → Configuration → Settings → Mail.
- Verify the blog notification types are enabled in Admin panel → Configuration → Settings → Notifications (Notification Types tab).
- Reply notifications require the parent comment author to have
notify_on_reply = true. - Self-replies do not trigger notifications (by design).
Cannot delete a category: “Cannot delete category with existing posts”
The add-on prevents deleting categories that have posts assigned to them. Either reassign the posts to a different category or delete them first.
Featured image not displaying
- Check that the upload succeeded: the post’s
image_pathcolumn must not be empty. - Verify the storage symlink exists:
php artisan storage:link. - Check file permissions on the storage directory.
Search returns no results despite matching posts
- The search looks in the title, content and excerpt of the current language only: switch the site language to search posts written in another one.
- Search is pattern-matched (contains), so partial matches should work.
- Only published posts (with
published_atin the past) are included in search results.
Reading time shows “1 min” for all posts
- Ensure the post has content (the reading time is calculated from
strip_tags(content)). - Check the
blog_words_per_minutesetting: the default is 200 WPM. - Very short posts will always show 1 minute (the minimum).
Blog & News v1.0.5: A LaraClassifier / JobClass add-on.
© BeDigit. All rights reserved.