(I make websites.)
<article class="pattern">
<figure style="background-image:url({{img}})">
<button @click="setBackground({{pattern}})">Try It</button>
</figure>
<figcaption>
<h2 class="name">{{name}}</h2>
<cite>
by <a href="{{author.url}}">{{author.name}}</a>
</cite>
<div class="description">
{{description}}
</div>
<div class="added">
Added on
<time datetime="{{date}}">{{date.format}}</time>
</div>
<div class="tags">
<a href="{{tag.url}}">{{tag.name}}</a>
</div>
</figcaption>
</article>
And now we need a way to put the content
or "stuff"
...into the HTML markup
or "nerd shit"
And there's a bunch of ways to do that.
Let's start with
Wordpress is very popular.
Let's do the usual approach...
Wordpress' popularity is also its greatest vulnerability
Source: Sucuri
In short:
Let's move on.
Source: drupal.org
html.html.twig
↳
page.html.twig
↳
region.html.twig
↳
block.html.twig
↳
paragraph.html.twig
↳
field.html.twig
html.html.twig
page.html.twig
region.html.twig
block--topnav.html.twig
block--single-pattern.html.twig
.field--pattern.html.twig
.field--name.html.twig
.field--author.html.twig
.field--date_added.html.twig
.field--tags.html.twig
block.html.twig
paragraph.html.twig
field.html.twig
block--footer.html.twig
.block-single-pattern.html.twig
<article class="pattern">
{{content.pattern}}
<figcaption>
{{content.name}}
{{content.author}}
{{content.author}}
{{content.date_added}}
{{content.tags}}
</figcaption>
</article>
.field--pattern.html.twig
{% for item in items %}
<figure class="pattern" background-image:url({{item.content['#image'].url}})="">
<button @click="setBackground({{item.content.title}})">Try It</button>
</figure>
{% endfor %}
A flat file CMS does not communicate with a database.
All user controlled content is stored in small files (.txt
or .yml
or .md
) inside the site's content folder.
Grav is probably the most popular flat file CMS.
But...
Now it's time to write some code!
Blueprint YAML file
fields:
pat:
label: Pattern File
type: file
destination: 'assets/img/patterns'
author_name:
label: Author Name
type: text
author_url:
label: Author URL
type: url
post_date:
label: Post Date
type: datetime
tags:
label: Pattern Tags
type: selectize
seamless:
label: Seamless?
type: toggle
options:
yes: Yes, this is seamless
no: No, this isn't
description:
label: Description
type: editor
Content Markdown file
---
title: Gold Chains On Velvet
pat:
/assets/img/patterns/GoldChainsOnVelvet.gif:
name: GoldChainsOnVelvet.gif
type: image/gif
size: 31264
path: user/themes/my-theme/assets/GoldChainsOnVelvet.gif
author_name: Ellen Schofield
author_url: https://ellenschofield.com
post_date: '04-07-2019 16:46'
tags:
- blue
- chains
- velvet
seamless: yes
description:
'Fusce vulputate arcu quis risus malesuada, vel gravida augue eleifend. Mauris feugiat sed ex ac laoreet. Nunc et odio urna. Curabitur elementum mattis mi, vel tincidunt est rhoncus et.'
---
Template Twig File
<article class="pattern">
<figure style="background-image:url({{pattern.pat}})">
<button @click="setBackground({{pattern.title}})">Try It</button>
</figure>
<figcaption>
<h2 class="name">{{pattern.title}}</h2>
{% if pattern.author_name && pattern.author_url %}
<cite>
by <a href="{{pattern.author_url}}">{{pattern.author_name}}</a>
</cite>
{% elseif pattern.author_name %}
<cite>
by {{pattern.author_name}}
</cite>
{% endif %}
<div class="description">
{{description|raw}}
</div>
{% if pattern.post_date %}
<div class="added">
Added on
<time datetime="{{pattern.postdate}}">{{pattern.postdate|date("F jS, Y g:ia")}}</time>
</div>
{% endif %}
{% if pattern.tags %}
<div class="tags">
{% for tag in pattern.tags %}
<a href="{{site.url}}/tag/{{tag}}">{{tag}}</a>
{% endif %}
</div>
{% endif %}
</figcaption>
</article>
This approach is very similar in
One of my all-time favorite CMS
But either way, we've written some Yaml, and we've written some twig.
Don't like PHP? Well, okay, let's try something else.
npm install ghost-cli@latest -g
ghost install local
ghost start
Public | http://localhost:2368 |
Admin | http://localhost:2368/ghost |
Ghost is a blogging platform.
A quick moment on pricing...
Price | Views | Users | |
---|---|---|---|
Basic | $29 | 100k | 2 |
Standard | $79 | 500k | 5 |
Business | $199 | 1M | 15 |
Source: Ghost Pricing |
Memory | VCPUs | SSD Disk | Transfer | Price /m |
---|---|---|---|---|
1 GB | 1 vCPU | 25 GB | 1 TB | $5 + .007/h ($5 - $11.11) |
2 GB | 1 vCPU | 50 GB | 2 TB | $10 + .015/h ($10 - $119.50) |
2 GB | 2 vCPU | 60 GB | 3 TB | $15 + .022/h ($15 - $175.60) |
8 GB | 4 vCPU | 160 GB | 5 TB | $40 + .06/h ($40 - $478) |
Source: Digital Ocean Pricing |
What if this all seems too complicated?
gem install jekyll bundler
jekyll new local
bundle exec jekyll serve
/_posts/2019-07-04-astroturf-argyle.md
---
layout: pattern
pat: "/images/AstroturfArgyle.gif"
title: "Astroturf Argyle"
date: 2019-07-04 20:19:22 -0500
author_name: Ellen Schofield
author_url: https://ellenschofield.com
seamless: true
tags: [grass,diamond,green,nature]
---
Have you ever wanted to have a website that's also a golf course that's also an art deco bathroom? Now you can live your dream.
/_layouts/home.html
{% for pattern in site.posts %}
<article class="pattern">
<figure style="background-image:url({{pattern.pat}})">
<button @click="setBackground({{pattern.pat}})">Try It</button>
</figure>
<figcaption>
<h2 class="name">{{pattern.title}}</h2>
<cite>
by <a href="{{pattern.author_url}}">{{pattern.author_name}}</a>
</cite>
<div class="description">
{{pattern.content}}
</div>
{% if pattern.date %}
<div class="added">
Added on
<time datetime="{{pattern.post}}">{{pattern.date | date: "%b %d, %y"}}</time>
</div>
{% endif %}
{% if pattern.tags %}
<div class="tags">
{% for tag in pattern.tags %}
<a href="{{site.url}}/tag/{{tag}}">{{tag}}</a>
{% endfor %}
</div>
{% endif %}
</figcaption>
</article>
{% endfor %}
Jekyll is fast.
But not for people who are afraid of code.
Okay, last one...
javascript
fetch('{site}/api/collections/get/Pattern?token={token}')
.then(res => res.json())
.then(res => console.log(res));
json result
{
"entries":[
{
"title":"Vaporwave Terrazzo",
"date":"2019-07-04",
"image_file":{
"path":"\/cockpit\/storage\/uploads\/2019\/07\/05\/5d1eb9fba959eVaporwaveTerrazzo.gif"
},
"author_name":"Ellen Schofield",
"author_url":"http:\/\/ellenschofield.com",
"seamless":true,
"tags":[
"bowling",
"blue",
"animated",
"terrazzo"
],
"_mby":"5d1a7d756463319516000206",
"_by":"5d1a7d756463319516000206",
"_modified":1562294867,
"_created":1562294835,
"_id":"5d1eba336463318159000090"
},
{
"title":"Astroturf Argyle",
"date":"2019-07-04",
"image_file":{
"path":"\/cockpit\/storage\/uploads\/2019\/07\/05\/5d1ebda03bd3bAstroturfArgyle.gif"
},
"author_name":"Ellen Schofield",
"author_url":"https:\/\/ellenshofield.com",
"seamless":true,
"tags":[
"grass",
"diamond",
"nature"
],
"_mby":"5d1a7d756463319516000206",
"_by":"5d1a7d756463319516000206",
"_modified":1562295778,
"_created":1562295754,
"_id":"5d1ebdca64633154cc0002ba"
},
{
"title":"Gold Chains On Velvet",
"date":"2019-07-04",
"image_file":{
"path":"\/cockpit\/storage\/uploads\/2019\/07\/05\/5d1ebdf5a527fGoldChainsOnVelvet.gif"
},
"author_name":"Ellen Schofield",
"author_url":"https:\/\/ellenschofield.com",
"seamless":true,
"tags":[
"gold",
"chains",
"blue",
"velvet"
],
"_mby":"5d1a7d756463319516000206",
"_by":"5d1a7d756463319516000206",
"_modified":1562295854,
"_created":1562295834,
"_id":"5d1ebe1a6463315b5900006f"
}
],
"total":3
}
Okay, here's some Vue...
<article class="pattern" v-for="pattern in patterns" :class="{ active: activeTitle == pattern.title}">
<figure :style="'background-image:url('+pattern.image_file.path+')'">
<button @click="setBackground(pattern.title)">Try It</button>
</figure>
<figcaption>
<h2 class="name">{{pattern-title}}</h2>
<cite v-if="pattern.author_url && pattern.author_name">
by <a :href="pattern.author_url">{{pattern.author_name}}</a>
</cite>
<cite v-else-if="pattern.author_name">
by {{pattern.author_name}}
</cite>
<div class="description" v-html="pattern.description">
</div>
<div class="added">
Added on
<time v-attr="{datetime: date}">{{parseDate(date.format)}}</time>
</div>
<div class="tags">
<a v-for="tag in pattern.tags" @click="filterTo(tag)">{{tag}}</a>
</div>
</figcaption>
</article>
We've just made a Single Page Application!
see also:
You have to decide that.
Play with new tech you haven't tried before.