Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion _11ty/blurry-placeholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ function getBitmapDimensions_(imgWidth, imgHeight) {
}

module.exports = async function (src) {
const filename = "_site/" + src;
let filename = "_site/" + src;
if (!await exists(filename) && src.startsWith("/assets/")) {
filename = "src" + src;
}
const cachedName = filename + ".blurred";
if (await exists(cachedName)) {
return readFile(cachedName, {
Expand Down
70 changes: 44 additions & 26 deletions _11ty/img-dim.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

const { JSDOM } = require("jsdom");
const { promisify } = require("util");
const fs = require("fs");
const sizeOf = promisify(require("image-size"));
const blurryPlaceholder = require("./blurry-placeholder");
const srcset = require("./srcset");
Expand Down Expand Up @@ -54,7 +55,11 @@ const processImage = async (img, outputPath) => {
}
let dimensions;
try {
dimensions = await sizeOf("_site/" + src);
let inputPath = "_site/" + src;
if (!fs.existsSync(inputPath) && src.startsWith("/assets/")) {
inputPath = "src" + src;
}
dimensions = await sizeOf(inputPath);
} catch (e) {
console.warn(e.message, src);
return;
Expand Down Expand Up @@ -93,39 +98,52 @@ const processImage = async (img, outputPath) => {
if (img.tagName == "IMG") {
img.setAttribute("decoding", "async");
img.setAttribute("loading", "lazy");
img.setAttribute(
"style",
`background-size:cover;` +
`background-image:url("${await blurryPlaceholder(src)}")`
);
try {
img.setAttribute(
"style",
`background-size:cover;` +
`background-image:url("${await blurryPlaceholder(src)}")`
);
} catch (e) {
console.warn(`[img-dim] blurryPlaceholder failed for ${src}: ${e.message}`);
}
const doc = img.ownerDocument;
const picture = doc.createElement("picture");
const avif = doc.createElement("source");
const webp = doc.createElement("source");
const jpeg = doc.createElement("source");
const fallback = await setSrcset(jpeg, src, fallbackType);
if (!fallback) {
try {
const fallback = await setSrcset(jpeg, src, fallbackType);
if (!fallback) {
return;
}
const avifFallback = await setSrcset(avif, src, "avif");
if (avifFallback) {
avif.setAttribute("type", "image/avif");
picture.appendChild(avif);
}
const webpFallback = await setSrcset(webp, src, "webp");
if (webpFallback) {
webp.setAttribute("type", "image/webp");
picture.appendChild(webp);
}
jpeg.setAttribute("type", `image/${fallbackType}`);
picture.appendChild(jpeg);
img.parentElement.replaceChild(picture, img);
picture.appendChild(img);
img.setAttribute("src", fallback);
} catch (e) {
console.warn(`[img-dim] setSrcset failed for ${src}: ${e.message}`);
return;
}
const avifFallback = await setSrcset(avif, src, "avif");
if (avifFallback) {
avif.setAttribute("type", "image/avif");
picture.appendChild(avif);
}
const webpFallback = await setSrcset(webp, src, "webp");
if (webpFallback) {
webp.setAttribute("type", "image/webp");
picture.appendChild(webp);
}
jpeg.setAttribute("type", `image/${fallbackType}`);
picture.appendChild(jpeg);
img.parentElement.replaceChild(picture, img);
picture.appendChild(img);
img.setAttribute("src", fallback);
} else if (!img.getAttribute("srcset")) {
const fallback = await setSrcset(img, src, fallbackType);
if (fallback) {
img.setAttribute("src", fallback);
try {
const fallback = await setSrcset(img, src, fallbackType);
if (fallback) {
img.setAttribute("src", fallback);
}
} catch (e) {
console.warn(`[img-dim] setSrcset (fallback) failed for ${src}: ${e.message}`);
}
}
};
Expand Down
8 changes: 7 additions & 1 deletion _11ty/srcset.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ async function resize(filename, width, format) {
if (await exists("_site" + out)) {
return out;
}
await sharp("_site" + filename)

let inputPath = "_site" + filename;
if (!await exists(inputPath) && filename.startsWith("/assets/")) {
inputPath = "src" + filename;
}

await sharp(inputPath)
.rotate() // Manifest rotation from metadata
.resize(width)
[format]({
Expand Down
23 changes: 19 additions & 4 deletions src/pages/content-playing-field.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Driver of Change (DoC) model for Si

### James

![James's avatar](images/FDBD38E0-FAA0-4A10-96DF-7B547D168F73-300x300.jpeg)
![James's avatar](/assets/images/FDBD38E0-FAA0-4A10-96DF-7B547D168F73-300x300.jpeg)

30something male from UK, 2 kids (boy 7, girl 2), married, web developer for a small company, mostly remote. More of a night owl than a morning person. 

Expand All @@ -53,7 +53,7 @@ James values giving back to society, special time with his family and learning n

### Antonia

![Antonia's avatar](images/4F1CD6A6-5576-4FEF-BBB5-EEDBB8DEC280-300x300.jpeg)
![Antonia's avatar](/assets/images/4F1CD6A6-5576-4FEF-BBB5-EEDBB8DEC280-300x300.jpeg)

20something female from US, single with no kids, freelance designer, works from home or co-working spaces. Generally up early except weekends. 

Expand Down Expand Up @@ -88,8 +88,23 @@ ADDE Examples for Si

### Assets

![Mini Coops in house style duotone](images/3B7A5BB9-EB74-4B3C-8B57-579A39F06FC5-1024x1024.jpeg)
![Mini Coops in house style duotone](/assets/images/3B7A5BB9-EB74-4B3C-8B57-579A39F06FC5-1024x1024.jpeg)

## Content Tilt 👓

\[**TODO**: _Competitor analysis to identify any unique angles from the side project community_\]
The side project community is bustling, but often polarized:

* **The Hustlers 💸**: "Ship fast," "MRR," and "Sleep when you're dead." Inspiring, but often leads to burnout and feelings of inadequacy for those with limited time.
* **The Techies 💻**: Deep dives into code, frameworks, and "How to build X." Essential for *building*, but lacks the structural advice to *finish* or stay motivated.
* **The Makers 🎨**: Focused on the craft and design. Often missing the pragmatic project management needed to ship.

**My unique angle:**
**Sustainable Side Projects for the Rest of Us.**

This publication sits at the intersection of **Agile Project Management** and **Personal Well-being**. It treats a side project not as a lottery ticket, but as a fulfilling creative outlet that must coexist with a career and family.

I apply professional leadership and delivery methodologies (usually reserved for enterprise teams) to the chaotic, emotional world of the solo creator.

* **Less** "How to make $10k/month" → **More** "How to find 2 hours a week without guilt."
* **Less** "Best React Framework" → **More** "Best framework for decision making."
* **Less** "Success Stories" → **More** "Honest Retrospectives on Failure."