├── .eleventyignore ├── .gitignore ├── src ├── _data │ └── meta.mjs ├── content │ ├── another.md │ └── post.md ├── _includes │ ├── _footer.vto │ ├── _loader.vto │ ├── layout.vto │ └── _navigation.vto ├── index.md └── css │ └── style.css ├── server └── main.ts ├── deno.json ├── README.md ├── layout.njk ├── eleventy.config.mjs └── deno.lock /.eleventyignore: -------------------------------------------------------------------------------- 1 | server -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .DS_Store -------------------------------------------------------------------------------- /src/_data/meta.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | url: Deno.env.get("Host") || "http://localhost:8080", 3 | siteName: "11ty deno htmx", 4 | siteDescription: "A quick way to get started with Eleventy and deno deploy (also using HTMX)", 5 | }; -------------------------------------------------------------------------------- /src/content/another.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Htmx 3 | slug: Htmx 4 | tags: pages 5 | layout: layout.vto 6 | --- 7 | 8 | ## Hello! 9 | 10 | Here is another page, and it was fetched using Htmx and replaced into the #content area of this page. If you inspect the network tab in a browser you’ll see Htmx handling page requests. In a non-javascript situation, everything will fall back to normal full page requests. 11 | -------------------------------------------------------------------------------- /src/content/post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deno 3 | slug: Deno 4 | tags: pages 5 | layout: layout.vto 6 | --- 7 | 8 | ## How do I use this? 9 | 10 | ### Installing Deno 11 | 12 | To install Deno, follow the [docs here](https://docs.deno.com/runtime/manual/getting_started/installation), 13 | You can then clone or download [this starter](https://github.com/cssandstuff/11ty-deno-htmx) 14 | 15 | For local development run the deno command:
deno task dev
16 | 17 | To deploy to deno.deploy you just need to [sign up for an account](https://deno.com/deploy), then once logged in you can create a new project and point it to your github repo. 18 | -------------------------------------------------------------------------------- /src/_includes/_footer.vto: -------------------------------------------------------------------------------- 1 | 11 | 12 | {{- css }} 13 | .footer { 14 | margin-top: var(--space-3); 15 | padding: var(--space) var(--space-2); 16 | display: flex; 17 | justify-content: space-between; 18 | align-items: baseline; 19 | } 20 | .footer ul{ 21 | margin: 0; padding: 0; 22 | display: flex; 23 | gap: var(--space-2); 24 | list-style: none; 25 | } 26 | {{ /css }} 27 | 28 | -------------------------------------------------------------------------------- /server/main.ts: -------------------------------------------------------------------------------- 1 | import { Application, Router } from "@oak/oak"; 2 | 3 | const app = new Application(); 4 | 5 | // First we try to serve static files from the _site folder. If that fails, we 6 | // fall through to the router below. 7 | app.use(async (ctx, next) => { 8 | try { 9 | await ctx.send({ 10 | root: `${Deno.cwd()}/_site`, 11 | index: "index.html", 12 | }); 13 | } catch { 14 | next(); 15 | } 16 | }); 17 | 18 | const router = new Router(); 19 | 20 | // After creating the router, we can add it to the app. 21 | app.use(router.routes()); 22 | app.use(router.allowedMethods()); 23 | 24 | console.log("✨ Server ready! Browse at http://localhost:8000 ✨"); 25 | 26 | await app.listen({ port: 8000 }); -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Esm in 11ty 3 | slug: 11ty 4 | layout: layout.vto 5 | --- 6 | 7 | ## 11ty 8 | 9 | Now that Eleventy supports ESM (from version 3.x), it means we can use it in places we couldn’t previously. 10 | 11 | ## Htmx 12 | 13 | Not really necessary to get you running on deno.deploy, but I like what this project sets out to achieve and it pairs great with Eleventy so that you can request pages without full page reloads. (pretty easily done with minimal changes to your templates). 14 | 15 | ## Deno 16 | 17 | Deno is a fast, secure and great alternative to Node and now supports most of the node ecosystem, so it seems like a great time to try and bring the two together in a starter project, and that’s exactly what this is. You can host statically on Deno, but then there’s room to do server stuff too if you want. 18 | 19 | 20 | -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "deno.ns"] 4 | }, 5 | "tasks": { 6 | "clean": "rm -rf _site", 7 | "eleventyWatch": "deno run --allow-sys --allow-run --allow-read --allow-write --allow-env --allow-ffi npm:@11ty/eleventy@^3.1.2 --watch", 8 | "generate": "deno task clean && deno run --allow-read --allow-write --allow-env --allow-sys --allow-ffi npm:@11ty/eleventy@^3.1.2", 9 | "dev": "deno task eleventyWatch & deno run --watch --allow-net --allow-read --unstable-kv --allow-ffi server/main.ts", 10 | "prod": "deno task generate" 11 | }, 12 | "imports": { 13 | "@11ty/eleventy": "npm:@11ty/eleventy@^3.1.2", 14 | "@11ty/eleventy-plugin-bundle": "npm:@11ty/eleventy-plugin-bundle@^3.0.7", 15 | "@oak/oak": "jsr:@oak/oak@^17.2.0", 16 | "eleventy-plugin-vento": "npm:eleventy-plugin-vento@^5.2.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/_includes/_loader.vto: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{- css }} 4 | @keyframes fade{ 5 | 0%{ 6 | background-position:-50% 50%; 7 | opacity: 0; 8 | } 9 | 50%{ 10 | background-position:200% 50%; 11 | opacity: 1; 12 | } 13 | 100%{ 14 | background-position:400% 50%; 15 | opacity: 0; 16 | } 17 | } 18 | 19 | #loader{ 20 | display: none; 21 | width: 100%; 22 | height: 6px; 23 | position: absolute; 24 | left: 0; top: 0; 25 | overflow: hidden; 26 | } 27 | 28 | #loader .loader{ 29 | animation: fade linear 2s infinite; 30 | width: 100vw; 31 | display: block; 32 | height: 100%; 33 | position: absolute; 34 | top: 0px; 35 | left: 0; 36 | background: linear-gradient(90deg, var(--grey-a0), var(--grey-a50), var(--grey-a0)); 37 | background-size: 75% 100%; 38 | } 39 | 40 | /* show loader animaton shimmer bar, when requests are being made */ 41 | body:has(#nav .htmx-request, #content a.htmx-request) #loader, 42 | body:has(.htmx-request) #loader 43 | { 44 | display: block; 45 | } 46 | {{ /css }} -------------------------------------------------------------------------------- /src/_includes/layout.vto: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ meta.siteName }} — {{ title }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

{{ title }}

17 | {{ include "./_loader.vto" }} 18 |
19 |
20 |

11tyHtmxDeno starter project

21 |
22 | {{ include "./_navigation.vto" }} 23 |
24 |
{{ content }}
25 |
26 | {{ include "./_footer.vto" }} 27 |
28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hi! thanks for checking this out, I’ve also written [a little bit of background](https://cssandstuff.com/writing/pairing-eleventy-with-htmx-and-deno/) about this project as well as some help [getting deno working with 11ty](https://cssandstuff.com/writing/eleventy-with-a-basic-deno-static-server-setup/). 2 | 3 | The project is also available to view at [11ty.deno.dev](https://11ty.deno.dev/) 4 | 5 | # 11ty + Htmx + Deno starter. 6 | 7 | Now that Eleventy supports ESM (from version 3.x), it means we can use it in places we couldn't previously. 8 | 9 | ## Deno 10 | 11 | Deno is a fast, secure and great alternative to Node and now supports most of the node ecosystem, so it seems like a great time to try and bring the two together in a starter project, and that's exactly what this is. Deno.deploy is also a super great place to try out ideas and has native key-pair database for doing server-side like things. 12 | 13 | ## Htmx 14 | 15 | I like what this project sets out to achieve and it pairs great with Eleventy... you can do client side routing pretty easily with minimal changes to your markup. 16 | 17 | ### Notes about Vento 18 | 19 | Vento is a new layout/templating engine written in javascript which has a well supported plugin module for 11ty and works natively in deno too, so I've switched over to using that for everthing. -------------------------------------------------------------------------------- /layout.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{meta.siteName}} — {{title}} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

{{title}}

17 | {% renderTemplate "webc" %}{% endrenderTemplate %} 18 |
19 |
20 |

11tHD starter project

21 |
22 |
23 | {% include '_navigation.njk' %} 24 |
{{ content | safe }}
25 |
26 | {% renderTemplate "webc" %}{% endrenderTemplate %} 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/_includes/_navigation.vto: -------------------------------------------------------------------------------- 1 | {{ set currentUrl = page.url }} 2 | {{- js }} 3 | document.body.addEventListener('htmx:afterSwap', function(evt) { 4 | let currentSlug = window.location.pathname; 5 | let navLinks = document.querySelectorAll('#nav a'); 6 | 7 | navLinks.forEach(function(link) { 8 | let linkSlug = link.getAttribute('href'); 9 | if (currentSlug === linkSlug) { 10 | link.setAttribute("aria-current", "page") 11 | }else{ 12 | link.removeAttribute("aria-current") 13 | } 14 | }); 15 | }); 16 | {{ /js }} 17 | 18 | 36 | 37 | {{- css }} 38 | .nav{ 39 | padding: 0 var(--space) 0 calc( var(--space) * 1.5 ); 40 | margin-bottom: var(--space-2); 41 | font-family: var(--fontFam); 42 | font-weight: 300; 43 | font-size: 1.2em; 44 | } 45 | 46 | .nav ul{ 47 | display: flex; 48 | gap: var(--space); 49 | margin: 0; 50 | padding: 0 51 | } 52 | 53 | .nav ul li{ 54 | list-style: none; 55 | padding: 0; 56 | margin: 0; 57 | } 58 | 59 | .nav [aria-current="page"]{ 60 | text-decoration-thickness: 2px; 61 | text-decoration-color: var(--link-color); 62 | } 63 | 64 | .nav ul li:first-child{ 65 | margin-left: calc( var(--space)/ 3 * -1) 66 | } 67 | 68 | .nav ul li a{ 69 | padding: var(--space) calc( var(--space)/ 2); 70 | display: block; 71 | } 72 | {{ /css }} 73 | 74 | -------------------------------------------------------------------------------- /eleventy.config.mjs: -------------------------------------------------------------------------------- 1 | // Eleventy 3! 2 | import { VentoPlugin } from 'eleventy-plugin-vento'; 3 | import { EleventyRenderPlugin } from "@11ty/eleventy"; 4 | 5 | export default function (eleventyConfig) { 6 | eleventyConfig.addPassthroughCopy("./src/css/*.css"); 7 | 8 | eleventyConfig.addPlugin(EleventyRenderPlugin); 9 | 10 | eleventyConfig.addBundle("css", { 11 | toFileDirectory: "_site", 12 | // Add all