Laravel Wink

Published:
Apr 20th 2021


Reading Time:
11 minutes

blog Mike Jones Writer

A bit of background.

What is Laravel Wink? Put it simply, Laravel Wink is the incredible package put together by Mohamed Said one of Laravel's full time developers. The package itself is a medium like blogging platform which hands over all front end control to the user instead of forcing constrains of "use this theme/template" on you. It's lightweight and is used to manage the Official Laravel Blog and divinglaravel.com. It is incredibly simple to use and take around 5 - 10 minutes to setup the back-end so you can concentrate on the appearance of your blog.

Wink is used for this blog and another project im working on which will be announced in a few months...

Is it difficult to install

Absolutely not, as mentioned above it takes around 10 mins from start to finish to get it working.

il talk through the steps now, Some of this is taken from the Wink GitHub Page and other bits have been found across the internet.

So here goes!

First off we will start with a fresh Laravel Project;

laravel new {wink-project-name}

Create yourself a local DB and update your laravel .ENV Mine for this example is below.

APP_NAME="Wink Test"
APP_ENV=local
APP_KEY=base64:Z6u+ysna0yN2zCM1O94Z2Rz5MyeMZ4vB9IZH+Qrpe+s=
APP_DEBUG=true
APP_URL=http://wink.vm

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wink
DB_USERNAME={DB-USERNAME}
DB_PASSWORD={DB-PASSWORD}

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

Once that's been done (CD to your projects root) and run the usual Laravel install commands.

composer install
npm install && npm run dev
php artisan migrate´╗┐

That's Laravel done, time to move on to Wink

Install Wink

If you head over to the Wink GitHub page these instructions are there also, i'll be expanding on them slightly with examples from what i did with this blog.

composer require themsaid/wink
php artisan wink:install
php artisan storage:link

There is a few other tutorials out there which will tell you to use an old composer require which caused a whole load of headaches for me, so just stick with these instructions or the ones from the Wink GitHub page.

Now this bit is your choice, Open up the file: config/wink.php so we can start making changes.

The first change is the database connection, it currently defaults to "WINK_DB_CONNECTION" But this doesn't exist. you can create it if you wish and continue with that or you can include it with your DB you setup at the beginning. i tend to go with the latter choice for ease of use and to do this you simply change

'database_connection' => env('WINK_DB_CONNECTION', 'wink'),

to

'database_connection' => env('DB_CONNECTION', 'wink'),

That's it for the DB..... Dead simple right?

Now onto the Preview settings.... this took me longer than id care to admit to figure out.... but for some reason when i was building my app i could never "Preview my post" as i was getting a 404 each time. Turns out its a setting in this wink.php file.

Line 79 has:

'preview_path' => '/{postSlug}',

Later on in this tutorial we will create blog routes which need to be reflected here. so change the above too:

'preview_path' => 'blog/{postSlug}',

it will become clearer later on in this post.

You can also update a number of other things in here also which you are free too do. a popular change is the "wink path" which is used to get to the wink back-end www.wink.vm/wink.

and finally in this config file scroll to line 94 and choose which method of editor you want to use. for the blog your reading now im using Rich Text editor with Tailwind. so if you wanna do something similar change the line from:

'default' => null, 

to

'default' => 'rich',

What do the three default options do?

  • Null - Gives you a choice of Markdown or Rich text editor. This is ok if you are the sole writer but if you have multiple writers there is a chance they could mess up and flip between editors.
  • Markdown - Yep you guessed it, gives you and editor for markdown text only. one nice way i found to use this was to write my post using Stackedit.io and copy the content from that over to Wink. That way you get a preview as your writing. Only thing you need to look at whilst doing this is the Images. u cant add them to stack edit and copy it over unless you're hosting your images off site.
  • Rich Text - I'm using this so i can use Tailwind and Tailwind Prose. basically WISYWIG, very easy to use and has all the function available to you whilst typing.

Now run:

php artisan wink:migrate

This command runs your migrations but will also generate a temp user and login for wink (Shown below)

Migrating: 2018_10_30_000000_create_tables
Migrated: 2018_10_30_000000_create_tables (534.79ms)
Migrating: 2018_11_16_000000_add_meta_fields
Migrated: 2018_11_16_000000_add_meta_fields (160.59ms)
Migrating: 2020_05_17_000000_add_markdown_field
Migrated: 2020_05_17_000000_add_markdown_field (40.27ms)
Wink is ready for use. Enjoy!
You may log in using admin@mail.com and password: hYD0wkgvJy31pf00

now in your browser type your project URL in followed by /wink in my example my url was http://wink.vm/wink You will be faced with a login and you just need to use the credentials the wink:migrate gave you. You will now be faced with the main Wink page.

You could dive right in and start writing your posts but i suggest sorting out your profile first.

Click the blue Circle top right to go to the profile, In here update all the information you want. If you have a wordpress account attached to the Email address you use here it will pick up the gravatar from it and display it like in the below screenshot.

Building the Controller(s)

Now depending how you want to do this there is a few options. In the current projects i'm working on i'm displaying the blog posts on my home page using a livewire component and paginating it to display 4 "tiles" only, then a separate page will have the archive on it paginated to 12 tiles per page.

For this example i'll stick with the "Blog index" and "post index page" which is used a lot online.

First off in this example i'm just going to extend the standard Laravel Welcome blade but usually you would have set you're templates up by now and would be working around that.

In the terminal run:

php artisan make:controller BlogController

Inside of this controller paste the following lines of code into it, these will control the Blog Post page and also the Blog Index.

