soltys/slate-bundle
soltys/slate-bundle is a PHP bundle that brings Slate integration to your application, making it easy to configure and render Slate content. A lightweight option for PHP projects that need structured rich-text handling.
First, calibrate expectations. soltys/slate-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/slate.php, no facade. For a Laravel codebase you will not composer require this and get working docs — you'll read it as a reference implementation for wiring Slate into a PHP app. With 4 stars, 0 dependents, and a 0.08 score, treat it as a blueprint, not a dependency.
Minimal steps in its native habitat (Symfony):
composer require soltys/slate-bundle (check the symfony/* version constraints in composer.json first — bundles of this vintage often cap at Symfony 3/4).app/AppKernel.php (or config/bundles.php on Symfony 4+).index.html, layout, stylesheets/, javascripts/) and a directory of markdown files — one file per API section (authentication.md, users.md, errors.md).config.yml, then hit /docs.Where to look first, in this order:
README.md — config keys and the expected directory layout.DependencyInjection/Configuration.php — the authoritative list of options; the README drifts from this in small bundles.Resources/views/ — the Twig template that renders the Slate shell. This is what you'll port.First use case: a single-page, three-column API reference (nav | prose | code samples) generated from hand-written markdown, deployable as static files. That's the entire value proposition, and it's a good one — Slate's layout is still one of the most readable API doc formats.
The Laravel equivalent, which is what you actually want:
// routes/web.php
Route::get('/docs/{version?}', fn ($version = 'v1') => view('docs.slate', compact('version')));
Drop the Slate static assets into public/docs/, markdown into resources/docs/{version}/, and have the Blade view inject the version into Slate's index.html config block. You get 95% of this bundle's functionality without the Symfony coupling.
Per-version doc trees. The pattern worth copying is one directory per API version, selected by route segment. New version = new folder + a line in the version nav. This beats a single growing index.html and keeps old docs live for clients on deprecated versions.
Generate markdown from your contract, don't hand-write it. The bundle only reads markdown — it doesn't know your routes. For a Laravel app, run widdershins or openapi-generator over your OpenAPI spec in CI:
openapi.yaml --(widdershins)--> resources/docs/v1/*.md --(slate build or JS fetch)--> /docs
This is the pattern that makes the docs survive refactors. Hand-maintained markdown rots within a sprint or two.
Serve static, don't render per-request. Slate is a static site generator by design: the markdown is compiled or fetched once and the browser does the rest. If you're rendering through a controller on every hit, you're paying framework boot cost for content that changes on deploy. Prefer an artisan docs:build command that writes to public/docs/ and let Nginx/Apache serve it. Use the Laravel route only for local development.
Gate the docs deliberately. API reference is often semi-public — you want /docs open but versioned drafts behind auth. Apply middleware per-version rather than globally:
Route::get('/docs/{version}', ...)->middleware('can:view-docs,version');
Integration tip — link from the API itself. Return the docs URL in your /api root response and in error payloads ("docs": "https://api.example.com/docs/v1#errors-429"). Anchors in Slate are stable (derived from heading text), so deep links into error sections work well and dramatically reduce support tickets.
Extension point (Symfony side): template overriding. Bundles of this style expect you to copy Resources/views/* into app/Resources/SoltysSlateBundle/views/ and edit. There's no event system or plugin API — if you need behavior changes, you fork the controller. Plan for that.
The framework mismatch is the headline gotcha. Everything below /docs assumes Symfony's container, routing, and Twig. There is no Laravel bridge, and with 0 dependents it's unlikely one appears. Budget an afternoon to port the view + static assets, not an hour to integrate.
Maintenance risk is real. 4 stars, 0 dependents, and a bundle that wraps a front-end project means you are pinned to whatever Slate version it vendored — likely years old, with the associated jquery/lunr/highlight.js CVEs. Run composer audit and check the bundled javascripts/ against current Slate. If you adopt it, vendor the assets into your own repo so a Packagist takedown doesn't break your deploy.
Asset path breakage under subdirectories. Slate's index.html uses relative paths for stylesheets/, javascripts/, and its markdown fetch. Deploy under example.com/api/docs/ rather than a domain root and you'll get a blank page with 404s in the console. Fix by setting the base path explicitly in the Slate layout config, and check the <script> tags, not just the CSS.
Route prefix collisions. /docs is a popular path — Laravel Nova, Telescope, and several packages claim adjacent routes. Dump your routes (php artisan route:list) before wiring anything, and prefer /api-docs or /developers if there's any chance of a clash.
Caching bites on redeploy. Slate fetches markdown at runtime; browsers and CDNs cache those .md files aggressively. Without cache-busting (hashed filenames or Cache-Control: no-cache on the markdown), clients see stale docs after a deploy and file bugs against your API for a problem that only exists in their browser cache. Version the markdown paths (/docs/v1/…) and this mostly evaporates.
Debugging config in Symfony: bin/console debug:config soltys_slate shows the resolved configuration after defaults and env overrides — far faster than reading YAML. If the docs render but are empty, it's almost always a wrong doc-root path (relative to the Symfony kernel root, not the bundle) or a markdown filename mismatch.
Consider the modern alternatives before investing. Slate is effectively in maintenance mode. Scalar, Redoc, and Stoplight Elements all render an OpenAPI spec directly with no markdown pipeline, no build step, and one npm/CDN dependency. If your API has a spec (it should), these are a strictly shorter path to the same outcome — and none of them require you to port a Symfony bundle.
If you do adopt the approach: pin the version, vendor the assets, generate markdown from your spec in CI, serve static, and write the /docs route yourself in routes/web.php. The bundle's contribution — "serve Slate's HTML with a configurable doc root" — is about forty lines you can own outright.
How can I help you explore Laravel packages today?