https://github.com/olssonm/ampersand
Plug and play flat file markdown blog for your Laravel-projects
https://github.com/olssonm/ampersand
blog flat-file laravel markdown
Last synced: 3 months ago
JSON representation
Plug and play flat file markdown blog for your Laravel-projects
- Host: GitHub
- URL: https://github.com/olssonm/ampersand
- Owner: olssonm
- License: mit
- Created: 2021-03-30T17:20:54.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2026-03-20T07:07:23.000Z (4 months ago)
- Last Synced: 2026-03-21T00:04:10.675Z (4 months ago)
- Topics: blog, flat-file, laravel, markdown
- Language: PHP
- Homepage:
- Size: 81.1 KB
- Stars: 27
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.YML
- License: LICENSE.md
Awesome Lists containing this project
README

# Ampersand
[](https://packagist.org/packages/olssonm/ampersand)
[](https://github.com/olssonm/ampersand/actions?query=workflow%3A%22Run+tests%22)
[](LICENSE.md)
Plug-and-play flat file markdown blog tool for your Laravel-project. Create an article or blog-section on your site without the hassle of setting up tables, models or your own flat file-system.
Built upon [spatie/sheets](https://github.com/spatie/sheets) to handle the markdown-files and YAML-front matter parsing.
>Note: This package is built for quick and easy setup and use – don't expect a fully featured CMS.
### 🛠 Install and configure
Require package:
```
$ composer require olssonm/ampersand
```
Publish config-files and views:
```
$ php artisan vendor:publish --provider="Olssonm\Ampersand\AmpersandServiceProvider"
```
In `config/ampersand.php` you can now customize the settings to your liking. Views are available at `resources/views/vendor/ampersand`
### ✏️ Writing posts
#### Filename format
All posts should be stores in your `posts_path`-directory with the filename format of `2021-03-30.my-post.md`, i.e. `{date:Y-m-d}.{slug}.md`.
The slug is what determines at what URL your post will be available at.
#### Artisan command
You can quickly create a new post via the artisan command:
```
php artisan ampersand:new
```
#### YAML front matter
Posts can contain any number of attributes via YAML-front matter:
```
---
title: This is a new post
date: '2020-01-01 20:00:01'
cover: https://amazingimages.com/my-cover.jpg
---
My post in **Markdown**
```
### 🖥 Displaying posts
Two views are shipped with this package; an index-view and a show-view (used for single posts). They are located in `/resources/vendor/views/ampersand` after installation and are fully customizable.
In `index.blade.php` a collection of post-objects is available via the `$posts`-variable. It behaves much as a standard Eloquent-collection.
``` php
@foreach ($posts as $post)
{{ $post->title }}
{!! $post->contents !!}
@endforeach
```
Pagination-links are also available:
``` php
{{ $posts->links() }}
```
The Post-object contains all your front matter attributes as well as `slug`, `date` and `contents`.
``` php
{{ $post->slug }} // my-post
{{ $post->date->format('Y-m-d') }} // 2021-03-30
{{ $post->contents }} //
My post in markdown
{{ $post->cover }} // https://amazingimages.com/my-cover.jpg
```
#### Retrieve posts in your application
You can retrieve posts and filter them as a collection anywhere in your application using the Post-model:
``` php
use Olssonm\Ampersand\Models\Post;
// Reject posts where is_draft is true or has a date in the future
$posts = Post::all()->reject(function($item) {
return $item->is_draft || $post->date->lessThan(now());
});
```
The posts are sorted by descending date per default, so to get the latest post:
``` php
// Get first post
$post = Post::all()->first();
```
### 🚦 Routes
The package routes are `ampersand.index` and `ampersand.show`:
```php
{{ route('ampersand.index') }} // http://mysite.test/blog
@foreach ($posts as $post)
// The show-route accepts either a Olssonm\Ampersand\Models\Post-object
// or a string; the post's slug
{{ route('ampersand.show', $post) }} // http://mysite.test/blog/post-slug
{{ route('ampersand.show', 'post-slug') }} // http://mysite.test/blog/post-slug
@endforeach
```
#### Defining your own routes
The default routes are registered with the ampersand-name and the default web-middleware group.
If you by any reason want to override this (for example if you want to have your articles behind a login or maybe you don't use the standard web-middleware group), you may set `register_routes` to `false` in ampersand.php, and then register them yourself:
``` php
// /routes/web.php
use Olssonm\Ampersand\Http\Controllers\PostController;
Route::group(['middleware' => 'can:read'], function() {
Route::get('/articles', [PostController::class, 'index'])->name('article.index');
Route::get('/articles/{post}', [PostController::class, 'show'])->name('article.show');
}]);
// A link to the blog index in some view
{{ route('article.index') }} // http://mysite.test/articles
```
### See it in action
Sites in the wild that uses Ampersand
[esignering.se/blogg](https://esignering.se/blogg)
*Do you use Ampersand and want your site featured here? Submit a PR!*
### License
The MIT License (MIT). Please see the [LICENSE.md](LICENSE.md) for more information.
© 2021-2026 [Marcus Olsson](https://marcusolsson.me).