public function index()
{
    $posts = WinkPost::with('tags')
        ->live()
        ->orderBy('publish_date', 'DESC')
        ->simplePaginate(6);

    return view('blog.index', [
        'posts' => $posts,
    ]);
}

Make sure you are importing the Wink Post at the top of the controller with:

use Wink\WinkPost;

Lets break it down.. This session is looking for all active (live) posts with all associated tags sorting them descending and only displaying 6 of them.

Its storing all of this inside of an array called $posts and passing it to our Blade.... which we are going to make now... you can make these view locations what ever you want. I'm unsure where i got this snippet from as i done it a year ago and just reused it in my projects :P .

Now create a file inside a directory "resources/views/blog/index.blade.php" and extend the blade like so:

@extends('layouts.app')
@section('content')
    <section class="text-gray-700 body-font">
        <div class="container px-8 pt-24 mx-auto lg:px-4">
            <div class="flex flex-wrap text-left">
                @foreach($posts as $post)
                    <div class="px-8 py-6 lg:w-1/3 md:w-full">
                        <div class="p-6 bg-gray-200 rounded-md">
                            <img class="object-cover object-center w-full h-40 mb-6 rounded" src="{{ $post->featured_image }}" alt="content">
                            <h2 class="mb-3 text-lg font-semibold text-gray-700 lg:text-2xl title-font"> {{ $post->title }} </h2>
                            <p class="mb-4 text-base leading-relaxed">{{ $post->excerpt }}</p>
                            <p class="mb-4 text-xs text-gray-600">Published: {{ $post->publish_date }}</p>
                            <a href="/blog/{{ $post->slug }}" class="inline-flex items-center font-semibold text-blue-700 md:mb-2 lg:mb-0 hover:text-blue-400 ">
                                Read More...
                            </a>
                        </div>
                    </div>
                @endforeach
            </div>
        </div>
    </section>
@endsection

I have used one of the components from Wicked Blocks for ease of use. I've not installed Tailwind in this project I've just used the CDN for it. you can use this as well if you're just testing but if you are going live go with Tailwind 2.0 Install. The CDN to test is: <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"> To use this in your project you just need to add it above the </head> tag.

Now inside you "Routes/web.php" insert the routes for the blog page and post pages:

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/blog', 'BlogController@index');
Route::get('blog/{slug}', 'BlogController@show');

Now the is the only bit of Wink i'm not keen with yet. there i no way to have Demo Data out of the box yet, Someone has requested it on GitHub but nothing yet. so before we visit our blog index go and create a post in the wink admin.

Something else to take into account here is if you are using Laravel 8, by default controller namespace is commented out and needs to be un-commented for this to work. so on line 29 of the "app/providers/RouteServiceProvider.php" you need to un-comment // protected $namespace = 'App\\Http\\Controllers';

Whilst creating your post take note of the sliders Icon next to your profile picture.... this is where you add things like the Cover photo, Excerpt tags and so on, Make sure you do this so we can see what is being passed to the blade shortly.

Now you have created your test post go to http://wink.vm/blog (replace wink.vm with what you set earlier as your application URL.

If you have followed this so far you should see this:

Beautiful right :)

You can make these tiles look however you want.... especially if you're using the awesome Tailwind CSS.

Now onto the actual Post page. Very similar story as the blog/index.blade.php were going to create one for post. create an index.blade.php inside of "resources/views/post/index.blade.php" and paste the following code (or your own):

@extends('layouts.app')
@section('content')
    <section class="p-48">
        <div class="mb-4 md:mb-0 w-full mx-auto relative">
            <div class="px-4 lg:px-0">
                <h2 class="text-4xl font-semibold text-gray-800 leading-tight"> {{ $post->title }} </h2>
                <p class="py-2 text-green-700 inline-flex items-center justify-center mb-2"> {{ implode(' - ', $post->tags->map->name->toArray())}} </p>
            </div>
            <img src="{{ $post->featured_image }}" class="w-full object-cover lg:rounded" style="height: 28em;"/>
        </div>
        <div class="flex flex-col lg:flex-row lg:space-x-12">
            <div class="px-4 lg:px-0 mt-12 text-gray-700 text-lg leading-relaxed w-full lg:w-3/4">
                <p class="pb-6 prose xl:prose">{!! $post->body !!}</p>
            </div>
            <div class="w-full lg:w-1/4 m-auto mt-12 max-w-screen-sm">
                <div class="p-4 border-t border-b md:border md:rounded">
                    <div class="flex py-2">
                        <img src="{{ $post->author->avatar }}" class="h-10 w-10 rounded-full mr-2 object-cover"/>
                        <div>
                            <p class="font-semibold text-gray-700 text-sm">{{ $post->author->name }} </p>
                            <p class="font-semibold text-gray-600 text-xs"> Site Developer </p>
                        </div>
                    </div>
                    <p class="text-gray-700 pt-3 pb-4"> {!! $post->author->bio !!} </p>
                    <button class="px-2 py-1 text-gray-100 bg-green-700 flex w-full items-center justify-center rounded"> Follow </button>
                </div>
            </div>
        </div>
    </section>
@endsection

Now if you visit your page you will get the basic post page...

i used a very basic example from TailwindComponents for this demo but you can make it look however you want. nice and clean or crazy like my blog.

And that's about it.... there is plenty of other stuff you can do with stuff that's built into wink from scratch. the beautiful thing about Wink is its simplicity and the ability to customise it to how YOU want it to look.

As always, if you have any questions please give me a shout.