diff --git a/README.md b/README.md new file mode 100644 index 00000000..62624c2f --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# eleventy-base-blog + +A starter repository showing how to build a blog with the [Eleventy](https://github.com/11ty/eleventy) static site generator. + +[![Build Status](https://travis-ci.org/11ty/eleventy-base-blog.svg?branch=master)](https://travis-ci.org/11ty/eleventy-base-blog) + +## Demos + +* [Netlify](https://eleventy-base-blog.netlify.com/) +* [Get your own Eleventy web site on Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)—seriously, just click OK a few times and it’s live—Netlify is amazing. +* [GitHub Pages](https://11ty.github.io/eleventy-base-blog/) + +## Getting Started + +### 1. Clone this repository: + +``` +git clone https://github.com/11ty/eleventy-base-blog.git my-blog-name +``` + + +### 2. Navigate to the directory + +``` +cd my-blog-name +``` + +Specifically have a look at `.eleventy.js` to see if you want to configure any Eleventy options differently. + +### 3. Install dependencies + +``` +npm install +``` + +### 4. Edit _data/metadata.json + +### 5. Run Eleventy + +``` +npx eleventy +``` + +Or build automatically when a template changes: +``` +npx eleventy --watch +``` + +Or in debug mode: +``` +DEBUG=* npx eleventy +``` + +### Implementation Notes + +* `about/index.md` shows how to add a content page. +* `posts/` has the blog posts but really they can live in any directory. They need only the `post` tag to be added to this collection. +* Add the `nav` tag to add a template to the top level site navigation. For example, this is in use on `index.njk` and `about/index.md`. +* Content can be any template format (blog posts needn’t be markdown, for example). Configure your supported templates in `.eleventy.js` -> `templateFormats`. + * Because `css` and `png` are listed in `templateFormats` but are not supported template types, any files with these extensions will be copied without modification to the output (while keeping the same directory structure). +* The blog post feed template is in `feed/feed.njk`. This is also a good example of using a global data files in that it uses `_data/metadata.json`. +* This example uses three layouts: + * `_includes/layouts/base.njk`: the top level HTML structure + * `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`) + * `_includes/layouts/post.njk`: the blog post template (wrapped into `base.njk`) +* `_includes/postlist.njk` is a Nunjucks include and is a reusable component used to display a list of all the posts. `index.njk` has an example of how to use it. \ No newline at end of file diff --git a/_data/metadata.json b/_data/metadata.json new file mode 100644 index 00000000..415d5e75 --- /dev/null +++ b/_data/metadata.json @@ -0,0 +1,15 @@ +{ + "title": "Your Blog Name", + "url": "https://myurl.com/", + "feed": { + "subtitle": "I am writing about my experiences as a naval navel-gazer.", + "filename": "feed.xml", + "path": "/feed/feed.xml", + "url": "https://myurl.com/feed/feed.xml", + "id": "https://myurl.com/" + }, + "author": { + "name": "Your Name Here", + "email": "youremailaddress@example.com" + } +} diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk new file mode 100644 index 00000000..1da45141 --- /dev/null +++ b/_includes/layouts/base.njk @@ -0,0 +1,38 @@ + + + + + + {{ title or metadata.title }} + + + + + +
+

{{ metadata.title }}

+ +
+ + +
+
    +
  1. Edit the _data/metadata.json with your blog’s information.
  2. +
  3. (Optional) Edit .eleventy.js with your configuration preferences.
  4. +
  5. Delete this message from _includes/layouts/base.njk.
  6. +
+

This is an Eleventy project created from the eleventy-base-blog repo.

+
+ + {{ layoutContent | safe }} + + + + + + + diff --git a/_includes/layouts/home.njk b/_includes/layouts/home.njk new file mode 100644 index 00000000..4dbf888c --- /dev/null +++ b/_includes/layouts/home.njk @@ -0,0 +1,5 @@ +--- +layout: layouts/base.njk +templateClass: tmpl-home +--- +{{ layoutContent | safe }} diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk new file mode 100644 index 00000000..b6b07a81 --- /dev/null +++ b/_includes/layouts/post.njk @@ -0,0 +1,9 @@ +--- +layout: layouts/base.njk +templateClass: tmpl-post +--- +

