-
+
\ No newline at end of file
diff --git a/_includes/layouts/blank-redirect.njk b/_includes/layouts/blank-redirect.njk
new file mode 100644
index 0000000..8d37655
--- /dev/null
+++ b/_includes/layouts/blank-redirect.njk
@@ -0,0 +1,78 @@
+
+
+
+
+{% include "partials/inspector-splash.njk" %}
+
+
+
+
+
+
+
+
+
+
+ {# redirect URL should be included in page frontmatter #}
+ {# rework this to include a /?rel= value from the referring URL #}
+
+
+
+
+
+
+ {{ site.title }}{% if subtitle %}: {{ subtitle }}{% endif %}
+
+
+
+
+
+ {# if applicable/desired (default: TB green) #}
+
+
+ {# Open Graph meta tags for social media sharing #}
+
+ {# Open Graph meta tags #}
+
+
+
+
+
+
+ {# favicons #}
+
+
+
+
+
+
+ {# ????? what is this ????? #}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if site.canapiKey %}
+
+ {% endif %}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_includes/macros/banner.njk b/_includes/macros/banner.njk
new file mode 100644
index 0000000..61a2ab6
--- /dev/null
+++ b/_includes/macros/banner.njk
@@ -0,0 +1,14 @@
+{% macro banner(content, id, dismissible=true, timeout=false, position="top", type="info") %}
+
+
+ {{ content | safe }}
+
+ {% if dismissible %}
+
+ {% endif %}
+
+{% endmacro %}
\ No newline at end of file
diff --git a/_includes/macros/button.njk b/_includes/macros/button.njk
new file mode 100644
index 0000000..1d77da2
--- /dev/null
+++ b/_includes/macros/button.njk
@@ -0,0 +1,13 @@
+{# not implemented, but would like to refactor sites to use this standardized button component! #}
+{% macro button(text, href="#", className="primary", ariaLabel="", target="", rel="", role="button") %}
+
+ {{ text }}
+
+{% endmacro %}
diff --git a/_includes/noscript-banner.njk b/_includes/noscript-banner.njk
deleted file mode 100644
index 6bc99f3..0000000
--- a/_includes/noscript-banner.njk
+++ /dev/null
@@ -1,5 +0,0 @@
-
\ No newline at end of file
diff --git a/_includes/partials/banners.njk b/_includes/partials/banners.njk
new file mode 100644
index 0000000..c9d94e4
--- /dev/null
+++ b/_includes/partials/banners.njk
@@ -0,0 +1,26 @@
+{% from 'macros/banner.njk' import banner %}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_includes/partials/footer.njk b/_includes/partials/footer.njk
new file mode 100644
index 0000000..ff03b15
--- /dev/null
+++ b/_includes/partials/footer.njk
@@ -0,0 +1,7 @@
+{# duplicate the Terrabyte footer here #}
+
+{# pulled from pixel footer #}
+{# #}
\ No newline at end of file
diff --git a/_includes/partials/inspector-splash.njk b/_includes/partials/inspector-splash.njk
new file mode 100644
index 0000000..361e072
--- /dev/null
+++ b/_includes/partials/inspector-splash.njk
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/_includes/partials/pixel-footer.njk b/_includes/partials/pixel-footer.njk
new file mode 100644
index 0000000..d603ea2
--- /dev/null
+++ b/_includes/partials/pixel-footer.njk
@@ -0,0 +1,39 @@
+
\ No newline at end of file
diff --git a/_includes/partials/ppt-header.njk b/_includes/partials/ppt-header.njk
new file mode 100644
index 0000000..e69de29
diff --git a/_includes/partials/svgs.njk b/_includes/partials/svgs.njk
new file mode 100644
index 0000000..fc0f8b0
--- /dev/null
+++ b/_includes/partials/svgs.njk
@@ -0,0 +1,57 @@
+
\ No newline at end of file
diff --git a/_includes/sr-toc.njk b/_includes/sr-toc.njk
deleted file mode 100644
index 66f454d..0000000
--- a/_includes/sr-toc.njk
+++ /dev/null
@@ -1,15 +0,0 @@
-{# component for building the table of contents for each page (used by screen readers) #}
-
-{# psuedo-code: #}
-{# 1. take the sections of the page #}
-{# 2. make list item for each section #}
-
-
- {# loop through each section in the page #}
-
-
- {# add a link to the top of the page #}
-
Looks like we found a bad byte and some dead pixels. Check the URL above and try again.
+
+
You can also head to the homepage () to try to find what you were looking for there.
+
Or, head to the Terrabyte website to start your digital eco-journey over from the top.
+
+
+
+
\ No newline at end of file
diff --git a/img/meta/logo.png b/img/meta/logo.png
new file mode 100644
index 0000000..25d10ba
Binary files /dev/null and b/img/meta/logo.png differ
diff --git a/index.njk b/index.njk
index 3efaacc..5ca641c 100644
--- a/index.njk
+++ b/index.njk
@@ -1,14 +1,37 @@
---
subtitle: Make It Green, Automatically
layout: layouts/base.njk
-keywords: canapi, terrabyte, automatic, api, software, b2b, green, tech, technology, omaha, nebraska, startup, midwest, business, project, environmental, environmental contributions, tree planting, coral planting, ocean plastic, removal, habitat, restoration, climate, climate change
+keywords: canapi, terrabyte, automatic, api, software, b2b, green, tech, technology, omaha, nebraska, startup, midwest, business, project, environmental, environmental contributions, tree planting, coral planting, ocean plastic, removal, habitat, restoration, climate, climate change, litter, sustainability, automation, saas, software as a service
---
-
+
make it green, automatically
-
\ No newline at end of file
+
+
+
+
+
+ {#
Plant a tree, pickup litter, fund animal research for every product sold, every newsletter sign-up - anything you can imagine.
#}
+
B2B software to help even small operations go green without the hassle.
+
+
+
Canapi is a software as a service (SaaS) product that acts as the middleman between companies and environmental organizations. You decide what triggers environmental contributions, we funnel funds to the organizations that matter most to you.
+
+
+
+
+
+
+
Join Our Newsletter
+
+
+
Stay updated with the latest news, updates, and insights from Canapi. Subscribe to our newsletter and be part of our journey towards a greener future.
+ {# newsletter sign up here #}
+
+
+
\ No newline at end of file
diff --git a/js/global-tb-scripts.js b/js/global-tb-scripts.js
new file mode 100644
index 0000000..ceb8c71
--- /dev/null
+++ b/js/global-tb-scripts.js
@@ -0,0 +1,26 @@
+window.addEventListener("load", function(){
+
+ console.log(`[${window.siteData.project}] global-tb-scripts.js loaded`);
+
+ // could revisit this and create within 11ty??
+
+ // change copyright date
+ var currentDate = new Date();
+ var currentYear = currentDate.getFullYear();
+
+ var copyrightSpan = document.getElementById("current-year-text");
+ // for older implementations
+ var oldCopyrightSpan = document.getElementsByClassName("copyright-date")[0];
+
+ if(copyrightSpan){
+ copyrightSpan.appendChild(document.createTextNode(currentYear));
+ }
+ // for older implementations
+ else if(oldCopyrightSpan){
+ oldCopyrightSpan.appendChild(document.createTextNode(currentYear));
+ }
+ else{
+ // element doesn't exist
+ }
+
+}, false);
\ No newline at end of file
diff --git a/js/scripts.js b/js/scripts.js
deleted file mode 100644
index 44813ef..0000000
--- a/js/scripts.js
+++ /dev/null
@@ -1,7 +0,0 @@
-window.addEventListener("load", function(){
-
- console.log("Canapi scripts.js loaded");
-
-///////////////
-
-}, false);
\ No newline at end of file
diff --git a/js/site-scripts.js b/js/site-scripts.js
new file mode 100644
index 0000000..f2daf1f
--- /dev/null
+++ b/js/site-scripts.js
@@ -0,0 +1,13 @@
+// Careful in template sync, should be site specific
+
+window.addEventListener("load", function(){
+
+ console.log(`[${window.siteData.project}] site-scripts.js loaded`);
+ console.log(`[${window.siteData.project}] Using Template v${window.siteData.templateVersion}`);
+
+ // Add a class to the body element to indicate that the page has loaded
+ document.body.classList.add("loaded");
+
+ // custom script here
+
+}, false);
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 0580e38..56ca0a9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
"name": "canapi-website",
"version": "1.0.0",
"license": "ISC",
+ "dependencies": {
+ "cheerio": "^1.1.2"
+ },
"devDependencies": {
"@11ty/eleventy": "^3.1.1"
}
@@ -409,6 +412,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
@@ -433,6 +442,177 @@
"node": ">=8"
}
},
+ "node_modules/cheerio": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
+ "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "encoding-sniffer": "^0.2.1",
+ "htmlparser2": "^10.0.0",
+ "parse5": "^7.3.0",
+ "parse5-htmlparser2-tree-adapter": "^7.1.0",
+ "parse5-parser-stream": "^7.1.2",
+ "undici": "^7.12.0",
+ "whatwg-mimetype": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=20.18.1"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cheerio-select/node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select/node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/cheerio/node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/cheerio/node_modules/dom-serializer/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/cheerio/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/cheerio/node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/cheerio/node_modules/htmlparser2": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
+ "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.1",
+ "entities": "^6.0.0"
+ }
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -475,6 +655,89 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-select/node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/css-select/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/css-select/node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/css-select/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
@@ -542,7 +805,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -599,11 +861,23 @@
"node": ">= 0.8"
}
},
+ "node_modules/encoding-sniffer": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
+ "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "whatwg-encoding": "^3.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+ }
+ },
"node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -914,6 +1188,18 @@
"node": ">= 0.8"
}
},
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -1288,6 +1574,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
"node_modules/nunjucks": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
@@ -1344,6 +1642,58 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/parse5-parser-stream": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+ "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+ "license": "MIT",
+ "dependencies": {
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1483,6 +1833,12 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
@@ -1654,6 +2010,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
+ "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -1671,6 +2036,27 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/ws": {
"version": "8.18.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
diff --git a/package.json b/package.json
index ae0cdb9..240309c 100644
--- a/package.json
+++ b/package.json
@@ -12,5 +12,8 @@
"description": "",
"devDependencies": {
"@11ty/eleventy": "^3.1.1"
+ },
+ "dependencies": {
+ "cheerio": "^1.1.2"
}
-}
+}
\ No newline at end of file
diff --git a/robots.txt.njk b/robots.txt.njk
new file mode 100644
index 0000000..49150a6
--- /dev/null
+++ b/robots.txt.njk
@@ -0,0 +1,7 @@
+---
+permalink: robots.txt
+eleventyExcludeFromCollections: true
+---
+User-agent: *
+Disallow:
+Sitemap: {{ site.url }}/sitemap.xml
\ No newline at end of file
diff --git a/site.manifest.njk b/site.manifest.njk
new file mode 100644
index 0000000..b657929
--- /dev/null
+++ b/site.manifest.njk
@@ -0,0 +1,25 @@
+---
+permalink: site.webmanifest
+eleventyExcludeFromCollections: true
+---
+{
+ "name": "{{ site.title }}",
+ "short_name": "{{ site.title }}",
+ "start_url": "/",
+ "display": "browser",
+ "background_color": "{{ site.backgroundColor or '#333333' }}",
+ "theme_color": "{{ site.accentColor or '#ffffff' }}",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "description": "{{ site.description | safe }}"
+}
diff --git a/site.webmanifest b/site.webmanifest
deleted file mode 100644
index 45dc8a2..0000000
--- a/site.webmanifest
+++ /dev/null
@@ -1 +0,0 @@
-{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/sitemap.xml.njk b/sitemap.xml.njk
new file mode 100644
index 0000000..8fd1982
--- /dev/null
+++ b/sitemap.xml.njk
@@ -0,0 +1,21 @@
+---
+permalink: sitemap.xml
+eleventyExcludeFromCollections: true
+---
+
+
+ {% for page in collections.all %}
+ {% if page.url and not page.data.draft and not page.data.private %}
+
+ {{ page.url | canonicalUrl }}
+ {# Calculate depth #}
+ {% if page.url == '/' %}{% set depth = 0 %}
+ {% else %}{% set depth = page.url | trim('/') | split('/') | length %}{% endif %}
+ {# Calculate priority #}
+ {% set priority = 1.0 - (depth * 0.1) %}
+ {% if priority > 0.1 %}{{ priority | round(1, 'floor') }}
+ {% else %}0.1{% endif %}
+
+ {% endif %}
+ {% endfor %}
+
\ No newline at end of file
diff --git a/template/.eleventy.js b/template/.eleventy.js
new file mode 100644
index 0000000..fb9750d
--- /dev/null
+++ b/template/.eleventy.js
@@ -0,0 +1,77 @@
+const cheerio = require("cheerio");
+const site = require("./_data/site.json");
+
+module.exports = function (eleventyConfig) {
+ // copy site data
+ eleventyConfig.addPassthroughCopy('.htaccess');
+ // copy directories to the output
+ eleventyConfig.addPassthroughCopy('css');
+ eleventyConfig.addPassthroughCopy('js');
+ eleventyConfig.addPassthroughCopy('img');
+ // copy favicons
+ eleventyConfig.addPassthroughCopy('*.ico');
+ eleventyConfig.addPassthroughCopy('*.png');
+
+ // watch directories for changes
+ eleventyConfig.addWatchTarget('css');
+ eleventyConfig.addWatchTarget('js');
+ eleventyConfig.addWatchTarget('img');
+
+ // shortcodes
+ eleventyConfig.addShortcode("currentYear", () => `${new Date().getFullYear()}`);
+
+ // page transforms and filters
+ // FILTER: split a string by a separator
+ eleventyConfig.addFilter("split", function(str, separator) {
+ if (!str) return [];
+ return str.split(separator);
+ });
+
+ // FILTER: Generate canonical URL
+ eleventyConfig.addFilter("canonicalUrl", function(pageUrl) {
+ // Remove trailing slash from site.url (if present, though it shouldn't be)
+ const base = site.url.replace(/\/$/, "");
+
+ // check if it's the homepage; if so, just return the base URL
+ if (!pageUrl || pageUrl === "/" || pageUrl === "/index.html") {
+ return base;
+ }
+
+ // otherwise, ensure pageUrl starts with a slash
+ const rel = pageUrl.startsWith("/") ? pageUrl : `/${pageUrl}`;
+ return base + rel;
+ });
+
+ // TRANSFORM: create accessibility table of contents
+ eleventyConfig.addTransform("injectSrToc", function(content, outputPath) {
+ if (outputPath && outputPath.endsWith(".html")) {
+ const $ = cheerio.load(content);
+
+ // Build TOC from sections
+ const sections = [];
+ $("section[id]").each((i, elem) => {
+ const id = $(elem).attr("id");
+ const title = id + " section";
+ sections.push({ id, title });
+ });
+
+ // Only inject if there are sections
+ if (sections.length) {
+ const tocHtml = `
+
+ `;
+ // Insert TOC at the start of on the page
+ $("body").prepend(tocHtml);
+ return $.html();
+ }
+ }
+ return content;
+ });
+
+};
\ No newline at end of file
diff --git a/template/.eleventyignore b/template/.eleventyignore
new file mode 100644
index 0000000..27f55c0
--- /dev/null
+++ b/template/.eleventyignore
@@ -0,0 +1,2 @@
+template/
+scripts/
\ No newline at end of file
diff --git a/template/.github/workflows/README.md b/template/.github/workflows/README.md
new file mode 100644
index 0000000..7e2a3fa
--- /dev/null
+++ b/template/.github/workflows/README.md
@@ -0,0 +1,57 @@
+# Terrabyte Cross-Project Template Sync System
+
+**Purpose:** Automatically sync updates from the `terrabyte-11ty-template` repo to downstream Terrabyte sites using a GitHub App and secure automation.
+
+## Overview
+
+This system uses:
+- A **GitHub App** for secure, scalable authentication
+- A **release-based trigger** in the template repo
+- A **repository_dispatch** event to notify downstream repos
+- A **subtree strategy** to keep `/template` folders up to date with the latest Template release
+
+No personal access tokens. No manual syncing. No CI/CD chaos (hopefully).
+
+## Components
+
+### GitHub App: `terrabyte-template-sync`
+- Install on downstream repos (e.g., Terrabyte websites that utilize this template)
+- Authenticates via JWT -> access token -> dispatch event
+
+### Template Repo: [`terrabyte-11ty-template`](./README.md)
+- Contains `notify-downstream.yml` workflow
+- Triggers on release -> sends dispatch to downstream repos
+
+### Downstream Repos
+- Contain `update-template.yml` workflow
+- Listen for `template-release` dispatch -> pull latest template via subtree
+
+## Setup
+
+### Template Repo
+
+The private key and `notify-downstream.yml` file are already in place. The only thing you need to do is create a new release using semantic versioning (v1.1.0, v1.1.1, etc.). Release titles can be descriptive or playful — versioning lives in the tag.
+
+### Downstream Repo
+1. Install GitHub App on the repo
+2. Add `.github/workflows/update-template.yml`:
+ - Listens for `repository_dispatch`
+ - Pulls latest template into `/template` folder
+ - Targets `dev` branch first, falls back to `main`
+ - Uses `[skip ci]` to avoid triggering deploy workflows
+
+## Caveats & Gotchas
+
+- JWTs expire after 10 minutes — automation handles this, but manual testing must be quick
+- App must be installed on each downstream repo — otherwise dispatch will fail silently
+- Do not install the app on the template repo — it only sends, not receives
+- Avoid copying `.github/workflows/notify-downstream.yml` into downstream repos — it’ll create a loop
+- Subtree merges must be squashed — use `--squash` to avoid polluting history
+
+## Scaling to more projects
+
+To add a new Terrabyte site to this automation:
+1. Install the GitHub App on the repo
+2. Add /template to the repo through the subtree process (we specifically need the `update-template.yml` file)
+3. Add the repo name to the `repos=` list in `notify-downstream.yml` Template file
+4. Boom — it’ll sync on the next release of the Terrabyte Template.
\ No newline at end of file
diff --git a/template/.github/workflows/notify-downstream.yml b/template/.github/workflows/notify-downstream.yml
new file mode 100644
index 0000000..45607fe
--- /dev/null
+++ b/template/.github/workflows/notify-downstream.yml
@@ -0,0 +1,60 @@
+name: Notify Downstream Repos
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Generate JWT
+ id: generate-jwt
+ run: |
+ npm install jsonwebtoken
+ node < jwt.txt
+ const fs = require('fs');
+ const jwt = require('jsonwebtoken');
+ const APP_ID = '1920979';
+ const PRIVATE_KEY = \`${{ secrets.APP_PRIVATE_KEY }}\`;
+ const now = Math.floor(Date.now() / 1000);
+ const payload = {
+ iat: now,
+ exp: now + (10 * 60),
+ iss: APP_ID
+ };
+ const token = jwt.sign(payload, PRIVATE_KEY, { algorithm: 'RS256' });
+ console.log(token);
+ EOF
+ echo "jwt=$(cat jwt.txt)" >> $GITHUB_OUTPUT
+
+ - name: Get Installation Access Token
+ id: get-token
+ run: |
+ TOKEN=$(curl -s -X POST \
+ -H "Authorization: Bearer ${{ steps.generate-jwt.outputs.jwt }}" \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/app/installations/84964465/access_tokens | jq -r .token)
+ echo "token=$TOKEN" >> $GITHUB_OUTPUT
+
+ - name: Set downstream repos
+ id: set-repos
+ run: |
+ echo "repos=terrabyte-tech/pixel-pegasus-website" >> $GITHUB_OUTPUT
+ echo "repos=terrabyte-tech/canapi-website" >> $GITHUB_OUTPUT
+ echo "repos=terrabyte-tech/terrabyte-11ty-starter" >> $GITHUB_OUTPUT
+
+ - name: Trigger downstream updates
+ run: |
+ repos="${{ steps.set-repos.outputs.repos }}"
+ for repo in $repos; do
+ echo "Triggering update for $repo..."
+ curl -X POST \
+ -H "Authorization: token ${{ steps.get-token.outputs.token }}" \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/repos/$repo/dispatches \
+ -d '{"event_type":"template-release","client_payload":{"tag":"${{ github.ref_name }}","commit_message_suffix":"[skip ci]"}}'
+ done
diff --git a/template/.github/workflows/update-template.yml b/template/.github/workflows/update-template.yml
new file mode 100644
index 0000000..da8b2f4
--- /dev/null
+++ b/template/.github/workflows/update-template.yml
@@ -0,0 +1,44 @@
+name: Sync Template on Template Release
+
+on:
+ repository_dispatch:
+ types: [template-release] # Triggered remotely from template repo
+ workflow_dispatch:
+
+jobs:
+ update-template:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Determine target branch
+ id: branch-check
+ run: |
+ if git ls-remote --heads origin dev | grep dev; then
+ echo "branch=dev" >> $GITHUB_OUTPUT
+ else
+ echo "branch=main" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Checkout target branch
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ steps.branch-check.outputs.branch }}
+
+ - name: Configure Git
+ run: |
+ git config --global user.name "Terrabyte Bot"
+ git config --global user.email "bot@terrabyte.eco"
+
+ - name: Pull latest template release
+ run: |
+ git subtree pull \
+ --prefix=template \
+ https://github.com/terrabyte-tech/terrabyte-11ty-template.git \
+ ${{ github.event.client_payload.tag }} \
+ --squash
+
+ - name: Commit & Push changes
+ run: |
+ git add template
+ git commit -m "chore: sync template to release ${{ github.event.client_payload.tag }} ${{ github.event.client_payload.commit_message_suffix }}" || echo "No changes to commit"
+ git push origin ${{ steps.branch-check.outputs.branch }}
diff --git a/template/.gitignore b/template/.gitignore
new file mode 100644
index 0000000..5a87346
--- /dev/null
+++ b/template/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+_site
\ No newline at end of file
diff --git a/template/.htaccess b/template/.htaccess
new file mode 100644
index 0000000..6f01167
--- /dev/null
+++ b/template/.htaccess
@@ -0,0 +1,25 @@
+ErrorDocument 400 /error.php
+ErrorDocument 401 /error.php
+ErrorDocument 403 /error.php
+ErrorDocument 404 /error.php
+
+# Performance: Caching headers
+
+ ExpiresActive On
+ ExpiresByType font/woff2 "access plus 1 year"
+ ExpiresByType image/webp "access plus 30 days"
+ ExpiresByType text/css "access plus 7 days"
+ ExpiresByType application/javascript "access plus 7 days"
+
+
+
+
+ Header set Cache-Control "public, max-age=31536000"
+
+
+ Header set Cache-Control "public, max-age=2592000"
+
+
+ Header set Cache-Control "public, max-age=604800"
+
+
\ No newline at end of file
diff --git a/template/README.md b/template/README.md
new file mode 100644
index 0000000..b28c6fa
--- /dev/null
+++ b/template/README.md
@@ -0,0 +1,155 @@
+# Terrabyte 11ty Template
+
+The purpose of this project is to standardize the Terrabyte website development and maintenance workflow. [11ty](https://www.11ty.dev/) is a static-site generator that makes the website build process more efficient by leveraging components, site data variables, and other web dev tools. For more information on using 11ty, please read [their documentation](https://www.11ty.dev/docs/).
+
+Below, you will find a set of instructions for getting started with 11ty, as well as how to best utilize this template in Terrabyte projects (downstream projects).
+
+**NOTE:** Creating a website with 11ty requires Node.js and npm on your machine.
+
+## Table of Contents
+
+- [Initializing a downstream project](#project-initialization)
+- [Changing downstream project content](#project-content)
+ - [Creating a subtree](#1-create-subtree)
+ - [Incorporating template](#2-incorporate-template)
+ - [Dependencies](#3-install-dependencies)
+ - [Adding downstream project content](#4-adding-project-content)
+- [Managing updates to template](#managing-updates)
+
+## Project Initialization
+
+DigitalOcean has a great [guide](https://www.digitalocean.com/community/tutorials/how-to-create-and-deploy-your-first-eleventy-website#step-2-choosing-a-templating-language) on building your first 11ty website. This guide will use their steps while adapting it to this template.
+
+### 1. Create repo & checkout
+
+Create a project repository in GitHub as per-norm. Initialize within GitHub by adding a README, and check it out to your local device through the GitHub CLI (or using terminal commands if you're a nerd ;).
+
+### 2. Initialize project
+
+Within the repo's root folder, run the following commands to create a new Node.js project...
+
+```
+npm init -y
+```
+
+...and install 11ty as a dependency.
+
+```
+npm install -D @11ty/eleventy
+```
+
+### 3. (Optional) package.json
+
+Optionally, you can add the following scripts to the newly-created `package.json` file to make development easier. Replace the existing `scripts{}` object with the following `scripts{}` object:
+
+```
+...
+ "scripts": {
+ "build": "eleventy",
+ "start": "eleventy --serve"
+ },
+...
+```
+
+After saving the `package.json` file, run the following command to build the project for the first time.
+
+```
+npm run build
+```
+
+## Project Content
+
+Now that the 11ty project bones are in place, it's time to implement the `terrabyte-11ty-starter` (boilerplate) and the `terrabyte-11ty-template` (this template). The two can be distinguished by thinking of the boilerplate as a launch point, and the template as shared UI/Component pieces. There may be some shared elements between the two as the file is required no matter if the template is implemented or not.
+
+### 1. Implement Boilerplate
+
+The starter repo is perfect for dropping in the files and components used to build a Terrabyte website. Fetching this content can either be done by simply copy/pasting the repo content, or by creating a subtree. For more information on this starter package, you can view the `terrabyte-11ty-starter` repo on [GitHub](https://github.com/terrabyte-tech/terrabyte-11ty-starter).
+
+### 2. Create Template Subtree
+
+By adding this template to a project folder, you are able to bring template updates into your project without disturbing your code additions later (as long as you diff right). We recommend putting the subtree in a root folder, `/template`.
+
+First, make sure all changes are committed to your branch. Then, create the subtree:
+
+```
+// define remote repo
+git remote add template-remote https://github.com/terrabyte-tech/terrabyte-11ty-template.git
+git fetch template-remote
+
+// ...then add the subtree from remote
+git subtree add --prefix=template template-remote main
+```
+
+### 3. Incorporate Template
+
+If you are starting a new project, you can simply copy all of the content from the `/template` folder into the root.
+
+Caveats that _should not_ be copied include:
+
+- `.git`: This is THIS project's git history - you'll make your own in your new project.
+- `.github/workflows/notify-downstream.yml`: This is automation for triggering the update process for projects that use this template. So, let's not create a blackhole by looping through automations that trigger themselves...
+- `_site`: This is the web-ready content rendered by the 11ty build process. It will be rendered in your new project as well.
+- `node_modules`: This is a folder containing node-specific files. These won't be committed in GitHub nor should they be copied from project to project (use npm for this).
+- `package.json` and `package-lock.json`: You just changed the `package.json` file, no need to overwrite it!
+- `README.md`: Your new project requires it's own README :)
+
+### 4. Install dependencies
+
+Before building the project again, you will need to install dependencies referenced in the template project. This includes:
+
+#### Cheerio
+
+Cheerio is used to create accessibility table of contents per-page (via the `.eleventy.js` file). To install the dependency, run the following command.
+
+```
+npm install cheerio
+```
+
+### 5. Adding project content
+
+At this point, you should be ready to build your website as you intend. This can include building components, pages, and other files.
+
+
+#### `site.json`
+
+This data file should be leveraged for changing site details, information, and other metadata. For a detailed set of data that can be in this file, see [/_data/site.bak.jsonc](./_data/site.bak.jsonc).
+
+## Managing Updates
+
+### General
+
+Whether you are dropping in content from an old project (converting to 11ty) or starting fresh, don't forget to:
+
+Run the build process after making changes to `.eleventy.js` or other build files.
+
+```
+npm run build
+```
+
+And run the local server in order to preview changes as you make them to site files.
+
+```
+npm run start
+```
+
+### Updating Template
+
+As long as this repo is added to the template's `notify-downstream.yml` file, the template within the `/template` folder should _always_ be synced with the latest release of the template. For setup instructions, caveats, and maintenance tips, see the [workflow documentation](.github/workflows/README.md). Otherwise, you can manually update the subtree in the `/template` folder by running the following commands:
+
+```
+// fetch the remote
+git fetch template-remote
+
+// pull remote into /template
+git subtree pull --prefix=template template-remote main
+```
+
+#### Version History
+
+As the template changes, so does the documented version. In order to manage what version you are on and what the latest is, template version is stored in the `package.json` file here, as well as in `site.json` for projects that leverage it. To get the most out of this template, we suggest keeping an updated subtree. For more detailed information on releases, please see the Git activity.
+
+- v1.0.0: Initial release
+- v1.1.x: Added styleType logic, fontFamily support
+- v1.2.x: Added downstream automation, component utilization, implementation documentation
+- v1.3.x: Added global styles, pixel styles, and Canapi styles
+- v1.4.x: Split repo into Template and Starter (boilerplate)
\ No newline at end of file
diff --git a/template/_data/site.bak.jsonc b/template/_data/site.bak.jsonc
new file mode 100644
index 0000000..58b59bd
--- /dev/null
+++ b/template/_data/site.bak.jsonc
@@ -0,0 +1,23 @@
+{
+ "templateVersion": "1.3.6",
+ "project": "Project Name",
+ "title": "Website Title",
+ "url": "https://www.terrabyte.eco",
+ "author": "Terrabyte",
+ "brand": "Terrabyte",
+ "language": "en-US",
+ "description": "Terrabyte is green tech company based in Omaha, NE.",
+ "accentColor": "#0A8C61",
+ "backgroundColor": "#333333",
+ "foregroundColor": "#ffffff",
+ // remove if no particular style set
+ "styleType": "pixel",
+ "schemaType": "Thing",
+ "schemaType": "Organization",
+ "fontsRel": "https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Manrope:wght@400;800&display=swap",
+ "fontsRel": "https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap",
+ // remove if no particular icons set
+ "iconsRel": "",
+ // remove if no Canapi integration
+ "canapiKey": ""
+}
\ No newline at end of file
diff --git a/template/_data/site.json b/template/_data/site.json
new file mode 100644
index 0000000..4a80fce
--- /dev/null
+++ b/template/_data/site.json
@@ -0,0 +1,15 @@
+{
+ "templateVersion": "1.4.0",
+ "project": "Project Name",
+ "title": "Website Title",
+ "url": "https://www.terrabyte.eco",
+ "author": "Terrabyte",
+ "brand": "Terrabyte",
+ "language": "en-US",
+ "description": "Terrabyte is green tech company based in Omaha, NE.",
+ "accentColor": "#0A8C61",
+ "backgroundColor": "#333333",
+ "foregroundColor": "#ffffff",
+ "schemaType": "Thing",
+ "fontsRel": "https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Manrope:wght@400;800&display=swap"
+}
\ No newline at end of file
diff --git a/template/_includes/layouts/base.njk b/template/_includes/layouts/base.njk
new file mode 100644
index 0000000..e64d50d
--- /dev/null
+++ b/template/_includes/layouts/base.njk
@@ -0,0 +1,178 @@
+
+
+
+
+{% include "partials/inspector-splash.njk" %}
+
+
+
+
+
+
+
+
+
+ {# add variable to nunjucks templates that shouldn't be indexed in frontmatter; noIndex: true #}
+ {% if noIndex %}
+
+ {% endif %}
+
+
+
+
+
+
+ {{ site.title }}{% if subtitle %}: {{ subtitle }}{% endif %}
+
+
+
+
+
+ {# if applicable/desired (default: TB green) #}
+
+
+ {# Open Graph meta tags for social media sharing #}
+
+ {# Open Graph meta tags #}
+
+
+
+
+
+
+ {# favicons #}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if site.iconsRel %}
+
+ {% endif %}
+
+
+
+
+
+ {# #}
+
+
+
+
+
+ {% if site.styleType == "pixel" %}
+
+ {% endif %}
+
+
+ {% if site.project == "Canapi" %}
+
+ {% endif %}
+
+
+
+
+ {# other conditional styles #}
+ {# {% if testPage %} #}
+ {# #}
+ {# {% else %} #}
+ {# #}
+ {# {% endif %} #}
+
+
+
+
+
+
+
+
+
+ {# #}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if site.canapiKey %}
+
+ {% endif %}
+
+
+
+
+
+{# ########## #}
+{# dependencies #}
+{# ########## #}
+
+ {# svg container component #}
+ {% include "partials/svgs.njk" %}
+
+{# ########## #}
+{# sys ui #}
+{# ########## #}
+
+ {# modals (not supported atm...) #}
+ {# {% include "modals.njk" %} #}
+
+ {# accessibility/screen reader TOC #}
+ {# handled as .eleventy.js transform #}
+
+ {# noscript banner component #}
+ {% include "partials/banners.njk" %}
+
+{# ########## #}
+{# page begins #}
+{# ########## #}
+
+
+ {% if site.project == "Pixel Planet Today" %}
+ {% include "partials/ppt-header.njk" %}
+ {% else %}
+ {% include "header.njk" %}
+ {% endif %}
+
+
+ {{ content | safe }}
+
+
+
+ {% if site.styleType == "pixel" %}
+ {% include "partials/pixel-footer.njk" %}
+ {% else %}
+ {% include "partials/footer.njk" %}
+ {% endif %}
+
+
\ No newline at end of file
diff --git a/template/_includes/layouts/blank-redirect.njk b/template/_includes/layouts/blank-redirect.njk
new file mode 100644
index 0000000..8d37655
--- /dev/null
+++ b/template/_includes/layouts/blank-redirect.njk
@@ -0,0 +1,78 @@
+
+
+
+
+{% include "partials/inspector-splash.njk" %}
+
+
+
+
+
+
+
+
+
+
+ {# redirect URL should be included in page frontmatter #}
+ {# rework this to include a /?rel= value from the referring URL #}
+
+
+
+
+
+
+ {{ site.title }}{% if subtitle %}: {{ subtitle }}{% endif %}
+
+
+
+
+
+ {# if applicable/desired (default: TB green) #}
+
+
+ {# Open Graph meta tags for social media sharing #}
+
+ {# Open Graph meta tags #}
+
+
+
+
+
+
+ {# favicons #}
+
+
+
+
+
+
+ {# ????? what is this ????? #}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if site.canapiKey %}
+
+ {% endif %}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/template/_includes/macros/banner.njk b/template/_includes/macros/banner.njk
new file mode 100644
index 0000000..61a2ab6
--- /dev/null
+++ b/template/_includes/macros/banner.njk
@@ -0,0 +1,14 @@
+{% macro banner(content, id, dismissible=true, timeout=false, position="top", type="info") %}
+
+
+ {{ content | safe }}
+
+ {% if dismissible %}
+
+ {% endif %}
+
+{% endmacro %}
\ No newline at end of file
diff --git a/template/_includes/macros/button.njk b/template/_includes/macros/button.njk
new file mode 100644
index 0000000..1d77da2
--- /dev/null
+++ b/template/_includes/macros/button.njk
@@ -0,0 +1,13 @@
+{# not implemented, but would like to refactor sites to use this standardized button component! #}
+{% macro button(text, href="#", className="primary", ariaLabel="", target="", rel="", role="button") %}
+
+ {{ text }}
+
+{% endmacro %}
diff --git a/template/_includes/partials/banners.njk b/template/_includes/partials/banners.njk
new file mode 100644
index 0000000..c9d94e4
--- /dev/null
+++ b/template/_includes/partials/banners.njk
@@ -0,0 +1,26 @@
+{% from 'macros/banner.njk' import banner %}
+
+