├── src
├── data
│ └── .gitkeep
├── posts
│ ├── my-first-post.md
│ ├── my-third-post.md
│ └── my-second-post.md
├── includes
│ ├── footer.njk
│ ├── header.njk
│ └── meta.njk
├── assets
│ ├── js
│ │ └── index.js
│ └── css
│ │ └── index.css
├── about.njk
├── sitemap.njk
├── layouts
│ └── base.njk
├── index.njk
└── posts.njk
├── .eleventyignore
├── .env.sample
├── .gitignore
├── postcss.config.js
├── tailwind.config.js
├── README.md
├── package.json
└── .eleventy.js
/src/data/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eleventyignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 |
--------------------------------------------------------------------------------
/.env.sample:
--------------------------------------------------------------------------------
1 | BASE_URL=https://example.com
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | .env
3 | node_modules
4 | .DS_Store
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/posts/my-first-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | title: My First Post
4 | tags: post
5 | ---
6 |
7 | Hello from {{ title }}!
--------------------------------------------------------------------------------
/src/posts/my-third-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | title: My Third Post
4 | tags: post
5 | ---
6 |
7 | Hello from {{ title }}!
--------------------------------------------------------------------------------
/src/posts/my-second-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | title: My Second Post
4 | tags: post
5 | ---
6 |
7 | Hello from {{ title }}!
--------------------------------------------------------------------------------
/src/includes/footer.njk:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/assets/js/index.js:
--------------------------------------------------------------------------------
1 | import '../css/index.css';
2 |
3 | import Alpine from 'alpinejs'
4 |
5 | window.Alpine = Alpine
6 |
7 | // Add Alpine extensions here
8 |
9 | Alpine.start()
10 |
11 | console.log('hello from index.js')
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./src/**/*.{njk,js,html,md,yml,yaml}",
5 | ],
6 | theme: {
7 | extend: {},
8 | },
9 | plugins: [],
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/about.njk:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | eleventyNavigation:
4 | key: About
5 | order: 2
6 | meta:
7 | title: About us
8 | description: this is our about page.
9 | ---
10 |
11 |
12 |
13 | This is the about page
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 11ty + Vite + Tailwind + Alpine
2 |
3 | A static site generation starter with modern tooling and sensible defaults.
4 |
5 | ### Built in settings and features
6 |
7 | - Navigation plugin with data file for configuring html
8 | - SEO optimized meta include file with multiple fallbacks
9 | - Image plugin for performance
10 | - Sitemap generation
--------------------------------------------------------------------------------
/src/assets/css/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 |
7 | body {
8 | min-height: 100dvh;
9 | display: flex;
10 | flex-direction: column
11 | }
12 |
13 | #main {
14 | @apply py-16 px-4 mx-auto max-w-[800px];
15 | }
16 |
17 | li.active {
18 | @apply underline;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/sitemap.njk:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: /public/sitemap.xml
3 | eleventyExcludeFromCollections: true
4 | ---
5 |
6 |
7 | {% for page in collections.all %}
8 |
9 | {{ site.baseUrl }}{{ page.url | url }}
10 | {{ page.date.toISOString() }}
11 |
12 | {% endfor %}
13 |
--------------------------------------------------------------------------------
/src/layouts/base.njk:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ site.title }} - {{ title or meta.title }}
7 | {% include "meta.njk" %}
8 |
9 |
10 |
11 |
12 | {% include "header.njk" %}
13 |
14 |
15 |
16 | {{ content | safe }}
17 |
18 |
19 |
20 | {% include "footer.njk" %}
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/index.njk:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | title: Home page
4 | description: this is the home page meta description.
5 | layout: base
6 | eleventyNavigation:
7 | key: Home
8 | order: 1
9 | ---
10 |
11 |
12 |
13 | Welcome
14 | Test Alpine.js Interactivity below:
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/includes/header.njk:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 | {{ collections.all | eleventyNavigation | eleventyNavigationToHtml({
10 |
11 | listElement: "ul",
12 | listItemElement: "li",
13 |
14 | listClass: "flex gap-4",
15 | listItemClass: "",
16 |
17 | listItemHasChildrenClass: "has-submenu",
18 | anchorClass: "",
19 |
20 | activeListItemClass: "active",
21 | activeAnchorClass: "active",
22 |
23 | activeKey: eleventyNavigation.key,
24 | showExcerpt: false
25 |
26 | }) | safe }}
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/posts.njk:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | eleventyNavigation:
4 | key: Articles
5 | order: 3
6 | pagination:
7 | data: collections.post
8 | size: 12
9 | alias: posts
10 | meta:
11 | title: Posts archive
12 | description: this is where you can find all our posts.
13 | ---
14 |
15 |
16 | All Articles
17 |
24 |
25 |
26 | {% if pagination.href.previous %}
27 |
Previous Page
28 | {% endif %}
29 | {% if pagination.href.next %}
30 |
Next Page
31 | {% endif %}
32 |
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "11ty-alpine-vite-tailwind",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "npx @11ty/eleventy --serve",
8 | "dev": "npx @11ty/eleventy --serve",
9 | "serve": "npx @11ty/eleventy --serve",
10 | "watch": "npx @11ty/eleventy --watch",
11 | "build": "npx @11ty/eleventy",
12 | "clean": "del-cli _site"
13 | },
14 | "keywords": [],
15 | "author": "",
16 | "license": "ISC",
17 | "devDependencies": {
18 | "@11ty/eleventy": "^2.0.1",
19 | "@11ty/eleventy-img": "^3.1.0",
20 | "@11ty/eleventy-navigation": "^0.3.5",
21 | "@11ty/eleventy-plugin-rss": "^1.2.0",
22 | "@11ty/eleventy-plugin-vite": "^4.0.0",
23 | "autoprefixer": "^10.4.14",
24 | "del-cli": "^5.0.0",
25 | "dotenv": "^16.0.3",
26 | "js-yaml": "^4.1.0",
27 | "postcss": "^8.4.21",
28 | "tailwindcss": "^3.3.1"
29 | },
30 | "dependencies": {
31 | "alpinejs": "^3.12.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/includes/meta.njk:
--------------------------------------------------------------------------------
1 | {# We use eleventy-rss plugin absoluteUrl filter as helper for absolute URL generation #}
2 |
3 | {# General #}
4 |
5 |
6 |
7 | {# Open Graph #}
8 |
9 |
10 |
11 |
12 |
13 |
14 | {%- if meta.image -%}
15 |
16 | {%- endif -%}
17 | {# End Open Graph #}
18 |
19 | {# Twitter #}
20 |
21 |
22 |
23 | {%- if meta.image -%}
24 |
25 | {%- endif -%}
26 | {# End Twitter #}
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.eleventy.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const pluginRss = require("@11ty/eleventy-plugin-rss"); // needed for absoluteUrl SEO feature
3 | const eleventyNavigationPlugin = require("@11ty/eleventy-navigation");
4 | const EleventyVitePlugin = require("@11ty/eleventy-plugin-vite");
5 | const Image = require("@11ty/eleventy-img");
6 | const yaml = require("js-yaml"); // Because yaml is nicer than json for editors
7 | require('dotenv').config();
8 |
9 | const baseUrl = process.env.BASE_URL || "http://localhost:8080";
10 | console.log('baseUrl is set to ...', baseUrl);
11 |
12 | const globalSiteData = {
13 | title: "11ty Starter Site",
14 | description: "This is a basic 11ty starter template with my most commonly used features and modern tooling",
15 | locale: 'en',
16 | baseUrl: baseUrl,
17 | }
18 |
19 | module.exports = function(eleventyConfig) {
20 |
21 | /* --- GLOBAL DATA --- */
22 |
23 | eleventyConfig.addGlobalData("site", globalSiteData);
24 |
25 | /* --- YAML SUPPORT --- */
26 |
27 | eleventyConfig.addDataExtension("yaml", contents => yaml.load(contents));
28 | eleventyConfig.addDataExtension("yml", contents => yaml.load(contents));
29 |
30 | /* --- PASSTHROUGHS --- */
31 |
32 | eleventyConfig.addPassthroughCopy('src/assets/css')
33 | eleventyConfig.addPassthroughCopy('src/assets/js')
34 |
35 |
36 | /* --- PLUGINS --- */
37 |
38 | eleventyConfig.addPlugin(pluginRss); // just includes absolute url helper function
39 | eleventyConfig.addPlugin(eleventyNavigationPlugin);
40 | eleventyConfig.addPlugin(EleventyVitePlugin, {});
41 |
42 | /* --- SHORTCODES --- */
43 |
44 | // Image shortcode config
45 | let defaultSizesConfig = "(min-width: 1200px) 1400px, 100vw"; // above 1200px use a 1400px image at least, below just use 100vw sized image
46 |
47 | eleventyConfig.addShortcode("image", async function(src, alt, sizes=defaultSizesConfig) {
48 | console.log(`Generating image(s) from: ${src}`)
49 | let metadata = await Image(src, {
50 | widths: [800, 1500],
51 | formats: ["webp", "jpeg"],
52 | urlPath: "/images/",
53 | outputDir: "./_site/images/",
54 | filenameFormat: function (id, src, width, format, options) {
55 | const extension = path.extname(src)
56 | const name = path.basename(src, extension)
57 | return `${name}-${width}w.${format}`
58 | }
59 | });
60 |
61 | let imageAttributes = {
62 | alt,
63 | sizes,
64 | loading: "lazy",
65 | decoding: "async",
66 | };
67 |
68 | return Image.generateHTML(metadata, imageAttributes);
69 | });
70 |
71 | // Output year for copyright notices
72 | eleventyConfig.addShortcode("year", () => `${new Date().getFullYear()}`);
73 |
74 |
75 | /* --- FILTERS --- */
76 |
77 | // Custom Random Helper Filter (useful for ID attributes)
78 | eleventyConfig.addFilter("generateRandomIdString", function (prefix) {
79 | return prefix + "-" + Math.floor(Math.random() * 1000000);
80 | });
81 |
82 |
83 | /* --- BASE CONFIG --- */
84 |
85 | return {
86 | dir: {
87 | input: "src",
88 | output: "_site",
89 | includes: "includes", // this path is releative to input-path (src/)
90 | layouts: "layouts", // this path is releative to input-path (src/)
91 | data: "data", // this path is releative to input-path (src/)
92 | },
93 | templateFormats: ["njk", "md"],
94 | htmlTemplateEngine: "njk",
95 | markdownTemplateEngine: "njk",
96 | };
97 | };
--------------------------------------------------------------------------------