Slide 1

Slide 1 text

STATIC SITE GENERATION FOR THE MASSES Denis Defreyne FOSDEM 2013 1

Slide 2

Slide 2 text

Me 2

Slide 3

Slide 3 text

Me 2 ‣ Denis Defreyne

Slide 4

Slide 4 text

Me 2 ‣ Denis Defreyne twitter.com/ddfreyne

Slide 5

Slide 5 text

Me 2 ‣ Denis Defreyne twitter.com/ddfreyne github.com/ddfreyne

Slide 6

Slide 6 text

Me 2 ‣ Denis Defreyne twitter.com/ddfreyne github.com/ddfreyne ‣ Software Engineer

Slide 7

Slide 7 text

Me 2 ‣ Denis Defreyne twitter.com/ddfreyne github.com/ddfreyne ‣ Software Engineer ‣ Author of nanoc

Slide 8

Slide 8 text

What exactly does a STATIC SITE GENERATOR do? 3

Slide 9

Slide 9 text

4

Slide 10

Slide 10 text

4 Mark- down

Slide 11

Slide 11 text

Markdown 5 In  *exactly*  one  month,  there’s  FOSDEM   again!  I  can  barely  control  my  excitement! *  First  element  of  a  list *  Second  element

Slide 12

Slide 12 text

6 Mark- down

Slide 13

Slide 13 text

6 Mark- down HTML fragment

Slide 14

Slide 14 text

HTML from Markdown 7

In  exactly  one  month,  there’s   FOSDEM  again!  I  can  barely  control  my   excitement!

  • First  element  of  a  list
  • Second  element

Slide 15

Slide 15 text

8 Mark- down HTML fragment

Slide 16

Slide 16 text

8 Mark- down HTML fragment Layout

Slide 17

Slide 17 text

Layout 9 <%=  item[:title]  %> <%=  yield  %>

Slide 18

Slide 18 text

10 Mark- down HTML fragment Layout

Slide 19

Slide 19 text

10 Mark- down HTML fragment Layout + HTML

Slide 20

Slide 20 text

11 One  Month  until  FOSDEM!

In  exactly  one  month,  there’s  FOSDEM   again!  I  can  barely  control  my  excitement!

  • First  element  of  a  list
  • Second  element

Slide 21

Slide 21 text

12 Mark- down HTML fragment Layout + HTML

Slide 22

Slide 22 text

13

Slide 23

Slide 23 text

VPS + 96 MB RAM + Ruby = TOO SLOW! 13

Slide 24

Slide 24 text

14 nanoc φϊοΫ

Slide 25

Slide 25 text

15

Slide 26

Slide 26 text

16 CMS Content Management System

Slide 27

Slide 27 text

16 CMS Content Management System

Slide 28

Slide 28 text

17 SSG Static Site Generator

Slide 29

Slide 29 text

Road map 18

Slide 30

Slide 30 text

Road map 1. What are SSGs? 18

Slide 31

Slide 31 text

Road map 1. What are SSGs? 2. What are SSGs capable of? 18

Slide 32

Slide 32 text

Road map 1. What are SSGs? 2. What are SSGs capable of? 3. Lessons Learnt & Future Work 18

Slide 33

Slide 33 text

19 What are SSGs?

Slide 34

Slide 34 text

Tiny example – pages 20 content/ about.md blog/ 2013-­‐01-­‐02-­‐one-­‐month-­‐until-­‐fosdem.md 2013-­‐02-­‐03-­‐fosdem-­‐was-­‐awesome.md

Slide 35

Slide 35 text

Tiny example – pages 21 -­‐-­‐-­‐ title:  One  Month  until  FOSDEM! -­‐-­‐-­‐ In  exactly  one  month,  there’s  FOSDEM  again!   I  can  barely  control  my  excitement!

Slide 36

Slide 36 text

Tiny example – layouts 22 <%=  item[:title]  %> <%=  yield  %>

Slide 37

Slide 37 text

Tiny example – result 23 One  Month  until  FOSDEM! In  exactly  one  month,  there’s  FOSDEM  again!  I   can  barely  control  my  excitement!

