Skip to content

Instantly share code, notes, and snippets.

View Nooshu's full-sized avatar

Matt Hobbs Nooshu

View GitHub Profile
@Nooshu
Nooshu / contact.js
Created March 9, 2026 19:49
This is the code that runs on my Cloudflare worker to allow sending of emails from my website contact form to my choosen email address.
import { escapeHtml } from '../../_helpers/escape-html.js';
export const onRequestPost = async ({ request, env }) => {
try {
// Accept standard form submissions
const contentType = request.headers.get('content-type') || '';
if (!contentType.includes('application/x-www-form-urlencoded') && !contentType.includes('multipart/form-data')) {
return new Response(JSON.stringify({ error: 'Unsupported content type' }), {
status: 415,
headers: { 'content-type': 'application/json' },
@Nooshu
Nooshu / accessible-form.html
Created March 8, 2026 23:13
The contact form code I use in conjunction with a Cloudflare Worker on my 11ty blog.
<form id="fs-frm" action="/api/contact" method="POST" aria-labelledby="page-title" novalidate>
<div id="form-error-summary" class="form-error-summary" role="alert" tabindex="-1" hidden></div>
<div id="form-status" class="form-status" role="status"></div>
<div class="spm" aria-hidden="true">
<input type="checkbox" name="_akjhaskjdkjhakjshdadjknjnkdsa" tabindex="-1" autocomplete="off" />
</div>
<input type="hidden" name="_redirect" value="/contact/thanks/" />
<input type="hidden" name="_append" value="false" />
<input type="hidden" name="_email.subject" value="New Message from Nooshu.com" />
<fieldset>
@Nooshu
Nooshu / webperf.js
Created March 4, 2026 23:12
The Web performance snippet I use to populate how quick a page loads on my blog, now fixed the iOS 0 milliseconds issue.
(function() {
/* check to see if the browser is modern enough to support the
PerformanceNavigationTiming API */
if (!window.performance?.getEntriesByType) {
console.warn('Performance API not supported');
return;
}
function showLoadTime() {
const entries = performance.getEntriesByType('navigation');
@Nooshu
Nooshu / build-events.js
Created February 20, 2026 13:29
The build events file that I use with my 11ty build. It contains extensive logging that output to the Cloudflare pages build log.
import env from '../_data/env.js';
import { clearCssBuildCache } from '../_helpers/css-manipulation.js';
import { generatePreloadHeaders } from '../_helpers/header-generator.js';
import { compressHtmlFiles } from '../_helpers/html-compression.js';
import { compressJavaScriptFiles } from '../_helpers/js-compression.js';
import { minifyJavaScriptFiles } from '../_helpers/js-minify.js';
/**
* Register eleventy.before and eleventy.after handlers.
* Only registered when !env.isLocal (production/preview)
@Nooshu
Nooshu / [[path]].js
Created February 20, 2026 13:01
The Cloudflare function that does the content negotiation for the HTML that has been compressed to Brotli 11.
/**
* Catch-all Pages Function for HTML document content negotiation.
* Serves pre-compressed Brotli 11 .br files when client sends Accept-Encoding: br,
* otherwise passes through to static assets (uncompressed HTML).
* Only runs for GET and HEAD; POST /api/contact is handled by functions/api/contact.js.
*/
async function handleHtmlWithBrotli(request, env) {
const url = new URL(request.url);
const pathname = url.pathname;
@Nooshu
Nooshu / html-compression.js
Created February 20, 2026 12:55
The HTML compression postbuild file for compressing the HTML to Brotli 11. (contains logging for Cloudflare pages builds)
import fs from 'fs';
import path from 'path';
import { brotliCompress, BROTLI_LEVEL } from './compression.js';
/**
* Recursively find all .html files in a directory.
* @param {string} dir - Directory to search
* @param {string[]} [acc=[]] - Accumulator for results
* @returns {string[]} Relative paths to .html files
@Nooshu
Nooshu / compression.js
Created February 20, 2026 12:52
The core compression code I use on my blog for compressing HTML (and other text assets) to Brotli level 11.
import { brotliCompressSync } from 'zlib';
/** Default Brotli compression level (0–11). Level 11 gives best ratio, slowest. */
export const BROTLI_LEVEL = 11;
/**
* Compress a buffer with Brotli.
* @param {Buffer | Uint8Array | string} input - Input buffer, TypedArray, or string (UTF-8)
* @param {number} [level=BROTLI_LEVEL] - Brotli level 0–11
* @returns {Buffer} Compressed buffer
@Nooshu
Nooshu / header-generator.js
Created September 1, 2025 22:25
Header generator file stripped of all comments used in my "Asset fingerprinting and the preload header in 11ty" blog post
import fs from 'fs';
import path from 'path';
export function generatePreloadHeaders() {
console.log('🔗 Generating preload headers for CSS files...');
const cssDir = path.join('./_site', 'css');
if (!fs.existsSync(cssDir)) {
console.log('CSS directory not found, skipping header generation');
return;
@Nooshu
Nooshu / CSP-11ty-dev.js
Last active February 9, 2025 20:46
This is the code I used to tweak my CSP response header on my local development environment.
// This is my site's Content Security Policy.
// Modify this CSP, don't just copy / paste it! It will break your site!
// You can also use `var` and `let` depending on your coding syntax, they all work
const CSP = `
base-uri 'self';
child-src 'self';
connect-src 'none';
default-src 'none';
img-src 'self' https://v1.indieweb-avatar.11ty.dev/;
font-src 'self';
@Nooshu
Nooshu / feed.txt.njk
Created January 28, 2025 23:18
The Nunjucks template I use to output my plaintext RSS feed in 11ty 3.0.0
---
permalink: feed/feed.txt
eleventyComputed:
layout: null
---
# {{ metadata.title }} - {{ metadata.author.name }} - {{ metadata.description }}
## {{ metadata.fulldescription }}
URL: {{ metadata.url }}
{% for post in collections.posts | reverse -%}