A Website For Yancy

by Doug Bell
(he, him, his)
@preaction
preaction
preaction.me/mojo
CC-BY-SA 4.0

For navigation help, press ?
For speaker view and notes, press S
For full-screen, press F

A Website For Yancy

  • Project Intro
  • Links
  • Documentation
  • Static Site

No Static Site Generator

A Yancy Markdown Site

  • Mojolicious
  • Yancy
  • (Bootstrap)
  • Mojo::SQLite

myapp.pl

#!/usr/bin/env perl
use Mojolicious::Lite;

Database Schema

db Helper

#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojo::SQLite;
helper db => sub {
    state $db = Mojo::SQLite->new( 'sqlite:docs.db' );
    return $db;
};

Schema Migrations

app->db->migrations->from_string( <<ENDSQL );
-- 1 up
CREATE TABLE pages (
    path VARCHAR PRIMARY KEY,
    markdown TEXT,
    html TEXT
);
ENDSQL
app->db->auto_migrate(1);

Configure Yancy

plugin 'Yancy', {
    backend => { Sqlite => app->db },
    read_schema => 1,
    schema => {
        pages => {
            properties => {
                markdown => {
                    format => 'markdown',
                    'x-html-field' => 'html',
                },
            },
        },
    },
};

Routes

get '/*id' => ...;

Destination

get '/*id' => 'index';
get '/*id' => sub {
    my ( $c ) = @_;
    $c->render( text => 'Hello' );
};

Controller

get '/*id' => sub {
    my ( $c ) = @_;
    $c->render( text => 'Hello' );
};
package MyApp::Controller::MyController;
use Mojo::Base 'Mojolicious::Controller';
sub hello {
    my ( $c ) = @_;
    $c->render( text => 'Hello' );
}
get '/*id' => {
    controller => 'MyController',
    action => 'hello',
};
get '/*id' => 'MyController#hello';

Yancy Controller

get '/*id' => {
    controller => 'yancy', # Yancy::Controller::Yancy
    action => 'get',
    schema => 'pages',
    template => 'pages',
    id => 'index', # Default to index page
};

Finish the App

app->start;

Template

__DATA__
@@ pages.html.ep
%== $item->{html}
<%== $item->{html} %>
<% my $html = $item->{html} %>
<%== $html %>
% if ( $item->{html} ) {
    %== $item->{html}
% }
% if ( $item->{html} ) {
    <h1><%= $item->{path} %></h1>
    %== $item->{html}
% }

Try it out!

$ perl myapp.pl daemon
[Wed Jan 23 23:24:28 2019] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000

Yancy Editor

Up Next

  • Documentation
  • Style
  • Deploy

PODViewer

Mojolicious::Plugin::PODViewer

Add Plugin

plugin 'PODViewer', {
    default_module => 'Yancy',
    allow_modules => [qw(
        Yancy Mojolicious::Plugin::Yancy
    )],
};

Style

  • Bootstrap Layout
  • Navigation Bar
  • Code Style

Layouts

default Layout

__DATA__
@@ layouts/default.html.ep

Building a Layout

__DATA__
@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
    <head>
        <title><%= title %></title>
        %= stylesheet "/yancy/bootstrap.css"

Building a Layout

<main class="container">
    <%= content %>
</main>

Content Sections

@@ pages.html.ep
% content_for 'head' => begin
    %= javascript 'vue.js'
% end
@@ layouts/default.html
<head>
    %= content 'head'
</head>
<body>
    %= content
</body>

Code Style

pre {
    border: 1px solid #ccc;
    border-radius: 5px;
    background: #f6f6f6;
    padding: 0.6em;
}
.crumbs .more {
    font-size: small;
}

Use the Layout

plugin 'PODViewer', {
    layout => 'default',
};
get '/*id' => {
    layout => 'default',
};
app->defaults({ layout => 'default' });

Static Export

  • Rewrite redirects
  • Prefix /yancy

export Command

Mojolicious::Command::export

Run an Export

$ perl myapp.pl export \
    --base /yancy \
    --to ./deploy

Deploy

# [r]ecursive, [v]erbose, [z]ipped, [m]odified dates
# --delete files from destination not in source
rsync -rvzm --delete ./deploy/. \
    preaction.me:/var/www/yancy/.

Questions?

Postscript

Static Site Generator

Yancy::Backend::Static

---
title: Yancy
---
# Yancy

Yancy is a simple Content Management System written for
[the Mojolicious web framework](http://mojolicious.org).

plugin Yancy => {
    backend => 'static:' . app->home,
    read_schema => 1,
};

Thank You