Slide 38

Slide 38 text

Tiny example – result 24 output/ about/index.html blog/2013/01/one-­‐month-­‐until-­‐fosdem/index.html blog/2012/02/fosdem-­‐was-­‐awesome/index.html

Slide 39

Slide 39 text

25

Slide 40

Slide 40 text

26

Slide 41

Slide 41 text

27

Slide 42

Slide 42 text

28

Slide 43

Slide 43 text

29

Slide 44

Slide 44 text

30

Slide 45

Slide 45 text

31

Slide 46

Slide 46 text

32

Slide 47

Slide 47 text

33

Slide 48

Slide 48 text

Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale - FMPP - Frank - fugitive - Graze - Hakyll - Hammer - Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma - Machined - Magneto - Markbox - Markdoc - Middleman - mynt - nanoc - Nikola - Octopress - Pagegen - Pelican - Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus - Rote - RubyFrontier - Ruroh - Second Crack - Socrates - Speechhub - Stasis - staticjinja - StaticMatic - StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site Maker - Webby - webgen - Website Meta Language - Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb 33

Slide 49

Slide 49 text

Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale - FMPP - Frank - fugitive - Graze - Hakyll - Hammer - Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma - Machined - Magneto - Markbox - Markdoc - Middleman - mynt - nanoc - Nikola - Octopress - Pagegen - Pelican - Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus - Rote - RubyFrontier - Ruroh - Second Crack - Socrates - Speechhub - Stasis - staticjinja - StaticMatic - StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site Maker - Webby - webgen - Website Meta Language - Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb 33

Slide 50

Slide 50 text

Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale - FMPP - Frank - fugitive - Graze - Hakyll - Hammer - Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma - Machined - Magneto - Markbox - Markdoc - Middleman - mynt - nanoc - Nikola - Octopress - Pagegen - Pelican - Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus - Rote - RubyFrontier - Ruroh - Second Crack - Socrates - Speechhub - Stasis - staticjinja - StaticMatic - StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site Maker - Webby - webgen - Website Meta Language - Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb 33 INCOMPLETE

Slide 51

Slide 51 text

34

Slide 52

Slide 52 text

35

Slide 53

Slide 53 text

36

Slide 54

Slide 54 text

37 Why static sites?

Slide 55

Slide 55 text

37 1. Fast Why static sites?

Slide 56

Slide 56 text

37 1. Fast 2. Secure Why static sites?

Slide 57

Slide 57 text

37 1. Fast 2. Secure 3. Works with your own tools (vim!) Why static sites?

Slide 58

Slide 58 text

37 1. Fast 2. Secure 3. Works with your own tools (vim!) 4. Content is in plain text Why static sites?

Slide 59

Slide 59 text

37 1. Fast 2. Secure 3. Works with your own tools (vim!) 4. Content is in plain text 5. Easy to deploy Why static sites?

Slide 60

Slide 60 text

37 1. Fast 2. Secure 3. Works with your own tools (vim!) 4. Content is in plain text 5. Easy to deploy 6. Easy to preview Why static sites?

Slide 61

Slide 61 text

37 1. Fast 2. Secure 3. Works with your own tools (vim!) 4. Content is in plain text 5. Easy to deploy 6. Easy to preview 7. Makes collaboration easy Why static sites?

Slide 62

Slide 62 text

38

Slide 63

Slide 63 text

39 What are SSGs capable of?

Slide 64

Slide 64 text

Arbitrary metadata 40

Slide 65

Slide 65 text

Arbitrary metadata 41 title:      Braid kind:        review subtype:  game year:        2008 rating:    5

Slide 66

Slide 66 text

Arbitrary metadata 42
    <%  @item.children  do  |review|  %>
  • <%=  '˒'  *  review[:rating]  %> <%=  review[:title]  %>
  • <%  end  %>

Slide 67

Slide 67 text

Arbitrary metadata 43
  • ˒˒˒˒ˑ  Borderlands
  • ˒˒˒˒˒  Braid
  • ˒˒˒˒ˑ  Legend  of  Grimrock
  • ˒˒˒˒˒  Max  Payne
  • ˒˒˒˒ˑ  Minecraft

Slide 68

Slide 68 text

Filters 44

Slide 69

Slide 69 text

Filters – Markdown A  First  Level  Header ==================== A  Second  Level  Header -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Now  is  the  time  for  all  good  men  to  come  to  the  aid  of  their   country.  This  is  just  a  regular  paragraph. *  Quick  brown  fox *  Lazy  dog 45

Slide 70

Slide 70 text

Filters – Textile h1.  Give  RedCloth  a  try! A  *simple*  paragraph  with a  line  break,  some  _emphasis_  and  a  "link":http://redcloth.org *  an  item *  and  another #  one #  two 46

Slide 71

Slide 71 text

Filters – ERB <%=  item[:title]  %> <%=  yield  %> 47

Slide 72

Slide 72 text

Filters – Mustache {{  title  }} {{  yield  }} 48

Slide 73

Slide 73 text

Filters – Haml !!! %html %head %title=  @item[:title] %body =  yield 49

Slide 74

Slide 74 text

Filters – Colorize Syntax

def  my_function
    (1..10).map  do  |i|
        "#{i}  is  #{i  %  2  ==  1  ?  'odd'  :  'even'}"
    end
end
50

Slide 75

Slide 75 text

Filters – Colorize Syntax def  my_function    (1..10).map  do  |i|        "#{i}  is  #{i  %  2  ==  1  ?  'odd'  :  'even'}"    end end 51

Slide 76

Slide 76 text

Filters – Typogruby 52 "Typogruby makes HTML look smarter & better, don't you think?" “Typogruby makes HTML look smarter & better, don’t you think?”

Slide 77

Slide 77 text

Filters – Custom class  CensorFilter  <  Nanoc::Filter identifier  :censor def  run(content,  params={}) content.gsub('nanoc  sucks',  'nanoc  rocks') end end 53

Slide 78

Slide 78 text

Rules 54

Slide 79

Slide 79 text

Rules 55 compile  '*'  do if  @item[:kind]  ==  'article' filter  :bluecloth end layout  'default' end

Slide 80

Slide 80 text

Rules 56 compile  '/images/*/'  do    filter  :img_optimize end

Slide 81

Slide 81 text

Rules 57 compile  '/images/*/'  do    filter  :img_optimize end compile  '/images/*/',  :rep  =>  :thumbnail  do    filter  :scale,  :width  =>  140 end

Slide 82

Slide 82 text

Rules 58 compile  '/blog/*/',  :rep  =>  :mp3  do    filter  :say    filter  :lame end

Slide 83

Slide 83 text

Rules versus Makefiles 59

Slide 84

Slide 84 text

Rules versus Makefiles 59 ‣ Push vs. pull

Slide 85

Slide 85 text

Rules versus Makefiles 59 ‣ Push vs. pull ‣ Cleaner syntax

Slide 86

Slide 86 text

Rules versus Makefiles 59 ‣ Push vs. pull ‣ Cleaner syntax ‣ Automatic dependency tracking

Slide 87

Slide 87 text

Helpers 60

Slide 88

Slide 88 text

61 module  Nanoc::Helpers::Tagging #  Find  all  items  with  the  given  tag. # #  @param  [String]  tag  The  tag  for  which  to  find  all  items # #  @return  [Array]  All  items  with  the  given  tag def  items_with_tag(tag) @items.select  do  |i| (i[:tags]  ||  []).include?(tag) end end end

Slide 89

Slide 89 text

Helpers – example 62

Tags  for  <%=  @item[:tag]  %>

    <%  items_with_tag(@item[:tag]).each  do  |i|  %>
  • <%=  link_to(@item[:tag],  i)  %>
  • <%  end  %>

Slide 90

Slide 90 text

Workflow 63

Slide 91

Slide 91 text

Workflow 63 1. Development

Slide 92

Slide 92 text

Workflow 63 1. Development 1. Version controlled

Slide 93

Slide 93 text

Workflow 63 1. Development 1. Version controlled 2. Branched development

Slide 94

Slide 94 text

