Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Static Websites with Sculpin

Building Static Websites with Sculpin

Avatar for Oliver Davies

Oliver Davies

August 28, 2024
Tweet

More Decks by Oliver Davies

Other Decks in Technology

Transcript

  1. What is a static website? .htaccess assets/images/od-logo.jpg build/tailwind.css call/index.html daily/2024/03/18/automated-drupal-11-compatibility-fixes/index.html

    drupal-upgrade/index.html favicon.ico index.html phpberks/index.html podcast/19-sam-mortenson/index.html pricing/index.html talks/taking-flight-with-tailwind-css/index.html talks/tdd-test-driven-drupal/index.html @opdavies
  2. What is Sculpin? • Static site generator • CLI tool

    • Built on Symfony components • Markdown + Twig = Static HTML @opdavies
  3. Why use a static site generator? • Rapid development. •

    Templating. • Security. • Performance. • Easy and cheap to host. @opdavies
  4. What do I use it for? • My personal website

    and Zettelkasten. • Some client websites. • HTML prototypes and testing. • Learning YAML and Twig (and some Symfony). @opdavies
  5. Using Sculpin • Configuration in app/config • Source files in

    source. • Templates in source/_templates or source/_layouts. • Includes in source/_includes or source/_partials. @opdavies
  6. output_dev/index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Hello!</title>

    5 </head> 6 <body> 7 <p>Hello, World!</p> 8 </body> 9 </html> @opdavies
  7. output_dev/index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Hello!</title>

    5 </head> 6 <body> 7 <p>Hello, World!</p> 8 </body> 9 </html> @opdavies
  8. output_dev/index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Hello!</title>

    5 </head> 6 <body> 7 <p>Hello, World!</p> 8 </body> 9 </html> @opdavies
  9. Configuration • Stored in app/config • sculpin_site.yml • sculpin_site_{env}.yml •

    Key-value pairs 1 --- 2 name: oliverdavies.uk 3 menu_links: 4 - { title: Home, href: / } 5 - { title: About, href: /about } @opdavies
  10. YAML front matter 1 --- 2 layout: post 3 title:

    New blog post 4 draft: yes 5 --- @opdavies
  11. YAML front matter 1 --- 2 layout: post 3 title:

    New blog post 4 draft: yes 5 --- @opdavies
  12. YAML front matter 1 --- 2 layout: post 3 title:

    New blog post 4 draft: yes 5 --- @opdavies
  13. More front matter 1 --- 2 layout: post 3 title:

    New blog post 4 draft: yes 5 tags: 6 - drupal 7 - php 8 - sculpin 9 --- @opdavies
  14. Even more front matter 1 --- 2 layout: post 3

    title: New blog post 4 draft: yes 5 tags: 6 - drupal 7 - php 8 - sculpin 9 tweets: yes 10 foo: bar 11 --- @opdavies
  15. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  16. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  17. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  18. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  19. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  20. Using on pages 1 --- 2 ... 3 testimonials: 4

    - { name: ..., role: ..., text: ..., url: ... } 5 - { name: ..., role: ..., text: ..., url: ... } 6 - { name: ..., role: ..., text: ..., url: ... } 7 --- 8 9 {% for testimonial in page.testimonials %} 10 <h2>{{ testimonial.name }} - {{ testimonial.role }}</h2> 11 <p>{{ testimonial.text }}</p> 12 {% endfor %} @opdavies
  21. Layouts 1 {# source/_layouts/base.html.twig #} 2 3 <!DOCTYPE html> 4

    <html lang="{{ site.locale|default('en') }}"> 5 <head> 6 <title>{{ site.name|default('Sculpin Skeleton') }}</title> 7 </head> 8 <body> 9 {% block body %}{% endblock %} 10 </body> 11 </html> @opdavies
  22. Layouts 1 {# source/_layouts/base.html.twig #} 2 3 <!DOCTYPE html> 4

    <html lang="{{ site.locale|default('en') }}"> 5 <head> 6 <title>{{ site.name|default('Sculpin Skeleton') }}</title> 7 </head> 8 <body> 9 {% block body %}{% endblock %} 10 </body> 11 </html> @opdavies
  23. Layouts 1 {# source/_layouts/base.html.twig #} 2 3 <!DOCTYPE html> 4

    <html lang="{{ site.locale|default('en') }}"> 5 <head> 6 <title>{{ site.name|default('Sculpin Skeleton') }}</title> 7 </head> 8 <body> 9 {% block body %}{% endblock %} 10 </body> 11 </html> @opdavies
  24. Layouts 1 {# source/_layouts/page.html.twig #} 2 3 {% extends 'base'

    %} 4 5 {% block body %} 6 {% block content %}{% endblock %} 7 {% endblock %} @opdavies
  25. Layouts 1 {# source/_layouts/page.html.twig #} 2 3 {% extends 'base'

    %} 4 5 {% block body %} 6 {% block content %}{% endblock %} 7 {% endblock %} @opdavies
  26. Layouts 1 {# source/_layouts/page.html.twig #} 2 3 {% extends 'base'

    %} 4 5 {% block body %} 6 {% block content %}{% endblock %} 7 {% endblock %} @opdavies
  27. Layouts 1 {# source/_layouts/page.html.twig #} 2 3 {% extends 'base'

    %} 4 5 {% block body %} 6 {% block content %}{% endblock %} 7 {% endblock %} @opdavies
  28. Includes {% include 'about-author' with { avatar: site.avatar, work: site.work,

    } only %} {% for link in links %} {% include 'menu-link' with { link } only %} {% endfor %} @opdavies
  29. Accessing custom content types 1 --- 2 title: My Daily

    Email Archive 3 layout: default 4 use: 5 - daily_email 6 --- 7 8 {% for email in data.daily_emails %} 9 <p>{{ email.title }}</p> 10 {% endfor %} @opdavies
  30. Accessing custom content types 1 --- 2 title: My Daily

    Email Archive 3 layout: default 4 use: 5 - daily_email 6 --- 7 8 {% for email in data.daily_emails %} 9 <p>{{ email.title }}</p> 10 {% endfor %} @opdavies
  31. Accessing custom content types 1 --- 2 title: My Daily

    Email Archive 3 layout: default 4 use: 5 - daily_email 6 --- 7 8 {% for email in data.daily_emails %} 9 <p>{{ email.title }}</p> 10 {% endfor %} @opdavies
  32. {{ 'today' }} {{ 'today'|date }} {{ 'today'|date('Y') }} {{

    'today'|date('Y') - 2007 }} # 17 (years of experience) @opdavies
  33. {{ 'today' }} {{ 'today'|date }} {{ 'today'|date('Y') }} {{

    'today'|date('Y') - 2007 }} # 17 (years of experience) @opdavies
  34. {{ 'today' }} {{ 'today'|date }} {{ 'today'|date('Y') }} {{

    'today'|date('Y') - 2007 }} # 17 (years of experience) @opdavies
  35. 1 {{ 'today' }} 2 3 {{ 'today'|date }} 4

    5 {{ 'today'|date('Y') }} 6 7 {{ 'today'|date('Y') - 2007 }} # 17 (years of experience) @opdavies
  36. 1 --- 2 title: Daily Email Archive 3 use: [daily_emails]

    4 --- 5 6 This is an archive of the {{ data.daily_emails|length }} 7 email messages I have sent to my daily email list 8 since the 12th of August, 2022. This is an archive of the 599 email messages I have sent to my daily email list since the 12th of August, 2022. @opdavies
  37. 1 --- 2 title: Building Static Websites with Sculpin 3

    events: 4 - name: PHP Berkshire 5 date: 2024-08-28 6 location: Reading, UK 7 url: https://www.meetup.com/php-berkshire/events/301850284 8 - name: BrumPHP 9 date: 2024-05-23 10 location: Birmingham, UK 11 url: https://www.eventbrite.com/e/brumphp-23rd-may-2024-tickets-803037766577 12 --- 13 @opdavies
  38. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  39. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  40. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  41. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  42. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  43. 1 {% set talkCount = 0 %} 2 3 {%

    for talk in data.talks %} 4 {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %} 5 {% set talkCount = talkCount + 1 %} 6 {% endfor %} 7 {% endfor %} 8 9 <p>I have given {{ talkCount }} talks.</p> 10 @opdavies
  44. 1 {% set talks = site.talks|filter(talk => talk.speaker == page.name)

    %} 2 3 {% if talks is not empty %} 4 <section> 5 <h2>Talks by {{ page.name }}</h2> 6 7 <div> 8 <ul> 9 {% for talk in talks %} 10 <li><a href="#0">{{ talk.title }}</a></li> 11 {% endfor %} 12 </ul> 13 </div> 14 </section> 15 {% endif %} @opdavies
  45. 1 {% set talks = site.talks|filter(talk => talk.speaker == page.name)

    %} 2 3 {% if talks is not empty %} 4 <section> 5 <h2>Talks by {{ page.name }}</h2> 6 7 <div> 8 <ul> 9 {% for talk in talks %} 10 <li><a href="#0">{{ talk.title }}</a></li> 11 {% endfor %} 12 </ul> 13 </div> 14 </section> 15 {% endif %} @opdavies
  46. 1 {% set talks = site.talks|filter(talk => talk.speaker == page.name)

    %} 2 3 {% if talks is not empty %} 4 <section> 5 <h2>Talks by {{ page.name }}</h2> 6 7 <div> 8 <ul> 9 {% for talk in talks %} 10 <li><a href="#0">{{ talk.title }}</a></li> 11 {% endfor %} 12 </ul> 13 </div> 14 </section> 15 {% endif %} @opdavies
  47. 1 {% set talks = site.talks|filter(talk => talk.speaker == page.name)

    %} 2 3 {% if talks is not empty %} 4 <section> 5 <h2>Talks by {{ page.name }}</h2> 6 7 <div> 8 <ul> 9 {% for talk in talks %} 10 <li><a href="#0">{{ talk.title }}</a></li> 11 {% endfor %} 12 </ul> 13 </div> 14 </section> 15 {% endif %} @opdavies
  48. 1 {% set talks = site.talks|filter(talk => talk.speaker == page.name)

    %} 2 3 {% if talks is not empty %} 4 <section> 5 <h2>Talks by {{ page.name }}</h2> 6 7 <div> 8 <ul> 9 {% for talk in talks %} 10 <li><a href="#0">{{ talk.title }}</a></li> 11 {% endfor %} 12 </ul> 13 </div> 14 </section> 15 {% endif %} @opdavies
  49. // app/SculpinKernel.php use Opdavies\Sculpin\Bundle\TwigMarkdownBundle\SculpinTwigMarkdownBundle; use Sculpin\Bundle\SculpinBundle\HttpKernel\AbstractKernel; final class SculpinKernel extends

    AbstractKernel { protected function getAdditionalSculpinBundles(): array { return [ SculpinTwigMarkdownBundle::class, ]; } } @opdavies