A Laravel publishing platform. Canvas is a fully open source package to extend your existing application and get you up-and-running with a blog in just a few minutes. In addition to a distraction-free writing experience, you can view monthly trends on your content, get insights into reader traffic and more!
Note: Canvas requires you to have user authentication in place prior to installation. For Laravel 5.* based projects you may run the
make:auth
Artisan command to satisfy this requirement. For Laravel 6.* based projects please see the official guide to get started.
You may use composer to install Canvas into your Laravel project:
composer require cnvs/canvas
Publish the assets and primary configuration file using the canvas:install
Artisan command:
php artisan canvas:install
Create a symbolic link to ensure file uploads are publicly accessible from the web using the storage:link
Artisan command:
php artisan storage:link
After publishing Canvas's assets, a primary configuration file will be located at config/canvas.php
. This file allows you to customize various aspects of how your application uses the package.
Canvas exposes a simple UI at /canvas
by default. This can be changed by updating the path
option:
/*
|--------------------------------------------------------------------------
| Base Route
|--------------------------------------------------------------------------
|
| This is the URI path where Canvas will be accessible from. You are free
| to change this path to anything you like. Note that the URI will not
| affect the paths of its internal API that aren't exposed to users.
|
*/
'path' => env('CANVAS_PATH_NAME', 'canvas'),
/*
|--------------------------------------------------------------------------
| Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be attached to every route in Canvas, giving you
| the chance to add your own middleware to this list or change any of
| the existing middleware. Or, you can simply stick with the list.
|
*/
'middleware' => [
'web',
'auth',
],
/*
|--------------------------------------------------------------------------
| Storage
|--------------------------------------------------------------------------
|
| This is the storage disk Canvas will use to put file uploads. You may
| use any of the disks defined in the config/filesystems.php file and
| you may also change the maximum upload size from its 3MB default.
|
*/
'storage_disk' => env('CANVAS_STORAGE_DISK', 'local'),
'storage_path' => env('CANVAS_STORAGE_PATH', 'public/canvas'),
'upload_filesize' => env('CANVAS_UPLOAD_FILESIZE', 3145728),
Note: If you'd rather have the following setup run automatically, just use this command to scaffold a Medium-inspired frontend. Aside from general post listings, you'll get localized content, reading suggestions and more!
Canvas takes care of the backend while giving you the freedom to display the final content however you choose. A very simple setup would include a controller, some views, and a few routes. Take a look at the following example:
Define a few routes inside of routes/web.php
:
// Get all published posts
Route::get('blog', 'BlogController@getPosts');
// Get posts for a given tag
Route::get('tag/{slug}', 'BlogController@getPostsByTag');
// Get posts for a given topic
Route::get('topic/{slug}', 'BlogController@getPostsByTopic');
// Find a single post
Route::middleware('Canvas\Http\Middleware\Session')->get('{slug}', 'BlogController@findPostBySlug');
Add the corresponding methods inside of a new BlogController
:
public function getPosts()
{
$data = [
'posts' => \Canvas\Post::published()->orderByDesc('published_at')->simplePaginate(10),
];
return view('blog.index', compact('data'));
}
public function getPostsByTag(string $slug)
{
if (\Canvas\Tag::where('slug', $slug)->first()) {
$data = [
'posts' => \Canvas\Post::whereHas('tags', function ($query) use ($slug) {
$query->where('slug', $slug);
})->published()->orderByDesc('published_at')->simplePaginate(10),
];
return view('blog.index', compact('data'));
} else {
abort(404);
}
}
public function getPostsByTopic(string $slug)
{
if (\Canvas\Topic::where('slug', $slug)->first()) {
$data = [
'posts' => \Canvas\Post::whereHas('topic', function ($query) use ($slug) {
$query->where('slug', $slug);
})->published()->orderByDesc('published_at')->simplePaginate(10),
];
return view('blog.index', compact('data'));
} else {
abort(404);
}
}
public function findPostBySlug(string $slug)
{
$posts = \Canvas\Post::with('tags', 'topic')->published()->get();
$post = $posts->firstWhere('slug', $slug);
if (optional($post)->published) {
$data = [
'author' => $post->user,
'post' => $post,
'meta' => $post->meta,
];
// IMPORTANT: This event must be called for tracking visitor/view traffic
event(new \Canvas\Events\PostViewed($post));
return view('blog.show', compact('data'));
} else {
abort(404);
}
}
Finally, just create index.blade.php
and show.blade.php
inside a /views/blog
directory to display your data.
Note: The following components are optional features, you are not required to use them.
Just run php artisan canvas:setup
after installing Canvas. Then, navigate your browser to http://your-app.test/blog
or any other URL that is assigned to your application. This command scaffolds a default frontend for your entire blog!
Want access to the entire Unsplash library?
Set up a new application at https://unsplash.com/oauth/applications, grab your access key, and update config/canvas.php
:
/*
|--------------------------------------------------------------------------
| Unsplash Integration
|--------------------------------------------------------------------------
|
| Visit https://unsplash.com/oauth/applications to create a new Unsplash
| app. Use the confidential Access Key given to you to integrate with
| the API. Note that demo apps are limited to 50 requests per hour.
|
*/
'unsplash' => [
'access_key' => env('CANVAS_UNSPLASH_ACCESS_KEY'),
]
Canvas allows users to receive a weekly summary of their authored content. Once your application is configured for sending mail, update config/canvas.php
:
/*
|--------------------------------------------------------------------------
| E-Mail Notifications
|--------------------------------------------------------------------------
|
| This option controls e-mail notifications that will be sent via the
| default application mail driver. A default option is provided to
| support the notification system as an opt-in feature.
|
|
*/
'mail' => [
'enabled' => env('CANVAS_MAIL_ENABLED', false),
]
Since the weekly digest runs on Laravel's Scheduler, you'll need to add the following cron entry to your server:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Canvas releases are versioned as MAJOR.MINOR.PATCH
numbers
- A major or minor version can contain breaking changes, so follow the upgrade guide for a step-by-step breakdown
- Patch versions will remain backwards compatible, so you can safely update the package by following the steps below:
You may update your Canvas installation using composer:
composer update
Run any new migrations using the migrate
Artisan command:
php artisan migrate
Re-publish the assets using the canvas:publish
Artisan command:
php artisan canvas:publish
Run the tests with:
composer test
One of the goals for the team behind Canvas is to ensure proper localization across the app. If you come across any translation mistakes or issues and want to make a contribution, please create a pull request. If you don't see your native language included in the resources/lang
directory, feel free to add it.
Canvas is open-sourced software licensed under the MIT license.
- The team that continues to support and develop this project
- Logo design and branding by Katerina Limpitsouni
- Thanks to Mohamed Said and his open source project Wink
- Anyone who has contributed a patch or made a helpful suggestion