Workflow 63 1. Development 1. Version controlled 2. Branched development 3. Pull requests

Slide 95

Slide 95 text

Workflow 63 1. Development 1. Version controlled 2. Branched development 3. Pull requests 2. Release

Slide 96

Slide 96 text

Workflow 63 1. Development 1. Version controlled 2. Branched development 3. Pull requests 2. Release 1. Preview

Slide 97

Slide 97 text

Workflow 63 1. Development 1. Version controlled 2. Branched development 3. Pull requests 2. Release 1. Preview 2. Check

Slide 98

Slide 98 text

Workflow 63 1. Development 1. Version controlled 2. Branched development 3. Pull requests 2. Release 1. Preview 2. Check 3. Deploy

Slide 99

Slide 99 text

64 Data Sources

Slide 100

Slide 100 text

65 Data Sources – nanoc

Slide 101

Slide 101 text

66 nanoc site CLI YARD FS {

Slide 102

Slide 102 text

67 nanoc CLI – definition name                'dostuff' usage              'dostuff  [options]' aliases          :ds,  :stuff summary          'does  stuff' description  'This  command  does  a  lot!' GITHUB.COM/DDFREYNE/CRI

Slide 103

Slide 103 text

68 nanoc CLI – generated help NAME        dostuff  -­‐  does  stuff USAGE        dostuff  [options] DESCRIPTION        This  command  does  a  lot  of  stuff.  I  really  mean  a  lot. OPTIONS        -­‐h  -­‐-­‐help            show  help  for  this  command        -­‐m  -­‐-­‐more            do  even  more  stuff        -­‐s  -­‐-­‐stuff          specify  stuff  to  do GITHUB.COM/DDFREYNE/CRI

Slide 104

Slide 104 text

69

Slide 105

Slide 105 text

nanoc filter class  CensorFilter  <  Nanoc::Filter identifier  :censor #  Some  documentation  goes  here… def  run(content,  params={}) content.gsub('nanoc  sucks',  'nanoc  rocks') end end 70

Slide 106

Slide 106 text

71

Slide 107

Slide 107 text

71

Slide 108

Slide 108 text

72

Slide 109

Slide 109 text

72

Slide 110

Slide 110 text

73

Slide 111

Slide 111 text

74 Data Sources – FOSDEM

Slide 112

Slide 112 text

{ 75 FOSDEM site PentaBarf FS

Slide 113

Slide 113 text

76

Slide 114

Slide 114 text

77

Slide 115

Slide 115 text

78 github.com/fosdem/website

Slide 116

Slide 116 text

78 github.com/fosdem/website

Slide 117

Slide 117 text

SSGs advantages 79

Slide 118

Slide 118 text

SSGs advantages ‣ More than Markdown + layout → HTML! 79

Slide 119

Slide 119 text

SSGs advantages ‣ More than Markdown + layout → HTML! ‣ Satisfactory in many cases 79

Slide 120

Slide 120 text

SSGs advantages ‣ More than Markdown + layout → HTML! ‣ Satisfactory in many cases ‣ Dynamic with JavaScript 79

Slide 121

Slide 121 text

SSGs advantages ‣ More than Markdown + layout → HTML! ‣ Satisfactory in many cases ‣ Dynamic with JavaScript ‣ Usable for publishing your data 79

Slide 122

Slide 122 text

80 Lessons Learnt

Slide 123

Slide 123 text

Internal DSLs 81

Slide 124

Slide 124 text

Internal DSLs compile  '/about/'  do filter  :kramdown end 82

Slide 125

Slide 125 text

Internal DSLs – side effects compile  '/about/'  do filter  :kramdown File.open('output/stuff.txt',  'w')  do  |f| f.write(item.raw_content) end end 83

Slide 126

Slide 126 text

Internal DSLs – mutability compile  '/articles/*/'  do    unless  @item[:layout] @item[:layout]  =  'article' end    layout  @item[:layout] end 84

Slide 127

Slide 127 text

Speed 85

Slide 128

Slide 128 text

Incremental compilation 86

Slide 129

Slide 129 text

Incremental compilation 86 ‣ Recompile only what’s necessary

Slide 130

Slide 130 text

Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω (#items) → Ω(#changed-items)

Slide 131

Slide 131 text

Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω (#items) → Ω(#changed-items) ‣ Scenarios

Slide 132

Slide 132 text

Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω (#items) → Ω(#changed-items) ‣ Scenarios Single changed page

Slide 133

Slide 133 text

Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω (#items) → Ω(#changed-items) ‣ Scenarios Single changed page Changed page that is included elsewhere

Slide 134

Slide 134 text

Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω (#items) → Ω(#changed-items) ‣ Scenarios Single changed page Changed page that is included elsewhere Changed rules

Slide 135

Slide 135 text

Pick the right libraries 87

Slide 136

Slide 136 text

Pick the right libraries ‣ RubyPants, Typogruby 87

Slide 137

Slide 137 text

Pick the right libraries ‣ RubyPants, Typogruby Winner: Fast Aleck 87

Slide 138

Slide 138 text

Pick the right libraries ‣ RubyPants, Typogruby Winner: Fast Aleck ‣ pygmentize, pygments.rb 87

Slide 139

Slide 139 text

Pick the right libraries ‣ RubyPants, Typogruby Winner: Fast Aleck ‣ pygmentize, pygments.rb Winner: pygments.rb 87

Slide 140

Slide 140 text

88

Slide 141

Slide 141 text

89

Slide 142

Slide 142 text

90 Future Work

Slide 143

Slide 143 text

Future Work 91

Slide 144

Slide 144 text

Future Work 91 ‣ Improving speed (Parallellisation)

Slide 145

Slide 145 text

Future Work 91 ‣ Improving speed (Parallellisation) ‣ Supporting huge sites

Slide 146

Slide 146 text

Future Work 91 ‣ Improving speed (Parallellisation) ‣ Supporting huge sites ‣ Writing great documentation

Slide 147

Slide 147 text

Future Work 91 ‣ Improving speed (Parallellisation) ‣ Supporting huge sites ‣ Writing great documentation ‣ Building an active contributors’ community

Slide 148

Slide 148 text

Future Work 91 ‣ Improving speed (Parallellisation) ‣ Supporting huge sites ‣ Writing great documentation ‣ Building an active contributors’ community ‣ GUI?

Slide 149

Slide 149 text

92 Recap

Slide 150

Slide 150 text

SSGs… 93

Slide 151

Slide 151 text

SSGs… 93 ‣ have big obvious advantages

Slide 152

Slide 152 text

SSGs… 93 ‣ have big obvious advantages fast, secure, easy to deploy, …

Slide 153

Slide 153 text

SSGs… 93 ‣ have big obvious advantages fast, secure, easy to deploy, … ‣ have big non-obvious advantages

Slide 154

Slide 154 text

SSGs… 93 ‣ have big obvious advantages fast, secure, easy to deploy, … ‣ have big non-obvious advantages metadata, data sources, checks, …

Slide 155

Slide 155 text

SSGs… 93 ‣ have big obvious advantages fast, secure, easy to deploy, … ‣ have big non-obvious advantages metadata, data sources, checks, … ‣ turn your web site into an open-source project!

Slide 156

Slide 156 text

SSGs… 93 ‣ have big obvious advantages fast, secure, easy to deploy, … ‣ have big non-obvious advantages metadata, data sources, checks, … ‣ turn your web site into an open-source project! share, learn, collaborate

Slide 157

Slide 157 text

94

Slide 158

Slide 158 text

94 MAIL denis.defreyne@stoneship.org TWITTER @ddfreyne GITHUB github.com/ddfreyne WWW nanoc.ws GITHUB github.com/nanoc IRC freenode #nanoc

Slide 159

Slide 159 text

95 Extra Slides!

Slide 160

Slide 160 text

Preprocessing 96 preprocess  do ts  =  Set.new(@items.map  {  |i|  i[:tags]  }.flatten) ts.each  do  |tag| @items  <<  Nanoc::Item.new( "",  {  :tag  =>  tag  },  "/tags/#{tag}/") end end