Skip to content

Instantly share code, notes, and snippets.

@shawn-sandy
Last active January 31, 2022 12:33
Show Gist options
  • Save shawn-sandy/1f9d7129bc300861508eb11d154ada0b to your computer and use it in GitHub Desktop.
Save shawn-sandy/1f9d7129bc300861508eb11d154ada0b to your computer and use it in GitHub Desktop.
FP-Pages
const fs = require("fs");
const Image = require("@11ty/eleventy-img");
const htmlmin = require("html-minifier");
const pluginRss = require("@11ty/eleventy-plugin-rss");
const markdown = require("@shawnsandy/ideas/lib/markdown");
const CleanCSS = require("clean-css");
const eleventyNavigationPlugin = require("@11ty/eleventy-navigation");
module.exports = function (eleventyConfig) {
eleventyConfig.setBrowserSyncConfig({
notify: true,
open: true,
callbacks: {
ready: function (err, bs) {
bs.addMiddleware("*", (req, res) => {
const content_404 = fs.readFileSync("www/404.html");
// Provides the 404 content without redirect.
res.write(content_404);
// Add 404 http status code in request header.
// res.writeHead(404, { "Content-Type": "text/html" });
res.writeHead(404);
res.end();
});
},
},
});
eleventyConfig.setQuietMode(true);
eleventyConfig.addWatchTarget("./src/sass/");
eleventyConfig.addWatchTarget("./README.md");
eleventyConfig.addWatchTarget("./src/js/");
eleventyConfig.addPassthroughCopy("./src/css", "www/css/");
eleventyConfig.addPassthroughCopy("./system/dsp/assets", "www/assets/");
eleventyConfig.addPassthroughCopy("./src/images", "./images/");
eleventyConfig.addPassthroughCopy("./img");
eleventyConfig.addPassthroughCopy("./src/js/min", "www/js");
eleventyConfig.addPassthroughCopy("./src/admin");
// eleventyConfig.addPassthroughCopy("./src/robots.txt")
eleventyConfig.addNunjucksAsyncShortcode("image", imageShortcode);
// css-min filter
eleventyConfig.addFilter("cssmin", (code) => {
return new CleanCSS({}).minify(code).styles;
});
//Minify our HTML
eleventyConfig.addTransform("htmlmin", (content, outputPath) => {
if (outputPath.endsWith(".html")) {
let minified = htmlmin.minify(content, {
useShortDoctype: true,
removeComments: true,
collapseWhitespace: true,
});
return minified;
}
return content;
});
eleventyConfig.addCollection("developer", (collection) =>
collection.getFilteredByTags("developers").sort((a, b) => {
if (a.data.page.fileSlug > b.data.page.fileSlug) return -1;
else if (a.data.page.fileSlug < b.data.page.fileSlug) return 1;
else return 0;
})
);
eleventyConfig.addPlugin(require("@shawnsandy/ideas/eleventy"));
eleventyConfig.addPlugin(pluginRss);
eleventyConfig.addPlugin(markdown);
// navigation
eleventyConfig.addPlugin(eleventyNavigationPlugin);
return {
dir: {
input: "src",
output: "www",
includes: "../system/_includes",
data: "../system/_data",
},
templateFormats: ["njk", "html", "md"],
htmlTemplateEngine: "njk",
markdownTemplateEngine: "njk",
// pathPrefix: "/",
};
};
async function imageShortcode(src, alt = "", sizes = "50vw, 100vw") {
let metadata = await Image(src, {
widths: [300, 600],
formats: ["avif", "jpeg"],
});
let imageAttributes = {
alt,
sizes,
loading: "lazy",
decoding: "async",
};
// You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
return Image.generateHTML(metadata, imageAttributes);
}
#HELLO=Hello developer
NODE_ENV=development
SITE_MAP_URL='https://www.sites.dev/sitemap.xml'
CONTACT_EMAIL=shawnsandy04@gmail.com
FORM_PROVIDER=web3forms
CONTACT_SUCCESS=/thank-you/
CONTACT_PROVIDER=web3forms
// @ts-check
'use strict'
const take = require('lodash.take')
const date = new Date()
const dayjs = require('dayjs')
const relativeTime = require('dayjs/plugin/relativeTime')
const currentYear = () => date.getFullYear()
const formatDate = (date) => new Date(date).toDateString()
const stripHtml = (data = null) => {
if (data === null || data === undefined) return
return data.replace(/(<([^>]+)>)/gi, '')
}
const limit = ($arr = [], $limit = 3) => {
if ($arr.length >= 1) {
if (!$limit || $limit === null) {
return $arr
}
return take($arr, $limit)
}
return null
}
const timeAgo = (date) => {
dayjs.extend(relativeTime)
return dayjs(date).fromNow()
}
const openUrl = (url, label = null) => {
if (!url) { console.warn('url required'); return }
return `<a href="${url}" target="_blank" rel="nofollow noopener">${label || url}</a>`
}
module.exports = {
year: currentYear,
currentYear,
formatDate,
strip: stripHtml,
stripHtml, // deprecated use strip
limit,
timeAgo,
openUrl
}
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="x-ua-compatible" content="ie=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<script src="https://kit.fontawesome.com/e2ffdf4c70.js" crossorigin="anonymous"></script>
<meta name="description" content="{{ settings.description }}"/>
{% block head %}
<title>{{ settings.title }}
|
{{ title }}</title>
{% set css %}
{% include "src/css/critical.css" %}
{% endset %}
{# css #}
<style>
{{css | cssmin | safe}}
</style>
<link rel="stylesheet" href="/css/styles.css" media="all"/>
<link rel="stylesheet" href="/css/elements.css" media="all"/>
{% for styles in settings.styles %}
<link href="{{ styles }}" rel="stylesheet" media="all"/>
{% endfor %}
{% if stylesheets %}
{% for style in stylesheets %}
<link rel="stylesheet" href="{{ style }}" media="all"/>
{% endfor %}
{% endif %}
{% endblock %}
{# load up global macros #}
{% import "_macros/collections/featured.njk" as feature with context %}
</head>
<body class="{{ title | slug }}">
{% block header %}
{% include "partials/nav.njk" %}
{% endblock %}
<header>
{% block cover %}{% endblock %}
</header>
{% block content %}
{{ content | safe }}
{% endblock %}
{% block footer %}
{% include "partials/footer.njk" %}
{% endblock %}
{% for js in metadata.scripts %}
<script src="{{ js }}"></script>
{% endfor %}
{# grab any scripts in the settings.js #}
{% if settings.scripts %}
{% for src in settings.scripts %}
<script src="{{ src }}"></script>
{% endfor %}
{% endif %}
{# load scripts data from the page #}
{% if scripts %}
{% for script in scripts %}
<script src="{{ script }}"></script>
{% endfor %}
{% endif %}
{%- if showRecaptcha and env.form_provider === "web3forms" %}
<script src="https://www.google.com/recaptcha/api.js?render={{ env.recaptcha_key or 'key-not-found' }}"></script>
<script>
grecaptcha.ready(function () {
grecaptcha
.execute("{{ env.recaptcha_key }}", {action: "contact"})
.then(function (token) {
recaptchaResponse.value = token;
});
});
</script>
{% endif -%}
</body>
</html>
{% if env.node_env != 'production' %}
<script src="https://cdn.accesslint.com/accesslint-1.1.2.js"></script>
{% endif %}
---
title: A decent(ish) built in clipboard manager for Windows10
subtitle: Windows10 not only has a built in clipboard manager but also gives you
the ability to sync your clipboard across devices
tags: ['posts', 'tips', 'Win10']
date: 2021-05-28
---
<article role="region">
<article>
<h3>
<a href="#">Sample Article</a>
</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae
assumenda odio rem maiores ad minima doloribus. Pariatur quibusdam dolorum
distinctio repellendus vero natus explicabo mollitia ea, nemo sunt
voluptatibus eaque!
</p>
<footer>
<p>
<a href="#" role="button"><span>Read more</span></a>
</p>
</footer>
</article>
<article>
<h3>
<a href="#">Sample Article</a>
</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae
assumenda odio rem maiores ad minima doloribus. Pariatur quibusdam dolorum
distinctio repellendus vero natus explicabo mollitia ea, nemo sunt
voluptatibus eaque!
</p>
<footer>
<p>
<a href="#" role="button"><span>Read more</span></a>
</p>
</footer>
</article>
<article>
<h3>
<a href="#">Sample Article</a>
</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae
assumenda odio rem maiores ad minima doloribus. Pariatur quibusdam dolorum
distinctio repellendus vero natus explicabo mollitia ea, nemo sunt
voluptatibus eaque!
</p>
<footer>
<p>
<a href="#" role="button"><span>Read more</span></a>
</p>
</footer>
</article>
<article>
<h3>
<a href="#">Sample Article</a>
</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae
assumenda odio rem maiores ad minima doloribus. Pariatur quibusdam dolorum
distinctio repellendus vero natus explicabo mollitia ea, nemo sunt
voluptatibus eaque!
</p>
<footer>
<p>
<a href="#" role="button"><span>Read more</span></a>
</p>
</footer>
</article>
<article>
<h3>
<a href="#">Sample Article</a>
</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae
assumenda odio rem maiores ad minima doloribus. Pariatur quibusdam dolorum
distinctio repellendus vero natus explicabo mollitia ea, nemo sunt
voluptatibus eaque!
</p>
<footer>
<p>
<a href="#" role="button"><span>Read more</span></a>
</p>
</footer>
</article>
</article>
{% macro articles(category = 'post', collection = null) %}
{% set collectionArr = collections[category] | reverse %}
{% if collection !== null %}
{% set collectionArr = collection %}
{% endif %}
<article>
{% for content in collectionArr %}
<article>
<h3 id="{{ content.data.title | slug }}">
<a href="{{ content.url }}">{{ content.data.title }}</a>
</h3>
<time datetime="{{ page.date.toLocaleString() }}">
Posted:
{{ content.date.toUTCString() }}
</time>
<p>{{ content.data.summary }}</p>
<footer>
<a href="{{ content.url }}" role="button">
<em>Continue reading</em>
</a>
</footer>
<hr/>
</article>
{% endfor %}
</article>
{% endmacro %}
{% extends "_Layout.njk" %}
<!-- head -->
{% block head %}{{ super() }} {% endblock %}
<!-- cover -->
{% block cover %} {% endblock %}
<!-- content -->
{% block content %}
<main>
<section>
{% if showDate %} Posted:
<time datetime="{{ page.date }}">
{{ page.date.toDateString() }}
</time>
{% endif %}
{{ content | safe }}
</section>
<aside>{% include "partials/sidebar.njk" %}</aside>
</main>
{% endblock %}
<nav role="navigation" aria-label="Main navigation">
<section role="region">
<h1>
<a href="/" aria-label="Site logo">
<img src="/images/dsp-kit-logo.svg" alt="DSP Kit" />
</a>
</h1>
</section>
<section>
<a href="/tokens" title="Color tokens">Color</a>
<a href="/fonts" title="Font Tokens">Fonts</a>
<a href="/components" title="View components">Components</a>
<a href="/docs" title="Documentation">Guide</a>
</section>
</nav>
{% extends "base.njk" %}
<!-- hide cover page -->
{% block cover %}
<section class="bg-section" style="">
<h3 class="title-font quote">
{{ subtitle or settings.subtitle }}
</h3>
{% endblock %}
{% block content %}
<main style="padding-top: calc(100 / 16 * 1rem)">
<section>
{# -------------- #}
<article>
<p>
{{ content | safe }}
</p>
</article>
</section>
<aside>
{% include "partials/sidebar.njk" %}
</aside>
</main>
{% endblock %}
---
title: Contact Us
scripts: ["/js/min/form.js"]
eleventyNavigation:
key: Contact Us
order: 5
---
<h4>Contact Info</h4>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid ut delectus
accusamus commodi officia fugit sequi? Quisquam deleniti, atque natus
inventore exercitationem voluptatem eius facilis maxime itaque, esse molestias
recusandae.
</p>
{% if env.form_provider == "netlify" %}
<div>{% include 'partials/contact.njk' %}</div>
{% elif env.form_provider == "web3forms" %}
<div>{% include 'partials/webform-contact.njk' %}</div>
{% else %}
<hr />
<p>
Thanks you message, feedback, questions or suggestions, someone form our team
will review your email and respond as soon as possible.
</p>
<hr />
{% endif %}
<p>{{ hlp.11ty.noHtml(content.templateContent) | truncate(300) }}</p>
@use "../system/dsp/dist/styledictionary/scss/variables.scss"as tokens;
@use '@shawnsandy/first-paint/src/components/reset.scss';
@use '@shawnsandy/first-paint/src/components.scss'with($render-page: true,
$render-type: true,
$render-nav: true,
$render-footer: true,
$render-main: true,
$render-grid: true,
// $render-form: true, // the form is optional
);
[data-cover] {
display: flex;
flex-direction: column;
height: 100vh;
}
nav,
footer {
flex-shrink: 0;
}
header {
display: flex;
flex-direction: column;
flex-grow: 1;
align-items: center;
justify-content: center;
&>[role="banner"] {
flex-grow: 1;
@include components.header-banner();
min-height: 35rem
}
.fp-button-link[role=button]>em,
a[role=button]>em {
font-size: 1.4rem;
background-color: #fff;
border-radius: 6.1875rem !important;
text-shadow: none;
box-shadow: none;
box-shadow: 0.2rem 0.2rem 0.2rem rgba(0, 0, 0, 0.2);
&:hover {
background-color: #fff;
box-shadow: 0.2rem 0.5rem 0.5rem rgba(7, 0, 0, 0.2)
}
}
}
@include components.button-links();
header {
background-color: tokens.$midnight-blue;
background-image: url('../images/banner-hero.svg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
color: tokens.$white-smoke;
text-shadow: 0.2rem 0.2rem 0.2rem rgba(0, 0, 0, 0.2);
padding: 3rem 0;
min-height: 350rem / 16;
h2 {
font-size: 4rem;
}
>section,
div {
max-width: 70vw;
text-align: center;
margin: 0 auto;
}
margin-bottom: 4rem;
}
section[aria-label="feature"] {
@media (min-width: 980px) {
max-width: 80%;
margin: auto;
}
&[aria-label=feature] h3 {
display: block;
font-size: 2.5rem;
color: #1010b9;
margin-bottom: 1.5rem;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>title</title>
<meta name="description" content="title" />
<meta name="author" content="author" />
<link rel="stylesheet" href="/styles/cover-page.css" />
</head>
<body>
<header>
<nav role="navigation" aria-label="Main navigation">
<section id="navigation">
<h1>
<a href="#" aria-label="Site logo">
<img src="/img/fp.svg" alt="" /><span aria-label="logo text"
>FirstPaint</span
>
</a>
</h1>
</section>
<section>
<ul>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
</ul>
</section>
<section>
<a href="#">Blog</a>
<a href="#">About</a>
<a href="http://">Documentation</a>
<a href="http://">Repository</a>
<a href="#">Contact Us</a>
<a href="http://" role="button"><em>Button Link</em></a>
</section>
</nav>
<section role="banner">
<div>
<!-- <img src="img/fp.svg" alt="" /> -->
<h2>Lightweight, Fast, Accessible, Inclusive</h2>
<p>
<span
>First Paint is lightweight easy to use CSS/SCSS starter library
for quickly scaffolding/building modern, mobile friendly
websites.</span
>
</p>
<a
href="#"
role="button"
aria-label="Add word, cta action, to your button title"
>
<span>Get Started</span></a
>
<a
href="#"
role="button"
aria-label="Add word, cta action, to your button title"
>
<strong>Get Started</strong></a
>
<a
href="#"
role="button"
aria-label="Add word, cta action, to your button title"
>
<em>Get Started</em></a
>
</div>
</section>
</header>
<!-- <script src="index.js"></script> -->
</body>
</html>
@use '@shawnsandy/first-paint/src/styles/critical.scss';
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>title</title>
<meta name="description" content="title" />
<meta name="author" content="author" />
<!-- load the critical styles inline -->
{% set css %} {% include "src/css/critical.css" %} {% endset %}
<!-- feed it through our cssmin filter to minify -->
<style>
{{ css | cssmin | safe }}
</style>
<link rel="stylesheet" href="/css/dashboard.css" />
</head>
<body>
<section role="region" aria-label="dashboard" data-dashboard>
<section data-sidebar>
<nav
data-sidebar-nav
id="sidebar"
role="navigation"
aria-label="Main navigation"
data-nav
>
<section role="region" aria-label="dashboard-nav">
<ul>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Blog</a></li>
</ul>
</section>
<section data-show-mobile role="region" aria-label="Close nav">
<hr />
<a href="#" data-sidebar-button>
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"
/>
</svg>
</span>
</a>
</section>
</nav>
</section>
<main>
<nav data-mobile role="navigation" aria-label="Main navigation">
<section>
<section data-show-mobile>
<a
role="button"
aria-label="Navigation button"
href="#sidebar"
data-sidebar-button
>
<small>
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z" />
</svg>
</span>
</small>
</a>
</section>
<section data-brand="">
<h1>
<a href="/" aria-label="Site logo">
<img
data-show-desktop
data-brand
src="/img/fp.svg"
alt=""
/><span aria-label="logo text" data-show-desktop
>FirstPaint</span
>
</a>
</h1>
</section>
</section>
</nav>
<header>
<section role="banner-">
<div>
<!-- <img src="img/fp.svg" alt="" /> -->
<h2>Dashboard Page</h2>
<hr />
<p>
<span
>First Paint is lightweight easy to use CSS/SCSS starter
library for quickly scaffolding/building modern, mobile
friendly websites.</span
>
</p>
<p>
<a
href="#"
role="button"
aria-label="Add word, cta action, to your button title"
>
<span>Get Started</span></a
>
</p>
<hr />
</div>
</section>
</header>
<section>
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ad,
nostrum hic, repudiandae amet perferendis nemo debitis harum quia
magni numquam eius! At corrupti dignissimos, temporibus veniam eos
aperiam nobis corporis?
</p>
</section>
</main>
</section>
<!-- <script src="index.js"></script> -->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ settings.title }} | {{ title }}</title>
<meta name="description" content="{{ settings.description }}" />
<meta name="author" content="{{ settings.author.name }}" />
<!-- load the critical styles inline -->
{% set css %} {% include "src/css/critical.css" %} {% endset %}
<!-- feed it through our cssmin filter to minify -->
<style>
{{ css | cssmin | safe }}
</style>
<link rel="stylesheet" href="/css/dashboard.css" />
</head>
<body>
<section role="region" aria-label="Dashboard application" data-dashboard>
<section data-sidebar>{% include "partials/nav-sidebar.njk" %}</section>
<main>
<nav data-mobile role="navigation" aria-label="Main navigation">
<section>
<section data-show-mobile>
<a
role="button"
aria-label="Navigation button"
href="#sidebar"
data-sidebar-button
>
<small>
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z" />
</svg>
</span>
</small>
</a>
</section>
<section data-brand="">
<h1>
<a href="/" aria-label="Site logo">
<span aria-label="logo text">{{ settings.title }}</span>
</a>
</h1>
</section>
</section>
</nav>
<header>
<section role="banner-">
<div>
<!-- <img src="img/fp.svg" alt="" /> -->
<h2>{{ title }}</h2>
<hr />
</div>
</section>
</header>
<section role="region" aria-label="Main content">
{{ content | safe }}
</section>
</main>
</section>
<!-- <script src="index.js"></script> -->
</body>
</html>
@use '@shawnsandy/first-paint/src/styles/dashboard.scss';
[data-dashboard] main {
width: 100%;
padding: 1rem;
}
[data-sidebar] strong a {
font-size: 1.1rem;
}
@use '@shawnsandy/first-paint/src/components.scss';
@include components.button-links();
@include components.form-elements();
@include components.header-addBorders();
@include components.elements-pre();
a[role=button]>em {
filter: contrast(1.15);
}
header>section[role=banner] {
@media (min-width: 980px) {
max-width: 70%;
}
}
strong {
font-weight: 500;
}
[aria-label=feature] {
ul {
margin-left: .9rem;
list-style: disc;
margin-bottom: 1rem;
li+li {
margin-top: .5rem;
}
}
blockquote {
padding: 3rem 0;
}
}
nav {
@media (min-width: 980px) {
//align-items: center;
}
}
eleventyConfig.addFilter("cssmin", function (code) {
return new CleanCSS({}).minify(code).styles
})
require('dotenv').config()
module.exports = {
hello: process.env.HELLO || 'Hello not set, but hi, anyway 👋',
node_env: process.env.NODE_ENV || 'development',
site_map_url: process.env.SITE_MAP_URL || 'https//site.com',
contact_email: process.env.CONTACT_EMAIL || 'site@amce.inc',
contact_success: process.env.CONTACT_SUCCESS || '/thank-you',
form_provider: process.env.FORM_PROVIDER || null,
url: process.env.URL || null,
developer_mode: process.env.DEVELOPER_MODE || true,
recaptcha_key: process.env.RECAPTCHA_KEY || null,
repository: process.env.REPOSITORY_URL || 'https://github.com/shawn-sandy/shawnsandy-dev'
}
{# grab/convert icons here https://favicon.io/favicon-converter/ #}
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png"/>
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png"/>
<link rel="manifest" href="/favicons/site.webmanifest"/>
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5"/>
<meta name="msapplication-TileColor" content="#da532c"/>
<meta name="theme-color" content="#ffffff"/>
{%- macro featuring(tag = 'posts', limit = 3) -%}
{%- set feature =
hlp.11ty.take(collections[tag], limit) -%}
<!-- {{ feature | length | log }} -->
<section>
<div role="list">
{%- for item in feature %}
<div role="listitem">
<h3>
<i class="fad fa-atom-alt"></i>
{{ item.data.title }}
</h3>
<p>
{% if item.data.summary.length -%}
{{ item.data.summary |
truncate(250) }}
{% else %}
{{ hlp.11ty.noHtml(item.templateContent) |
truncate(50) }}
{% endif -%}
</p>
</div>
{%- endfor %}
</div>
</section>
<hr/>
{%- endmacro -%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ settings.title }}</title>
<meta name="description" content="title" />
<meta name="author" content="author" />
<script
src="https://kit.fontawesome.com/e2ffdf4c70.js"
crossorigin="anonymous"
></script>
<!-- load the critical styles inline -->
{% set css %} {% include "src/css/cover-page.css" %} {% endset %}
<!-- feed it through our cssmin filter to minify -->
<style>
{{ css | cssmin | safe }}
</style>
</head>
<body>
<div data-cover>
{% include 'partials/nav.njk' %}
<header>
<section role="banner">
<div>
<!-- <img src="img/fp.svg" alt="" /> -->
<h2>{{ settings.subtitle }}</h2>
<p>
<span>{{ settings.description }}</span>
</p>
<p>
<a href="/main" role="button" aria-label="Go to the main page">
<em>Get Started</em></a
>
</p>
</div>
</section>
</header>
<footer role="contentinfo">
<div>
<p>
Copyright &copy; {{ hlp.11ty.year() }} {{ settings.author.name }}
All rights reserved
</p>
</div>
</footer>
</div>
<!-- <script src="index.js"></script> -->
</body>
</html>

FP-Pages is a minimalist UI/Frontend Toolkit for building performance driven, accessibility first websites. Powered by modern Serverless, Javascript, API's and Markdown stack, with built in Netlify, Cloudflare pages and Azure coming soon integration for easy server(less) deploys. A lightweight classless 10kb/3kb(gzip) CSS/SCSS library for style and layout FirstPaint and Eleventy a simple and easy to use next-gen static site generator.

// @ts-check
const Jimp = require('jimp')
const fs = require('fs')
const img = (imgs = 'google-security-check.jpg', options = {}) => {
const width = options.width || 1280
const height = options.width || Jimp.AUTO
const srcDir = options.srcDir || './assets/img/'
const outputDir = options.outputDir || './www/images/'
const quality = options.quality || 80
const imageSrc = `${srcDir}${imgs}`
const imagePath = `${outputDir}${imgs}`
const force = options.force || false
const outputCache = options.cacheDir || './.cache/images/'
try {
if (!fs.existsSync(`${outputCache}${imgs}`) && fs.existsSync(imageSrc) || force) {
console.log('processing image')
Jimp.read(`${srcDir}${imgs}`, (err, lenna) => {
if (err) throw err
lenna
.resize(width, height)
.quality(quality)
.write(`${outputDir}${imgs}`)
.write(`${outputCache}${imgs}`)
})
} else {
console.log(`Seems image already exist ${imagePath}`)
}
} catch (error) {
console.info(error)
}
return `/images/${imgs}`
}
module.exports = {
img
}
{% extends "base.njk" %}
{% block cover %}
{% include "partials/hero.njk" %}
{% endblock %}
{% block content %}
{% import "_macros/collections/featured.njk" as feature with context %}
{{ feature.featured() }}
<hr/>
{{ super() }}
{% endblock %}
---
layout: landing.njk
title: "Cover Page"
tags: "page"
eleventyExcludeFromCollections": true
feature: ["interaction", "experience", "engineering"]
scripts: []
---
<section>{%- include "./partials/quotes.html" %}</section>
<!-- -->
{% import "macros/features.njk" as feature with context %}
<section>{{ feature.category('experience') }}</section>
<hr />
<section>{{ feature.category('interaction') }}</section>
<hr />
<section>{{ feature.category('engineering') }}</section>
<hr />
<section>{{ feature.category() }}</section>
<title>{{ settings.title }}</title>
<meta name="description" content="{{ settings.description }}" />
<meta name="author" content="{{ settings.author.name }}" />
<nav data-mobile aria-label="Main navigation">
<section>
<section data-show-mobile>
<a
role="button"
aria-label="Navigation button"
href="#sidebar"
data-sidebar-button
>
<small>
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z" />
</svg>
</span>
</small>
</a>
</section>
<section data-brand>
<h1>
{% include 'partials/brand.njk' %}
</h1>
</section>
</section>
{% set navPages = collections.all | eleventyNavigation %}
<section id="sidebar">
<ul>
{%- for entry in navPages %}
<li>
<a href="{{ entry.url | url }}"{% if entry.url == page.url %} data-current="current item"{% endif %}>{{ entry.title }}</a>
</li>
{%- endfor %}
<li>
<div data-show-mobile>
<a href="#">
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"
/>
</svg>
</span>
</a>
</div>
</li>
</ul>
</section>
</nav>
<nav data-mobile aria-label="Main navigation">
<section>
<section data-show-mobile>
<a
role="button"
aria-label="Navigation button"
href="#sidebar"
data-sidebar-button
>
<small>
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z" />
</svg>
</span>
</small>
</a>
</section>
<section data-brand>
<h1>
{% include 'partials/brand.njk' %}
</h1>
</section>
</section>
{% set navPages = collections.all | eleventyNavigation %}
<section id="sidebar">
<ul>
{%- for entry in navPages %}
<li>
<a href="{{ entry.url | url }}"{% if entry.url == page.url %} data-current="current item"{% endif %}>{{ entry.title }}</a>
</li>
{%- endfor %}
<li>
<div data-show-mobile>
<a href="#">
<span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"
/>
</svg>
</span>
</a>
</div>
</li>
</ul>
</section>
</nav>
[build]
publish = "www"
command = "npm run build"
[template.environment]
NODE_ENV = "NODE environment"
SITE_MAP_URL = "https://www.xxx.com/sitemap.xml"
CONTACT_EMAIL = "Contact email"
FORM_PROVIDER = "Contact form provider (netlify/webforms)"
CONTACT_SUCCESS = "/thank-you (page)"
<meta property="og:title" content="{{ title or settings.title }}"/>
<meta property="og:description" content="{{ subtitle or settings.description }}"/>
<meta property="og:type" content="{{ type or 'website' }}"/>
<meta property="og:url" content="{{ settings.url }}{{ page.url }}"/>
<meta property="og:image" content="{{ settings.url }}{{ coverImage or '/images/og-cover.png' }}"/>
<meta property="twitter:card" content="summary_large_image"/>
<meta property="twitter:image" content="{{ settings.url }}{{ coverImage or '/images/og-cover.png' }}"/>
<meta property="twitter:site" content="{{ settings.author.twitter }}"/>
---
permalink: "/js/repcatcha.js"
eleventyExcludeFromCollections: true
---
eleventyExcludeFromCollections: true
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY_HERE"></script>
<script>
grecaptcha.ready(function () {
grecaptcha
.execute("YOUR_SITE_KEY_HERE", {
action: "contact",
})
.then(function (token) {
recaptchaResponse.value = token;
});
});
</script>
{
"title": "ShawnSandy.dev",
"subtitle": "Design, Code, Performance, Usability, Accessibility, Inclusion",
"url": "https://shawnsandy.dev",
"description": "Design First; frontend engineer, advocate, Dad, Husband, and content creator that's crazy about design, performance, usability, accessibility empowerment, diversity, inclusion, and making the world a better place.",
"logo_url": "/images/nav-logo.svg",
"feed": {
"subtitle": "A UI toolkit for creating and managing design/style systems, pattern libraries, style-guides, etc",
"filename": "feed.xml",
"path": "/feed/feed.xml",
"id": "https://shawnsandy.dev/"
},
"author": {
"name": "Shawn Sandy",
"email": "shawnsandy@shawnsandy.dev",
"twitter": "@shawnsandy"
},
"styles": [],
"scripts": [
"./js/min/index.min.js"
]
}
// @ts-check
const sharp = require('sharp')
const fs = require('fs')
const getName = (img) => {
const _name = img.split('.')
const imgName = _name[0].replace('/', '-')
return imgName
}
/**
*
* @param {*} imgs
* @param {*} options
* @returns
*/
const resize = (imgs = [], options = {}) => {
// console.log(options)
const format = options.format || 'jpg'
const srcDir = options.srcDir || './assets/img/'
const outputDir = options.outputDir || './www/images/'
const force = options.force || false
if (!Array.isArray(imgs) || imgs.length < 0) {
console.error('Image error (please ensure img is and array)')
return
}
imgs.map((img, index) => {
// console.log(index)
const _name = img.split('.')
// const imgFormat = img.split('.').pop()
const getFormat = img.split('.').pop()
if (!options.format) { options.format = getFormat }
const imgName = options.name || _name[0]
const src = `${srcDir}${img}`
const suffix = options.suffix || ''
const image = `${outputDir}${imgName}${suffix}.${options.format}`
if (!fs.existsSync(src)) {
// console.log(image)
console.error('Image not found', src)
return null
}
if (!fs.existsSync(image) || force) {
sharp(`${src}`)
.toFormat(format)
.resize({ width: options.width || 1200, height: options.height || null })
.toFile(`${image}`, (err, info) => {
if (err) console.log('Error', err)
if (info) console.warn('Image created', `${image}`)
})
}
return true
})
}
/**
*
* @param {*} imgs
* @param {*} options
* @returns
*/
const img = (imgs = ['google-security-check.jpg'], options = {}) => {
if (imgs.length > 0) {
resize([imgs[0]], options)
const getFormat = imgs[0].split('.').pop()
if (!options.format) { options.format = getFormat }
const imgName = getName(imgs[0])
return `/${options.imgDir || 'images'}/${imgName}${options.suffix || ''}.${options.format}`
}
return null
}
/**
*
* @param {*} imgs
* @param {*} options
* @returns
*/
const imgSrc = (imgs = 'google-security-check.jpg', options = {}) => {
return `<img loading="lazy" src="${img(imgs, options)}" alt="${options.name}"/>`
}
/**
*
* @param {*} imgs
* @returns
*/
const coverImage = (imgs = ['og-cover.png']) => {
return img(imgs, { width: 800, height: 500, format: 'webp', suffix: '-cover', force: true })
}
module.exports = {
img,
imgSrc,
resize,
coverImage
}
// @use replace @import with @use
// as - defines the namespace for your imports
// with - override default variables
@use "@shawnsandy/first-paint/src/styles/main.scss";
<textarea role="presentation" name="" id="" cols="30">
<h3>Subtitle</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis asperiores
doloremque magnam mollitia fugiat alias explicabo eum! Dolorem obcaecati
laudantium commodi quis, facere aspernatur sapiente, molestias quidem
molestiae repellat adipisci?
</p>
</textarea
>
<form action="https://api.web3forms.com/submit" method="POST">
<input
type="hidden"
name="apikey"
value="d1ee3a5e-b148-4264-a8b2-b0e68c6b39c1"
/>
<div>
<label for="name"> <em>Name</em></label>
<input
type="text"
name="name"
id="name"
autocomplete="name"
placeholder="Your name"
title="Please enter your name"
required
/>
</div>
<div>
<label for="email"> <em>Email</em> </label>
<input
type="email"
name="email"
id="email"
autocomplete="email"
placeholder="Your email address"
title="The domain portion of the email address is invalid (the portion after the @)."
required
/>
</div>
<div>
<label for="message"> <em>Message</em> </label>
<textarea
name="message"
id="message"
placeholder="Write your message here"
rows="7"
required
></textarea>
</div>
<input type="hidden" name="redirect" value="{{ env.contact_success }}" />
<input type="hidden" name="recaptcha_response" id="recaptchaResponse" />
<button type="submit">Submit Form</button>
</form>
<!-- recaptcha form -->
<script src="https://www.google.com/recaptcha/api.js?render={{
env.recaptcha_key
}}"></script>
<script>
grecaptcha.ready(function () {
grecaptcha
.execute("{{ env.recaptcha_key }}", {
action: "contact",
})
.then(function (token) {
recaptchaResponse.value = token;
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment