Download the PHP package dirkblack/blog without Composer

On this page you can find all versions of the php package dirkblack/blog. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package blog

dirkblack/blog

A Laravel 12 composer package that installs a full-featured blog with a Vue 3 SPA frontend and Laravel API backend.

Features

Requirements

Installation

1. Require the package

The service provider is auto-discovered — no manual registration needed.

2. Publish assets and config

3. Run migrations

This creates the blog_posts, blog_comments, and blog_user_roles tables (plus spatie tag/media tables if not already present).

4. Assign your first admin

Or use the HasBlogRole trait on your User model:

5. Visit your blog

Navigate to /blog (or your configured prefix) in your browser.

Configuration Reference

Publish the config with php artisan vendor:publish --tag=blog-config. All options are in config/blog.php:

Route Prefix

All blog routes are prefixed with this value. Change to 'news' and your blog lives at /news.

Middleware

Add your own middleware (e.g., 'auth' to restrict the entire blog to logged-in users).

User Model

The fully qualified class name of your application's User model. Used for author relationships and role assignments.

Comments

Media

Set BLOG_MEDIA_DISK in your .env to use a different storage disk (e.g., s3).

Notifications

Set to true and ensure your User model uses the Notifiable trait.

Load Default CSS

When true, the package serves its built-in stylesheet. Set to false if you've published and customized the styles.

Footnotes

Customize the CSS classes and ID prefixes used by the footnote extension. The defaults work well with the built-in stylesheet. See Footnotes for syntax details.

Markdown Class Map

Apply CSS/Tailwind classes to all rendered markdown HTML elements globally. Empty strings are ignored. See the HTML Class Map section below.

Roles & Authorization

The package uses a 4-tier role system stored in the blog_user_roles pivot table:

Role Level Capabilities
guest 0 Read public posts and pages
member 1 All guest capabilities + post comments
author 2 All member capabilities + create/edit/delete own posts, manage own media
admin 3 All author capabilities + manage all posts, moderate comments, assign roles

Using the HasBlogRole Trait

Add the trait to your User model for convenience methods:

Using BlogRoleResolver Directly

API Reference

All API routes are prefixed with /{prefix}/api (default: /blog/api). Responses use JSON:API-style resource formatting.

Public Endpoints (no authentication required)

Method Endpoint Description
GET /posts List published posts (paginated). Query: ?page=, ?tag=
GET /posts/{slug} View a single published post
GET /pages List published pages
GET /pages/{slug} View a single published page
GET /tags List all tags with post counts
GET /posts/{slug}/comments List approved comments (threaded)
GET /auth/user Get current authenticated user and blog role

Member Endpoints (authentication required)

Method Endpoint Description
POST /posts/{slug}/comments Create a comment. Body: { "body": "...", "parent_id": null }
PUT /comments/{id} Update own comment. Body: { "body": "..." }
DELETE /comments/{id} Delete own comment

Author Endpoints (author role required)

Method Endpoint Description
GET /author/posts List own posts (all statuses). Query: ?status=, ?search=, ?page=
POST /author/posts Create post. Body: { "title", "body_markdown", "type", "tags": [] }
GET /author/posts/{id} View own post with media
PUT /author/posts/{id} Update own post
DELETE /author/posts/{id} Soft-delete own post
POST /author/posts/{id}/publish Publish immediately or schedule. Body: { "scheduled_at": null }
POST /author/posts/{id}/unpublish Revert to draft
GET /author/posts/search Search posts by title. Query: ?q=
POST /author/preview-markdown Preview rendered markdown. Body: { "body_markdown": "..." }
GET /author/media List own media (paginated)
POST /author/posts/{id}/media Upload media file (multipart form)
DELETE /author/media/{id} Delete media

Admin Endpoints (admin role required)

Method Endpoint Description
GET /admin/posts List all posts (all authors, all statuses)
PUT /admin/posts/{id} Update any post
DELETE /admin/posts/{id} Delete any post
GET /admin/comments List all comments. Query: ?status=
PUT /admin/comments/{id}/approve Approve a comment
PUT /admin/comments/{id}/spam Mark comment as spam
DELETE /admin/comments/{id} Delete a comment
GET /admin/users List users with blog roles. Query: ?role=, ?search=, ?page=
PUT /admin/users/{id}/role Assign blog role. Body: { "role": "author" }

AI Integration (MCP)

The blog ships an MCP server so a site owner can build and maintain the site by working with Claude (or any MCP-capable AI client). It's opt-in and off by default. The AI acts as a real blog user — bounded by the blog role system, a writes switch, a destructive-actions switch, and per-token abilities — and every mutation is audited.

1. Requirements

Add Laravel Sanctum's trait to your host User model (the one change the AI feature needs):

Publish Sanctum's migration if you haven't (php artisan vendor:publish --tag=sanctum-migrations) and migrate.

2. Enable it

Set the flags in config/blog.php (or via env). They are layered, strictest last:

Setting (blog.ai.*) Env Default Effect
enabled BLOG_AI_ENABLED false Master switch — the /blog/api/ai + /blog/mcp routes 404 when off
write_enabled BLOG_AI_WRITE_ENABLED false Allow create/update/publish/tag/moderate/upload tools
allow_destructive BLOG_AI_ALLOW_DESTRUCTIVE false Allow delete-post, delete-comment, assign-role
rate_limit BLOG_AI_RATE_LIMIT 60,1 Throttle for AI routes (max,minutes)
audit BLOG_AI_AUDIT true Log AI mutations to blog_ai_audit

