Creating Content
Your Content
When building your project, Tapestry buckets files into collections based upon them matching filters for configured content types; by default Tapestry comes with just two content types: blog
and default
.
Essentially if a file doesn't match any configured content type filters then it gets placed into the default
collection – there is no limit on how many content types you add to Tapestry, click here for more information on how they work and examples on how to configure them.
Supported file extensions
Out of the box Tapestry comes with content renderers that support the following file extensions:
.md
/.markdown
.htm
/.html
.phtml
Any file not matching the above extensions will be copied with the same relative path to the build directory.
Writing posts
Posts are looked for as files within the source/_blog
folder of your project. Tapestry expects the _blog
folder to have a flat structure containing markdown files with a filename format of: YYYY-MM-DD-post-title.md
– Tapestry does however support omitting the date in preference of including it within the files front matter.
A typical post
The standard blog style post file contains optional front matter and the posts content. If your filename is formatted with the date of publish then including date and title within the files front matter is optional; however it will take precedent if set.
---
title: "My first post"
date: 2017-03-30
categories:
- first post
- update
tags:
- example
---
# My first post
Paste this within a `.md` file inside your projects `_posts` directory and build your project to see how it gets generated.
Post Layouts
The default blog content type is configured to look for a blog.phtml
file inside the _views
directory of your project. Tapestry will compile the markdown content into HTML and then inject it and the post meta data into the blog.phtml
.
You can use built in content helpers to display post content and meta data, e.g:
<?php
// $title is equal to the posts title; this will need passing on to the parent template
// if you want it to be used for the <title> tag.
$this->layout('_templates/default', ['title' => $title]);
?>
<article>
<header>
<h1><?= $title ?></h1>
<small>Published on <?= $date->format('F jS Y') ?></small>
</header>
<?= $this->getContent() ?>
</article>
Displaying an index of posts
Collections are accessed by templates through the use
front matter property for example:
---
use:
- blog
- blog_categories
---
The above will prompt Tapestry to inject the template with $blog_items
and $blog_categories_items
. Note the _items postfix; any content type, or its taxonomy can be requested in this manor, for more details on this mechanism see here.
Both variables will be arrays and therefore provide you with the ability to slice, filter and order however you would like, either within the template itself or within a custom view helper function that you have created.
For example to get the first six posts and pass them to a partial template you can do the following:
<?php
/**
* @var \Tapestry\Entities\ViewFile[] $blog_items
* @var \Tapestry\Entities\ViewFile $item
*/
foreach(array_slice($blog_items, 0, 6) as $item) {
echo $this->fetch('_views/article_tile', ['item' => $item]);
}
Within the _views/article_tile
template you can use all the same helpers and variables as you could with the blog.phtml
template to access the posts information, except on $item
rather than $this
– this is because the $this
variable will reference the article_tile
file while the $item
variable will be the actual blog post in question.
Creating pages
Pages are content files that end up getting placed into the default
collection; they can be placed anywhere within your source folder so long as the path is not within you configured ignore list.
Tapestry supports pages with any of the supported file extensions; if a file isn't supported by a configured renderer then Tapestry will copy it instead.
Flattening pages from subfolders into the root directory
If you have your projects pages organised into sub-folders but would like to flatted them into the root folder on build, you need to set the permalink property within the files front matter:
---
title: A super awesome page
permalink: super.html
---
This will prompt Tapestry to output the rendered file content to super.html
within the root of the build destination folder.
Additional Content
In addition to assets, pages, posts and other content types that you may choose to configure; you will likely have additional content files that require generating such as your robots.txt and atom.xml files. Normally due to their extension Tapestry treats these as assets and marks them for copying.
However there is a way to have Tapestry generate these files and that is to have them in your source as .phtml
and set their permalink to the final file extension. For example the below produces an atom.xml
file containing the most recent 10 items from the posts collection:
---
use:
- blog
permalink: atom.xml
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="https://www.w3.org/2005/Atom">
<title><![CDATA[<?= $this->site('title') ?>]]></title>
<link href="<?= $this->url('/atom.xml') ?>" rel="self"/>
<link href="<?= $this->url('/') ?>"/>
<updated><?= date('c') ?></updated>
<id><?= $this->url('/') ?></id>
<?php if ($this->site('author', false) || $this->site('email', false)) { ?>
<author>
<?php if ($author = $this->site('author', null)){ ?>
<name><![CDATA[<?= $author ?>]]></name>
<?php } ?>
<?php if ($email = $this->site('email', null)){ ?>
<email><![CDATA[<?= $email ?>]]></email>
<?php } ?>
</author>
<?php } ?>
<generator uri="<?= $this->url('/') ?>"><?= $this->site('title') ?></generator>
<?php
/** @var \Tapestry\Entities\ViewFile $item */
foreach(array_slice($blog_items,0, 10) as $item ){ ?>
<entry>
<title type="html"><![CDATA[<?= $item->getData('title') ?>]]></title>
<link href="<?= $item->getUrl() ?>"/>
<updated><?= $item->getDate()->format('c') ?></updated>
<id><?= $item->getUrl() ?></id>
<content type="html"><![CDATA[<?= $item->getContent() ?>]]></content>
</entry>
<?php } ?>
</feed>
Working with drafts
Drafts are files with draft: true
set within their front matter. Tapestry will not publish files marked as draft unless the environment configuration for publishing drafts is set to true
.