Skip to content

Kirby 4.1.2

Portfolio

Highlight your projects

Projects overview

/site/blueprints/pages/projects.yml
title: Projects
preset: pages
icon: 🖼

drafts:
  extends: sections/projects
  label: Project Drafts

listed:
  extends: sections/projects
  label: Published Projects
  layout: cards

File cover blueprint

We'll create a cover blueprint file for the project to reference a certain image as being more special than just an image. This will be useful since we'll be able to specify what image will represent the project.

/site/blueprints/files/cover.yml
extends: files/image

Reusable projects section

/site/blueprints/sections/projects.yml
type: pages
label: Projects
parent: kirby.page('projects')
layout: cards
template: project
image:
  query: page.images.template("cover").first
  ratio: 3/2
  cover: true
info: "{{ page.year }}"

Note that the above section will throw an error in the Panel as long as the given parent page does not exist in the file system.

Result

Single project

/site/blueprints/pages/project.yml
title: Project
preset: page

status:
  draft: Draft
  listed: Published

fields:
  headline:
    type: text
    width: 3/4
    required: true
  year:
    type: number
    min: 2000
    default: 2018
    required: true
    width: 1/4
  tags:
    type: tags
  intro:
    type: textarea
    size: small
  text:
    type: textarea
    size: large

sidebar:
  cover:
    type: files
    label: Cover
    layout: cards
    info: "{{ file.dimensions }}"
    template: cover
    min: 1
    max: 3
  gallery:
    type: files
    label: Gallery
    template: image

Result

Example projects template

/site/templates/projects.php
<?php snippet('header') ?>

<main>
  <?php snippet('intro') ?>

  <ul class="projects"<?= attr(['data-even' => $page->children()->listed()->isEven()], ' ') ?>>
    <?php foreach ($page->children()->listed() as $project): ?>
    <li>
      <a href="<?= $project->url() ?>">
        <figure>
          <?= $project->images()->findBy("template", "cover") ?>
          <figcaption><?= $project->title() ?> <small><?= $project->year() ?></small></figcaption>
        </figure>
      </a>
    </li>
    <?php endforeach ?>
  </ul>
</main>

<?php snippet('footer') ?>

Example project controller and template

Controller

/site/controllers/project.php
<?php

return function ($page) {

    $gallery = $page->images()->filterBy("template", "image")->sortBy("sort");

    return [
        'gallery' => $gallery
    ];

};

Template

/site/templates/project.php
<?php snippet('header') ?>

<main class="project">
  <article>

    <header>
      <?php if ($cover = $page->images()->findBy("template", "cover")): ?>
      <figure class="project-cover">
        <?= $cover ?>
        <figcaption>
          <div>
            <h1><?= $page->headline()->or($page->title()) ?></h1>
            <?php if($page->intro()->isNotEmpty()): ?>
            <div class="text">
              <?= $page->intro()->kt() ?>
            </div>
            <?php endif ?>
          </div>
        </figcaption>
      </figure>
      <?php endif ?>
    </header>

    <div class="project-text text">
      <time class="project-year"><?= $page->year() ?></time>
      <?= $page->text()->kt() ?>

      <?php if ($page->tags()->isNotEmpty()): ?>
      <p class="project-tags"># <?= $page->tags() ?></p>
      <?php endif ?>
    </div>

    <ul class="project-gallery"<?= attr(['data-even' => $gallery->isEven(), 'data-count' => $gallery->count()], ' ') ?>>
      <?php foreach ($gallery as $image): ?>
      <li>
        <figure>
          <?= $image->crop(800, 1000) ?>
        </figure>
      </li>
      <?php endforeach ?>
    </ul>
  </article>
</main>

<?php snippet('footer') ?>