{{ title }}

+ +{{ layoutContent | safe }} + +

← Home

\ No newline at end of file diff --git a/_includes/postslist.njk b/_includes/postslist.njk new file mode 100644 index 00000000..f6d6c0ae --- /dev/null +++ b/_includes/postslist.njk @@ -0,0 +1,14 @@ +
    +{% for post in postslist | reverse %} +
  1. + {% if post.data.title %}{{ post.data.title }}{% else %}{{ post.url }}{% endif %} + {{ post.date | readableDate }} + {% for tag in post.data.tags %} + {%- if tag != "post" -%} + {% set tagUrl %}/tags/{{ tag }}/{% endset %} + {{ tag }} + {%- endif -%} + {% endfor %} +
  2. +{% endfor %} +
diff --git a/about/index.md b/about/index.md new file mode 100644 index 00000000..4ccc204b --- /dev/null +++ b/about/index.md @@ -0,0 +1,10 @@ +--- +layout: layouts/post.njk +title: About Me +tags: + - nav +navtitle: About +templateClass: tmpl-post +--- + +I am a person that writes stuff. diff --git a/css/index.css b/css/index.css new file mode 100644 index 00000000..dbe07412 --- /dev/null +++ b/css/index.css @@ -0,0 +1,203 @@ +:root { + --red: #C5004A; + --darkred: #7F0036; + --lightgray: #e0e0e0; + --gray: #C0C0C0; + --darkgray: #666; + --navy: #17050F; + --blue: #082840; + --white: #fff; +} +* { + box-sizing: border-box; +} +html, +body { + padding: 0; + margin: 0; + font-family: sans-serif; +} +p:last-child { + margin-bottom: 0; +} +p, +.tmpl-post li, +img { + max-width: 37.5em; /* 600px /16 */ +} +p, +.tmpl-post li { + line-height: 1.45; +} +a[href] { + color: var(--blue); +} +a[href]:visited { + color: var(--navy); +} +main { + padding: 1rem; +} +main :first-child { + margin-top: 0; +} +header { + border-bottom: 1px dashed var(--lightgray); +} +header:after { + content: ""; + display: table; + clear: both; +} +pre, +code { + font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace; + line-height: 1.5; +} +pre { + font-size: 14px; + line-height: 1.375; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + padding: 1em; + margin: .5em 0; + background-color: #f6f6f6; +} +.highlight-line { + padding: 0.125em 1em; /* 2px 16px /16 */ +} +.highlight-line-isdir { + color: #b0b0b0; + background-color: #222; +} +.highlight-line-active { + background-color: #444; + background-color: hsla(0, 0%, 27%, .8); +} +.highlight-line-add { + background-color: #45844b; +} +.highlight-line-remove { + background-color: #902f2f; +} + +/* Header */ +.home { + padding: 0 1rem; + float: left; + margin: 1rem 0; /* 16px /16 */ + font-size: 1em; /* 16px /16 */ +} +.home :link:not(:hover) { + text-decoration: none; +} + +/* Nav */ +.nav { + padding: 0; + list-style: none; + float: left; + margin-left: 1em; +} +.nav-item { + display: inline-block; + margin-right: 1em; +} +.nav-item a[href]:not(:hover) { + text-decoration: none; +} +.nav-item-active { + font-weight: 700; + text-decoration: underline; +} + +/* Posts list */ +.postlist { + list-style: none; + padding: 0; +} +.postlist-item { + counter-increment: start-from -1; +} +.postlist-item:before { + display: inline-block; + pointer-events: none; + content: "" counter(start-from, decimal-leading-zero) ". "; + line-height: 100%; + text-align: right; +} +.postlist-date, +.postlist-item:before { + font-size: 0.8125em; /* 13px /16 */ + color: var(--darkgray); +} +.postlist-date { + word-spacing: -0.5px; +} +.postlist-link { + display: inline-block; + padding: 0.25em 0.1875em; /* 4px 3px /16 */ +} +.postlist-item-active .postlist-link { + font-weight: bold; +} +.tmpl-home .postlist-link { + font-size: 1.1875em; /* 19px /16 */ + font-weight: 700; +} + + +/* Tags */ +.tag { + display: inline-block; + vertical-align: text-top; + text-transform: uppercase; + font-size: 0.625em; /* 10px /16 */ + padding: 2px 4px; + margin-left: 0.8em; /* 8px /10 */ + background-color: var(--red); + color: var(--white); + border-radius: 0.25em; /* 3px /12 */ + text-decoration: none; +} +a[href].tag, +a[href].tag:visited { + color: #fff; +} + +/* Warning */ +.warning { + background-color: #ffc; + padding: 1em 0.625em; /* 16px 10px /16 */ +} +.warning ol:only-child { + margin: 0; +} + +/* Direct Links / Markdown Headers */ +.direct-link { + font-family: sans-serif; + text-decoration: none; + font-style: normal; + margin-left: .1em; +} +a[href].direct-link, +a[href].direct-link:visited { + color: transparent; +} +a[href].direct-link:focus, +a[href].direct-link:focus:visited, +:hover > a[href].direct-link, +:hover > a[href].direct-link:visited { + color: #aaa; +} \ No newline at end of file diff --git a/css/prism-base16-monokai.dark.css b/css/prism-base16-monokai.dark.css new file mode 100644 index 00000000..dceb2a65 --- /dev/null +++ b/css/prism-base16-monokai.dark.css @@ -0,0 +1,89 @@ +code[class*="language-"], pre[class*="language-"] { + font-size: 14px; + line-height: 1.375; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + background: #272822; + color: #f8f8f2; +} +pre[class*="language-"] { + padding: 1.5em 0; + margin: .5em 0; + overflow: auto; +} +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} +.token.comment, .token.prolog, .token.doctype, .token.cdata { + color: #75715e; +} +.token.punctuation { + color: #f8f8f2; +} +.token.namespace { + opacity: .7; +} +.token.operator, .token.boolean, .token.number { + color: #fd971f; +} +.token.property { + color: #f4bf75; +} +.token.tag { + color: #66d9ef; +} +.token.string { + color: #a1efe4; +} +.token.selector { + color: #ae81ff; +} +.token.attr-name { + color: #fd971f; +} +.token.entity, .token.url, .language-css .token.string, .style .token.string { + color: #a1efe4; +} +.token.attr-value, .token.keyword, .token.control, .token.directive, .token.unit { + color: #a6e22e; +} +.token.statement, .token.regex, .token.atrule { + color: #a1efe4; +} +.token.placeholder, .token.variable { + color: #66d9ef; +} +.token.deleted { + text-decoration: line-through; +} +.token.inserted { + border-bottom: 1px dotted #f9f8f5; + text-decoration: none; +} +.token.italic { + font-style: italic; +} +.token.important, .token.bold { + font-weight: bold; +} +.token.important { + color: #f92672; +} +.token.entity { + cursor: help; +} +pre > code.highlight { + outline: 0.4em solid #f92672; + outline-offset: .4em; +} diff --git a/feed/feed.njk b/feed/feed.njk new file mode 100644 index 00000000..636c9c2b --- /dev/null +++ b/feed/feed.njk @@ -0,0 +1,26 @@ +--- +permalink: feed/feed.xml +--- + + + {{ metadata.title }} + {{ metadata.feed.subtitle }} + + + {{ collections.posts | rssLastUpdatedDate }} + {{ metadata.feed.id }} + + {{ metadata.author.name }} + {{ metadata.author.email }} + + {%- for post in collections.posts %} + {% set absolutePostUrl %}{{ post.url | url | absoluteUrl(metadata.url) }}{% endset %} + + {{ post.data.title }} + + {{ post.date | rssDate }} + {{ absolutePostUrl }} + {{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} + + {%- endfor %} + \ No newline at end of file diff --git a/feed/htaccess.njk b/feed/htaccess.njk new file mode 100644 index 00000000..3318d603 --- /dev/null +++ b/feed/htaccess.njk @@ -0,0 +1,5 @@ +--- +permalink: feed/.htaccess +--- +# For Apache, to show `{{ metadata.feed.filename }}` when browsing to directory /feed/ (hide the file!) +DirectoryIndex {{ metadata.feed.filename }} \ No newline at end of file diff --git a/index.njk b/index.njk new file mode 100644 index 00000000..70159be0 --- /dev/null +++ b/index.njk @@ -0,0 +1,10 @@ +--- +layout: layouts/home.njk +tags: + - nav +navtitle: Home +--- + +{% set postslist = collections.posts %} +{% include "postslist.njk" %} + diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 00000000..829d5e59 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,3 @@ +[build] + publish = "_site" + command = "DEBUG=* eleventy" \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..7a7e81dc --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "eleventy-base-blog", + "version": "4.0.2", + "description": "A starter repository for a blog web site using the Eleventy static site generator.", + "scripts": { + "build": "npx eleventy", + "watch": "npx eleventy --watch", + "debug": "DEBUG=* npx eleventy" + }, + "repository": { + "type": "git", + "url": "git://github.com/11ty/eleventy-base-blog.git" + }, + "author": { + "name": "Zach Leatherman", + "email": "zachleatherman@gmail.com", + "url": "https://zachleat.com/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/11ty/eleventy-base-blog/issues" + }, + "homepage": "https://github.com/11ty/eleventy-base-blog#readme", + "devDependencies": { + "@11ty/eleventy": "^0.4.0", + "@11ty/eleventy-plugin-rss": "^1.0.2", + "@11ty/eleventy-plugin-syntaxhighlight": "^1.0.5", + "luxon": "^1.0.0", + "markdown-it": "^8.4.1", + "markdown-it-anchor": "^4.0.0" + } +} diff --git a/posts/firstpost.md b/posts/firstpost.md new file mode 100644 index 00000000..55f3af91 --- /dev/null +++ b/posts/firstpost.md @@ -0,0 +1,22 @@ +--- +title: This is my first post. +tags: + - post + - another-tag +layout: layouts/post.njk +--- +Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment. + +Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring. + +## Section Header + +Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line. + +``` text/2-3 +// this is a command +function myCommand() { + let counter = 0; + counter++; +} +``` diff --git a/posts/secondpost.md b/posts/secondpost.md new file mode 100644 index 00000000..c7afa5f2 --- /dev/null +++ b/posts/secondpost.md @@ -0,0 +1,17 @@ +--- +title: This is my second post. +tags: + - post + - number-2 +layout: layouts/post.njk +--- +Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment. + +## Section Header + +First post +Third post + +Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring. + +Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line. diff --git a/posts/thirdpost.md b/posts/thirdpost.md new file mode 100644 index 00000000..d1283844 --- /dev/null +++ b/posts/thirdpost.md @@ -0,0 +1,22 @@ +--- +title: This is my third post. +tags: + - post + - second-tag +layout: layouts/post.njk +--- +Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment. + +``` js/2/3 +// this is a command +function myCommand() { + let counter = 0; + counter++; +} +``` + +Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring. + +## Section Header + +Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line. diff --git a/tags.njk b/tags.njk new file mode 100644 index 00000000..32cf5986 --- /dev/null +++ b/tags.njk @@ -0,0 +1,18 @@ +--- +pagination: + data: collections + size: 1 + alias: tag + filter: + - all + - nav + - post + - posts +permalink: /tags/{{ tag }}/ +layout: layouts/home.njk +--- + +

Tagged “{{ tag }}”

+ +{% set postslist = collections[ tag ] %} +{% include "postslist.njk" %}