3. Mint a token

The token resolves to that user, so its blog role still governs what it can do. Abilities are a second, narrower gate:

Ability Unlocks
posts:read read/search posts, tags, preview, validate, maintenance tools
posts:write create / update / publish / tag posts, upload media
posts:delete delete posts (destructive)
comments:read list comments
comments:moderate approve/spam/delete comments (delete is destructive)
users:manage assign roles (destructive)

4. Connect a client

What the AI can do

The server also exposes resources that teach the AI your conventions (blog://guide/markdown, blog://guide/shortcodes, blog://guide/roles, blog://site/config) and prompts for common workflows (draft-post, build-home-page, weekly-maintenance).

Note: upload-media can fetch from a URL server-side. Only enable writes for tokens you trust.

Custom Markdown Syntax

The blog includes a custom markdown engine built on league/commonmark with GitHub Flavored Markdown support, footnotes, and three custom extensions.

All standard markdown and GFM features work out of the box (headings, bold, italic, lists, tables, strikethrough, code blocks, etc.).

Footnotes — Citations & References

Add footnotes using standard markdown syntax. References render as superscript numbered links, and a footnote section with backlinks is auto-generated at the bottom of the content.

Named references can be reused: write [^label] multiple times and they all link to the same [^label]: definition. Labels are for authoring only — the rendered output is auto-numbered by order of first reference.

The footnote section, backref symbol (↩), and CSS classes are all configurable via config('blog.footnotes').

WikiLinks — Internal Post & Page Links

Link to other posts and pages using double-bracket syntax. The renderer automatically resolves the slug to a URL and pulls the post title as the link label.

Slugs are unique across all content, so you only need the slug — the renderer looks up the target and links to the correct URL whether it's a post (/blog/about-us) or a page (/blog/page/about-us), using the right title as the label.

The page: / post: prefix is an optional authoring hint, not required for linking. Because the type is derived from the resolved record, it is ignored when the target already exists. It only matters for a missing target: the prefix tells the "create" link what type to scaffold. Write [[page:future-page]] if you want a not-yet-existing link to create a page (otherwise it defaults to a post).

Existing targets render as: <a href="/blog/my-post-slug" class="wiki-link">My Post Title</a> (pages link to /blog/page/{slug}).

Missing targets render as red links with a wiki-link--missing class, linking to the creation page with the slug — and the type hint, if given — pre-filled. The URL prefix respects your blog.prefix config value.

Image Classes — CSS Classes on Images

Append CSS classes to images using curly-brace syntax after the standard markdown image tag:

Produces: <img src="/images/sunset.jpg" alt="Sunset photo" class="half-right" />

Predefined class shortcuts: .half-right, .half-left, .banner, .thumbnail. You can use any CSS class.

HTML Class Map — Global CSS Classes on Rendered Elements

Apply CSS classes to all rendered markdown elements via the markdown_classes config. Supports 12 element types: h1, h2, h3, p, ul, ol, blockquote, code, pre, a, img, table.

Empty strings are ignored — only elements with non-empty class values get modified.

Auto-Rendering on Save

Markdown is automatically converted to HTML whenever a post is saved:

Using the Converter Directly

The converter is registered as a singleton, so the CommonMark environment is only built once per request.

Theming & CSS Customization

Built-in Styles

The package ships with a Tailwind CSS v4 stylesheet scoped under .blog-app. It includes:

Customizing Styles

Option 1: Override via Markdown Class Map — Use config('blog.markdown_classes') to apply your own Tailwind/CSS classes to rendered markdown elements without touching CSS.

Option 2: Publish and Modify the Stylesheet

This copies the CSS to resources/css/vendor/blog.css. Include it in your own build pipeline and set config('blog.load_default_css') to false.

Option 3: Override with Custom CSS — The .blog-app scope and .blog-prose content class make it straightforward to override styles in your app's stylesheet.

Asset Publishing

Tag Destination Description
blog-assets public/vendor/blog/ Compiled JS and CSS (required)
blog-config config/blog.php Configuration file
blog-migrations database/migrations/ Migration files
blog-views resources/views/vendor/blog/ Blade templates
blog-styles resources/css/vendor/blog.css Source CSS for custom builds

Post Scheduling

Posts can be scheduled for future publication:

The blog:publish-scheduled command runs every minute via Laravel's scheduler to auto-publish due posts. Ensure php artisan schedule:run is in your crontab.

When a scheduled post is published, the author can optionally receive an email notification (set config('blog.notifications.post_published') to true).

Testing

PHP Tests (Pest)

170 tests covering models, enums, policies, middleware, all API endpoints, markdown extensions, link tracking, and the scheduling system.

JavaScript Tests (Vitest)

95 tests covering all 6 Pinia stores, 7 Vue components, and composables.

License

MIT


All versions of blog with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
laravel/framework Version ^12.0 || ^13.0
spatie/laravel-tags Version ^4.0
spatie/laravel-medialibrary Version ^11.0
league/commonmark Version ^2.0
symfony/html-sanitizer Version ^7.0
laravel/sanctum Version ^4.0
laravel/mcp Version ^0.7
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package dirkblack/blog contains the following files

Loading the files please wait ...