Merge branch 'staging' into the-bitter-lesson

This commit is contained in:
Dave Kerr
2025-03-28 10:03:58 +00:00
committed by GitHub
21 changed files with 1508 additions and 133 deletions

0
.github/website/backup/ideas.md vendored Normal file
View File

189
.github/website/backup/index2.html vendored Normal file
View File

@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hacker Laws</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- Bootstrap Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" />
<style>
/* Soft pastel parchment background */
body {
background-color: #fdf6e3;
color: #333;
padding-top: 70px; /* to account for sticky navbar */
}
/* Navbar customization */
.navbar-custom {
background-color: #ffffff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Header styling */
header h1 {
font-size: 2.5rem;
font-weight: bold;
}
header p.lead {
font-size: 1.25rem;
color: #555;
}
/* Law section container */
.law-section {
margin-bottom: 2rem;
padding: 1.5rem;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
/* Social sharing icons */
.social-sharing a {
margin-right: 0.75rem;
font-size: 1.2rem;
color: #555;
text-decoration: none;
}
.social-sharing a:hover {
color: #000;
}
/* Back to top link styling */
.back-to-top a {
font-size: 0.9rem;
text-decoration: none;
color: #007bff;
}
.back-to-top a:hover {
text-decoration: underline;
}
</style>
</head>
<body id="top">
<!-- Sticky Navbar -->
<nav class="navbar navbar-expand-lg navbar-custom fixed-top">
<div class="container">
<a class="navbar-brand fw-bold" href="#top">Hacker Laws</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMenu" aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navMenu">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-book"></i> Effective Shell</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-cup"></i> Sponsor</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-brain"></i> Terminal AI</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-github"></i> GitHub</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Page Header -->
<header class="container my-4">
<h1>Hacker Laws</h1>
<p class="lead">Laws, Theories, Principles and Patterns that developers will find useful.</p>
</header>
<!-- Main Content -->
<main class="container">
<!-- Introduction Section -->
<section id="introduction" class="law-section">
<h2>Introduction</h2>
<p>There are lots of laws which people discuss when talking about development. This repository is a reference and overview of some of the most common ones. Please share and submit PRs!</p>
<p><strong>Note:</strong> This repo contains an explanation of some laws, principles and patterns, but does not <em>advocate</em> for any of them. Whether they should be applied will always be a matter of debate, and greatly dependent on what you are working on.</p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top Options (choose one) -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
<!-- Alternative options:
<a href="#top">Back to Top</a>
<a href="#top">Return to Top</a>
<a href="#top">Go Up</a>
<a href="#top">Scroll Up</a>
-->
</div>
</section>
<!-- 9091 Principle (1% Rule) Section -->
<section id="9091-principle" class="law-section">
<h2>9091 Principle (1% Rule)</h2>
<p>The 90-9-1 principle suggests that within an internet community such as a wiki, 90% of participants only consume content, 9% edit or modify content and 1% of participants add content.</p>
<p>Real-world examples:</p>
<ul>
<li>A 2014 study of four digital health social networks found the top 1% created 73% of posts, the next 9% accounted for an average of ~25% and the remaining 90% accounted for an average of 2%.</li>
</ul>
<p>See Also: <a href="#the-pareto-principle-the-8020-rule">Pareto Principle</a></p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top Options -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
</div>
</section>
<!-- 9090 Rule Section -->
<section id="9090-rule" class="law-section">
<h2>9090 Rule</h2>
<p>The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.</p>
<p>This is a wry reinterpretation of the <a href="#the-pareto-principle-the-8020-rule">Pareto Principle</a> (or 80-20 rule) that highlights the real-world challenges of completing engineering work. This sentiment is also echoed in <a href="#hofstadters-law">Hofstadter's Law</a>.</p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top Options -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
</div>
</section>
<!-- Additional law sections would follow the same structure -->
</main>
<!-- Footer -->
<footer class="container text-center my-4">
<p>&copy; 2025 Hacker Laws</p>
</footer>
<!-- Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Optional: Smooth scrolling for in-page links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const targetElem = document.querySelector(this.getAttribute('href'));
if (targetElem) {
targetElem.scrollIntoView({ behavior: 'smooth' });
}
});
});
</script>
</body>
</html>

194
.github/website/backup/index3.html vendored Normal file
View File

@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hacker Laws</title>
<!-- Google Font for elegant serif fonts -->
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&display=swap" rel="stylesheet">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- Bootstrap Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" />
<style>
/* Use an elegant serif font and a clean, minimal palette */
body {
font-family: 'Libre Baskerville', Georgia, serif;
background-color: #fff;
color: #333;
padding-top: 70px; /* account for sticky navbar */
}
.container {
max-width: 800px;
}
/* Simplified Navbar */
.navbar-custom {
background-color: #fff;
border-bottom: 1px solid #e5e5e5;
}
.navbar-brand,
.nav-link {
font-weight: 700;
}
/* Centered, minimal header */
header {
text-align: center;
margin-bottom: 2rem;
}
header h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
header p.lead {
font-size: 1.25rem;
color: #555;
}
/* Law section styling: simple borders instead of shadows */
.law-section {
margin-bottom: 2rem;
padding: 1.5rem;
background-color: #fff;
border-bottom: 1px solid #e5e5e5;
}
/* Social sharing icons remain the same */
.social-sharing a {
margin-right: 0.75rem;
font-size: 1.2rem;
color: #555;
text-decoration: none;
}
.social-sharing a:hover {
color: #000;
}
/* Back to top link styling */
.back-to-top a {
font-size: 0.9rem;
text-decoration: none;
color: #007bff;
}
.back-to-top a:hover {
text-decoration: underline;
}
</style>
</head>
<body id="top">
<!-- Sticky Navbar -->
<nav class="navbar navbar-expand-lg navbar-custom fixed-top">
<div class="container">
<a class="navbar-brand" href="#top">Hacker Laws</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMenu" aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navMenu">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-book"></i> Effective Shell</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-cup"></i> Sponsor</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-brain"></i> Terminal AI</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-github"></i> GitHub</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Page Header -->
<header class="container my-4">
<h1>Hacker Laws</h1>
<p class="lead">Laws, Theories, Principles and Patterns that developers will find useful.</p>
</header>
<!-- Main Content -->
<main class="container">
<!-- Introduction Section -->
<section id="introduction" class="law-section">
<h2>Introduction</h2>
<p>There are lots of laws which people discuss when talking about development. This repository is a reference and overview of some of the most common ones. Please share and submit PRs!</p>
<p><strong>Note:</strong> This repo contains an explanation of some laws, principles and patterns, but does not <em>advocate</em> for any of them. Whether they should be applied will always be a matter of debate, and greatly dependent on what you are working on.</p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
</div>
</section>
<!-- 9091 Principle (1% Rule) Section -->
<section id="9091-principle" class="law-section">
<h2>9091 Principle (1% Rule)</h2>
<p>The 90-9-1 principle suggests that within an internet community such as a wiki, 90% of participants only consume content, 9% edit or modify content and 1% of participants add content.</p>
<p>Real-world examples:</p>
<ul>
<li>A 2014 study of four digital health social networks found the top 1% created 73% of posts, the next 9% accounted for an average of ~25% and the remaining 90% accounted for an average of 2%.</li>
</ul>
<p>See Also: <a href="#the-pareto-principle-the-8020-rule">Pareto Principle</a></p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
</div>
</section>
<!-- 9090 Rule Section -->
<section id="9090-rule" class="law-section">
<h2>9090 Rule</h2>
<p>The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.</p>
<p>This is a wry reinterpretation of the <a href="#the-pareto-principle-the-8020-rule">Pareto Principle</a> (or 80-20 rule) that highlights the real-world challenges of completing engineering work. This sentiment is also echoed in <a href="#hofstadters-law">Hofstadter's Law</a>.</p>
<!-- Social Sharing Icons -->
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Share on LinkedIn"><i class="bi bi-linkedin"></i></a>
</div>
<!-- Back to Top -->
<div class="back-to-top mt-2">
<a href="#top">↑ Top</a>
</div>
</section>
</main>
<!-- Footer -->
<footer class="container text-center my-4">
<p>&copy; 2025 Hacker Laws</p>
</footer>
<!-- Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Smooth scrolling for in-page links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const targetElem = document.querySelector(this.getAttribute('href'));
if (targetElem) {
targetElem.scrollIntoView({ behavior: 'smooth' });
}
});
});
</script>
</body>
</html>

0
.github/website/backup/index4.html vendored Normal file
View File

1
.github/website/build/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*

161
.github/website/generate.py vendored Normal file
View File

@@ -0,0 +1,161 @@
"""Generate the Hacker Laws website from the Hacker Laws README"""
import argparse
import os
import shutil
from jinja2 import Environment, FileSystemLoader
import markdown
from bs4 import BeautifulSoup
def bisect_text(content: str, bisect_line: str) -> tuple[str, str]:
lines = content.splitlines()
head = []
tail = []
found = False
for line in lines:
if found is False and line == bisect_line:
found = True
continue
if found:
tail.append(line)
else:
head.append(line)
return ("\n".join(head), "\n".join(tail))
def load_template():
"""Load Jinja2 template from the specified directory."""
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
return env.get_template(TEMPLATE_FILE)
def prepare_markdown(path: str) -> str:
"""
Pre-process the README markdown by removing content we will not show in
the final website.
"""
# Load the markdown content.
with open(path, "r", encoding="utf-8") as f:
content = f.read()
return content
def parse_markdown(markdown_content: str):
(_, remains) = bisect_text(markdown_content, "---")
(links, remains) = bisect_text(remains, "---")
(_, content) = bisect_text(remains, "<!-- vim-markdown-toc -->")
md = markdown.Markdown(extensions=['toc'])
links = md.convert(links)
print(f"links: {links}")
md.convert(content)
toc = md.toc
markdown_sections = content.split("\n#") # Split by Markdown headings
sections = []
laws = []
for markdown_section in markdown_sections:
if markdown_section.strip():
lines = markdown_section.split("\n", 1)
title = lines[0].strip("# ").strip()
content = md.convert(lines[1] if len(lines) > 1 else "")
full_content = md.convert(markdown_section)
id = title.lower().replace(" ", "-")
laws.append({"title": title, "content": content, "id": id})
sections.append({
"title": title,
"content": content,
"id": id,
"full_content": full_content
})
return (links, toc, sections)
def extract_static_files(html_content, output_dir):
"""
Extract linked CSS, JS, and image files and copy them to the output
directory.
"""
soup = BeautifulSoup(html_content, "html.parser")
files_to_copy = []
# Extract <link> stylesheets
for link in soup.find_all("link", href=True):
href = link["href"]
if not href.startswith(("http", "//")): # Ignore external links
files_to_copy.append(href)
# Extract <script> files
for script in soup.find_all("script", src=True):
src = script["src"]
if not src.startswith(("http", "//")):
files_to_copy.append(src)
# Extract <img> files
for img in soup.find_all("img", src=True):
src = img["src"]
if not src.startswith(("http", "//")):
files_to_copy.append(src)
# Copy files to the output directory
for file_path in files_to_copy:
src_path = os.path.join(TEMPLATE_DIR, file_path)
dest_path = os.path.join(output_dir, file_path)
if os.path.exists(src_path): # Ensure file exists before copying
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
shutil.copy2(src_path, dest_path)
print(f"📂 Copied: {src_path}{dest_path}")
else:
print(f"⚠️ Warning: Missing file {src_path} (skipping)")
return files_to_copy
def generate_site(markdown_content: str, output_dir: str):
"""Generate the static HTML file from Markdown and Jinja2 template."""
template = load_template()
(links, toc, sections) = parse_markdown(markdown_content)
# Ensure output directory exists
os.makedirs(output_dir, exist_ok=True)
# Render HTML
html_output = template.render(links=links, toc=toc, sections=sections)
# Save HTML to output directory
output_file = os.path.join(output_dir, "index.html")
with open(output_file, "w", encoding="utf-8") as f:
f.write(html_output)
print(f"✅ Static site generated: {output_file}")
# Copy static files (CSS, JS, images)
extract_static_files(html_output, output_dir)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate a static site from Markdown.")
parser.add_argument("-o", "--output-dir", default="build", help="Directory to save the generated site.")
args = parser.parse_args()
# Read environment variables with defaults
TEMPLATE_FILE = os.getenv("TEMPLATE_FILE", "template.html")
TEMPLATE_DIR = os.getenv("TEMPLATE_DIR", ".")
template_path = f"{TEMPLATE_DIR}/{TEMPLATE_FILE}"
markdown_path = os.getenv("MARKDOWN_FILE", "laws.md")
output_dir = args.output_dir
print(f"📝 Loading template from: {template_path}")
print(f"📖 Loading markdown from: {markdown_path}")
print(f"💾 Outputting files to: {output_dir}")
# First, extract that markdown that we want to process.
markdown_content = prepare_markdown(markdown_path)
# Generate the site from the markdown.
generate_site(markdown_content, args.output_dir)

38
.github/website/makefile vendored Normal file
View File

@@ -0,0 +1,38 @@
SHELL := /bin/bash
TEMPLATE_DIR=src
TEMPLATE_FILE=index.html.jinja
MARKDOWN_FILE=../../README.md
OUTPUT_FILE=build/index.html
default: help
.PHONY: help
help: # Show help for each of the Makefile recipes.
@grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done
.PHONY: install
install: # 📦 install dependencies
@echo "📦 Installing dependencies..."
pip install -r requirements.txt
.PHONY: build
build: #🔨 building static site
@echo "🔨 Building static site..."
cp -rf ../../images ./build
TEMPLATE_FILE=$(TEMPLATE_FILE) MARKDOWN_FILE=$(MARKDOWN_FILE) OUTPUT_FILE=$(OUTPUT_FILE) TEMPLATE_DIR=$(TEMPLATE_DIR) \
python generate.py
.PHONY: serve
serve: # 🚀 start local server
@echo "🚀 Starting local server at http://localhost:8000..."
python3 -m http.server 8000
.PHONY: watch
watch: build # 👀 Watch for changes...
@echo "👀 Watching for changes..."
watchmedo shell-command --patterns="$(MARKDOWN_FILE);*.py;src/*" --command="make build" .
.PHONY: clean
clean: #🧹 Clean up generated files
@echo "🧹 Cleaning up generated files..."
rm -f $(OUTPUT)

4
.github/website/requirements.txt vendored Normal file
View File

@@ -0,0 +1,4 @@
markdown
jinja2
watchdog
beautifulsoup4

3
.github/website/src/favicon.svg vendored Normal file
View File

@@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 0C7.16 0 0 7.16 0 16C0 23.08 4.58 29.06 10.94 31.18C11.74 31.32 12.04 30.84 12.04 30.42C12.04 30.04 12.02 28.78 12.02 27.44C8 28.18 6.96 26.46 6.64 25.56C6.46 25.1 5.68 23.68 5 23.3C4.44 23 3.64 22.26 4.98 22.24C6.24 22.22 7.14 23.4 7.44 23.88C8.88 26.3 11.18 25.62 12.1 25.2C12.24 24.16 12.66 23.46 13.12 23.06C9.56 22.66 5.84 21.28 5.84 15.16C5.84 13.42 6.46 11.98 7.48 10.86C7.32 10.46 6.76 8.82 7.64 6.62C7.64 6.62 8.98 6.2 12.04 8.26C13.32 7.9 14.68 7.72 16.04 7.72C17.4 7.72 18.76 7.9 20.04 8.26C23.1 6.18 24.44 6.62 24.44 6.62C25.32 8.82 24.76 10.46 24.6 10.86C25.62 11.98 26.24 13.4 26.24 15.16C26.24 21.3 22.5 22.66 18.94 23.06C19.52 23.56 20.02 24.52 20.02 26.02C20.02 28.16 20 29.88 20 30.42C20 30.84 20.3 31.34 21.1 31.18C27.42 29.06 32 23.06 32 16C32 7.16 24.84 0 16 0V0Z" fill="#24292E"/>
</svg>

After

Width:  |  Height:  |  Size: 959 B

77
.github/website/src/index.html.jinja vendored Normal file
View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hacker Laws</title>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RGJ5TDHWY9"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-RGJ5TDHWY9');
</script>
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Inter:wght@400;600&display=swap" rel="stylesheet">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- Bootstrap Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" />
<link rel="stylesheet" href="styles.css">
</head>
<body id="top">
<nav class="navbar navbar-expand-lg fixed-top bg-dark" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand" href="#top">Hacker Laws</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMenu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navMenu">
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link" href="https://effective-shell.com" target="_blank"><i class="bi bi-book"></i> Effective Shell</a></li>
<li class="nav-item"><a class="nav-link" href="https://github.com/dwmkerr/terminal-ai" target="_blank"><i class="bi bi-terminal"></i> Terminal AI</a></li>
<li class="nav-item"><a class="nav-link" href="https://github.com/sponsors/dwmkerr" target="_blank"><i class="bi bi-cup-hot"></i> Sponsor</a></li>
</ul>
<a href="https://github.com/dwmkerr/hacker-laws" target="_blank"><button class="btn btn-outline-light" type="submit"><i class="bi bi-github"></i> GitHub</button></a>
</div>
</div>
</nav>
<header class="container">
<h1>Hacker Laws</h1>
<p class="lead">Laws, Theories, Principles and Patterns that developers will find useful.</p>
</header>
<main class="container">
<!-- Quick links. -->
{{ links }}
<hr>
<!-- The table of contents. -->
{{ toc }}
<hr>
<!-- Each of the sections - most of which are laws. -->
{% for section in sections %}
<section id="{{ section.id }}" class="law-section">
{{ section.full_content | safe }}
<div class="social-sharing">
<a href="https://twitter.com/intent/tweet?url=https://hacker-laws.com/#{{ section.id}}?hashtags=example" title="Share on Twitter" target="_blank"><i class="bi bi-twitter"></i></a>
<a href="https://www.facebook.com/sharer/sharer.php?u=https://hacker-laws.com/&num;{{ section.id }}" title="Share on Facebook" target="_blank"><i class="bi bi-facebook"></i></a>
</div>
<div class="back-to-top"><a href="#top">↑ Back to Top</a></div>
</section>
{% endfor %}
</main>
<footer class="container text-center my-4">
<p>&copy; 2025 Hacker Laws</p>
</footer>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="script.js"></script>
</body>
</html>

18
.github/website/src/script.js vendored Normal file
View File

@@ -0,0 +1,18 @@
$(document).ready(function() {
$("h1, h2, h3, h4, h5, h6").each(function() {
var $heading = $(this);
var headingId = $heading.attr("id") || $heading.text().trim().toLowerCase().replace(/\s+/g, "-");
// Ensure a unique ID
$heading.attr("id", headingId);
// Create the anchor link
var $anchor = $('<a>')
.attr("href", "#" + headingId)
.addClass("header-link")
.html("#");
// Append to the heading
$heading.append($anchor);
});
});

73
.github/website/src/styles.css vendored Normal file
View File

@@ -0,0 +1,73 @@
html {
scroll-behavior: auto !important;
}
body {
font-family: 'Inter', sans-serif;
background-color: #fff;
color: #333;
padding-top: 70px;
}
.container {
max-width: 800px;
}
header {
text-align: center;
margin-bottom: 2rem;
padding: 2rem 0;
border-bottom: 1px solid #e5e5e5;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Libre Baskerville', serif;
/* Avoid scrolling under the sticky header. */
scroll-margin-top: 80px;
}
.law-section {
margin-bottom: 2rem;
padding: 1.5rem;
background-color: #fff;
border-bottom: 1px solid #e5e5e5;
position: relative;
}
.law-section h2 {
position: relative;
display: flex;
align-items: center;
}
.law-section h2 a.anchor {
text-decoration: none;
color: #999;
margin-left: 0.5rem;
visibility: hidden;
}
.law-section:hover h2 a.anchor {
visibility: visible;
}
.social-sharing a {
margin-right: 0.75rem;
font-size: 1.2rem;
color: #555;
text-decoration: none;
}
.social-sharing a:hover {
color: #000;
}
.back-to-top {
margin-top: 1rem;
}
/* Initially hide the hash link */
.header-link {
text-decoration: none;
margin-left: 12px; /* Increased left padding */
opacity: 0;
transition: opacity 0.2s;
font-size: inherit; /* Matches the heading size */
}
/* Only show the hash when the whole section is hovered */
section:hover .header-link,
article:hover .header-link,
div:hover .header-link {
opacity: 1;
}

View File

@@ -1,18 +1,27 @@
# This pipeline builds the PDF ebook on any pull request to master.
name: "Build PDF"
name: "Validate Pull Request"
on:
pull_request:
branches:
- master
jobs:
prepare-pdf:
# Focal Fossa. Please don't use 'latest' tags, it's an anti-pattern.
runs-on: ubuntu-20.04
test-website-build:
runs-on: ubuntu-24.04
steps:
# Checkout the code.
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Test Website Build
run: |
cd .github/website
make install
make build
cp -r build/. '../pages'
ls -al "../pages"
prepare-pdf:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
# Set a descriptive version. For PRs it'll be the short sha.
- name: Set Version
@@ -41,3 +50,4 @@ jobs:
with:
name: hacker-laws.md
path: hacker-laws.md

46
.github/workflows/pages.yaml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Deploy to Pages
on:
# Runs on pushes targeting the default branch (or runs manually).
push:
branches: [$default-branch]
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Build Website
run: |
cd .github/website
make install
make build
cp -r build/. '../pages'
ls -al "../pages"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './.github/pages'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

231
README.md
View File

@@ -1,86 +1,94 @@
# 💻📖 hacker-laws
<h1 align="center"><a href="https://hacker-laws.com" target="_blank">hacker-laws</a></h1>
<h4 align="center">🧠 Laws, Theories, Principles and Patterns for developers and technologists.</h4>
Laws, Theories, Principles and Patterns that developers will find useful.
---
[Translations](#translations): [🇮🇩](./translations/id.md) [🇧🇷](./translations/pt-BR.md) [🇨🇳](https://github.com/nusr/hacker-laws-zh) [🇩🇪](./translations/de.md) [🇫🇷](./translations/fr.md) [🇬🇷](./translations/el.md) [🇮🇹](https://github.com/csparpa/hacker-laws-it) [🇱🇻](./translations/lv.md) [🇰🇷](https://github.com/codeanddonuts/hacker-laws-kr) [🇵🇱](./translations/pl.md) [🇷🇺](https://github.com/solarrust/hacker-laws) [🇪🇸](./translations/es-ES.md) [🇹🇷](https://github.com/umutphp/hacker-laws-tr) [🇯🇵](./translations/jp.md) [🇺🇦](./translations/uk.md) [🇻🇳](./translations/vi.md)
Like this project? Please considering [sponsoring me](https://github.com/sponsors/dwmkerr) and the [translators](#translations). Also check out this podcast on [The Changelog - Laws for Hackers to Live By](https://changelog.com/podcast/403) to learn more about the project! You can also [download the latest PDF eBook](https://github.com/dwmkerr/hacker-laws/releases/latest/download/hacker-laws.pdf). Check the [Contributor Guide](./.github/contributing.md) if you are keen to contribute!
- 📖 Check out my new book [Effective Shell](https://effective-shell) on [Amazon](https://amzn.to/4ho0F91)
- 🌍 Check out the website [hacker-laws.com](https://hacker-laws.com)
- ☕️ Like this project? Consider [buying me a coffee with a one-off donation](https://github.com/sponsors/dwmkerr?frequency=one-time)
- 🧠 Check out my new project [Terminal AI](https://github.com/dwmkerr/terminal-ai)
- 🎧 Try the podcast [The Changelog - Laws for Hackers to Live By](https://changelog.com/podcast/403)
- 📖 Download the [PDF eBook](https://github.com/dwmkerr/hacker-laws/releases/latest/download/hacker-laws.pd)
---
<!-- vim-markdown-toc GFM -->
* [Introduction](#introduction)
* [Laws](#laws)
* [9091 Principle (1% Rule)](#9091-principle-1-rule)
* [Amdahl's Law](#amdahls-law)
* [The Broken Windows Theory](#the-broken-windows-theory)
* [Brooks' Law](#brooks-law)
* [CAP Theorem (Brewer's Theorem)](#cap-theorem-brewers-theorem)
* [Clarke's three laws](#clarkes-three-laws)
* [Conway's Law](#conways-law)
* [Cunningham's Law](#cunninghams-law)
* [Dunbar's Number](#dunbars-number)
* [The Dunning-Kruger Effect](#the-dunning-kruger-effect)
* [Fitts' Law](#fitts-law)
* [Gall's Law](#galls-law)
* [Goodhart's Law](#goodharts-law)
* [Hanlon's Razor](#hanlons-razor)
* [Hick's Law (Hick-Hyman Law)](#hicks-law-hick-hyman-law)
* [Hofstadter's Law](#hofstadters-law)
* [Hutber's Law](#hutbers-law)
* [The Hype Cycle & Amara's Law](#the-hype-cycle--amaras-law)
* [Hyrum's Law (The Law of Implicit Interfaces)](#hyrums-law-the-law-of-implicit-interfaces)
* [Kernighan's Law](#kernighans-law)
* [Linus's Law](#linuss-law)
* [Metcalfe's Law](#metcalfes-law)
* [Moore's Law](#moores-law)
* [Murphy's Law / Sod's Law](#murphys-law--sods-law)
* [Occam's Razor](#occams-razor)
* [Parkinson's Law](#parkinsons-law)
* [Premature Optimization Effect](#premature-optimization-effect)
* [Putt's Law](#putts-law)
* [Reed's Law](#reeds-law)
* [The Law of Conservation of Complexity (Tesler's Law)](#the-law-of-conservation-of-complexity-teslers-law)
* [The Law of Demeter](#the-law-of-demeter)
* [The Law of Leaky Abstractions](#the-law-of-leaky-abstractions)
* [The Law of the Instrument](#the-law-of-the-instrument)
* [The Law of Triviality](#the-law-of-triviality)
* [The Unix Philosophy](#the-unix-philosophy)
* [The Scout Rule](#the-scout-rule)
* [The Spotify Model](#the-spotify-model)
* [The Two Pizza Rule](#the-two-pizza-rule)
* [Wadler's Law](#wadlers-law)
* [Wheaton's Law](#wheatons-law)
* [The Bitter Lesson](#the-bitter-lesson)
* [Principles](#principles)
* [All Models Are Wrong (George Box's Law)](#all-models-are-wrong-george-boxs-law)
* [Chesterton's Fence](#chestertons-fence)
* [The Dead Sea Effect](#the-dead-sea-effect)
* [The Dilbert Principle](#the-dilbert-principle)
* [The Pareto Principle (The 80/20 Rule)](#the-pareto-principle-the-8020-rule)
* [The Shirky Principle](#the-shirky-principle)
* [The Peter Principle](#the-peter-principle)
* [The Robustness Principle (Postel's Law)](#the-robustness-principle-postels-law)
* [SOLID](#solid)
* [The Single Responsibility Principle](#the-single-responsibility-principle)
* [The Open/Closed Principle](#the-openclosed-principle)
* [The Liskov Substitution Principle](#the-liskov-substitution-principle)
* [The Interface Segregation Principle](#the-interface-segregation-principle)
* [The Dependency Inversion Principle](#the-dependency-inversion-principle)
* [The DRY Principle](#the-dry-principle)
* [The KISS principle](#the-kiss-principle)
* [YAGNI](#yagni)
* [The Fallacies of Distributed Computing](#the-fallacies-of-distributed-computing)
* [The Principle of Least Astonishment](#the-principle-of-least-astonishment)
* [Reading List](#reading-list)
* [Online Resources](#online-resources)
* [PDF eBook](#pdf-ebook)
* [Podcast](#podcast)
* [Translations](#translations)
* [Related Projects](#related-projects)
* [Contributing](#contributing)
* [TODO](#todo)
- [Introduction](#introduction)
- [Laws](#laws)
- [9091 Principle (1% Rule)](#9091-principle-1-rule)
- [9090 Rule](#9090-rule)
- [Amdahl's Law](#amdahls-law)
- [The Broken Windows Theory](#the-broken-windows-theory)
- [Brooks' Law](#brooks-law)
- [CAP Theorem (Brewer's Theorem)](#cap-theorem-brewers-theorem)
- [Clarke's three laws](#clarkes-three-laws)
- [Conway's Law](#conways-law)
- [Cunningham's Law](#cunninghams-law)
- [Dunbar's Number](#dunbars-number)
- [The Dunning-Kruger Effect](#the-dunning-kruger-effect)
- [Fitts' Law](#fitts-law)
- [Gall's Law](#galls-law)
- [Goodhart's Law](#goodharts-law)
- [Hanlon's Razor](#hanlons-razor)
- [Hick's Law (Hick-Hyman Law)](#hicks-law-hick-hyman-law)
- [Hofstadter's Law](#hofstadters-law)
- [Hutber's Law](#hutbers-law)
- [The Hype Cycle & Amara's Law](#the-hype-cycle--amaras-law)
- [Hyrum's Law (The Law of Implicit Interfaces)](#hyrums-law-the-law-of-implicit-interfaces)
- [Input-Process-Output (IPO)](#input-process-output-ipo)
- [Kernighan's Law](#kernighans-law)
- [Linus's Law](#linuss-law)
- [Metcalfe's Law](#metcalfes-law)
- [Moore's Law](#moores-law)
- [Murphy's Law / Sod's Law](#murphys-law--sods-law)
- [Occam's Razor](#occams-razor)
- [Parkinson's Law](#parkinsons-law)
- [Premature Optimization Effect](#premature-optimization-effect)
- [Putt's Law](#putts-law)
- [Reed's Law](#reeds-law)
- [The Ringelmann Effect](#the-ringelmann-effect)
- [The Law of Conservation of Complexity (Tesler's Law)](#the-law-of-conservation-of-complexity-teslers-law)
- [The Law of Demeter](#the-law-of-demeter)
- [The Law of Leaky Abstractions](#the-law-of-leaky-abstractions)
- [The Law of the Instrument](#the-law-of-the-instrument)
- [The Law of Triviality](#the-law-of-triviality)
- [The Unix Philosophy](#the-unix-philosophy)
- [The Scout Rule](#the-scout-rule)
- [The Spotify Model](#the-spotify-model)
- [The Two Pizza Rule](#the-two-pizza-rule)
- [Twyman's law](#twymans-law)
- [Wadler's Law](#wadlers-law)
- [Wheaton's Law](#wheatons-law)
- [Principles](#principles)
- [All Models Are Wrong (George Box's Law)](#all-models-are-wrong-george-boxs-law)
- [Chesterton's Fence](#chestertons-fence)
- [Kerckhoffs's principle](#kerckhoffss-principle)
- [The Dead Sea Effect](#the-dead-sea-effect)
- [The Dilbert Principle](#the-dilbert-principle)
- [The Pareto Principle (The 80/20 Rule)](#the-pareto-principle-the-8020-rule)
- [The Shirky Principle](#the-shirky-principle)
- [The Peter Principle](#the-peter-principle)
- [The Robustness Principle (Postel's Law)](#the-robustness-principle-postels-law)
- [SOLID](#solid)
- [The Single Responsibility Principle](#the-single-responsibility-principle)
- [The Open/Closed Principle](#the-openclosed-principle)
- [The Liskov Substitution Principle](#the-liskov-substitution-principle)
- [The Interface Segregation Principle](#the-interface-segregation-principle)
- [The Dependency Inversion Principle](#the-dependency-inversion-principle)
- [The DRY Principle](#the-dry-principle)
- [The KISS principle](#the-kiss-principle)
- [YAGNI](#yagni)
- [The Fallacies of Distributed Computing](#the-fallacies-of-distributed-computing)
- [The Principle of Least Astonishment](#the-principle-of-least-astonishment)
- [Reading List](#reading-list)
- [Online Resources](#online-resources)
- [PDF eBook](#pdf-ebook)
- [Podcast](#podcast)
- [Translations](#translations)
- [Related Projects](#related-projects)
- [Contributing](#contributing)
- [TODO](#todo)
<!-- vim-markdown-toc -->
@@ -92,7 +100,7 @@ There are lots of laws which people discuss when talking about development. This
## Laws
And here we go!
Laws can be opinions on inevitabilities in the world of software engineering, or wry observations on unavoidable realities.
### 9091 Principle (1% Rule)
@@ -108,6 +116,19 @@ See Also:
- [Pareto principle](#the-pareto-principle-the-8020-rule)
### 9090 Rule
[90-90 Rule on Wikipedia](https://en.wikipedia.org/wiki/Ninety%E2%80%93ninety_rule)
> The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.
A wry reinterpretation of the [Pareto Principe (or 80-20 rule)](#the-pareto-principle-the-8020-rule) that highlights the real-world challenges of completing engineering work. This sentiment is also echoed in [Hofstadter's Law](#hofstadters-law).
See also:
- [Hofstadter's Law](#hofstadters-law)
- [The Pareto Principe](#the-pareto-principle-the-8020-rule)
### Amdahl's Law
[Amdahl's Law on Wikipedia](https://en.wikipedia.org/wiki/Amdahl%27s_law)
@@ -408,6 +429,24 @@ See also:
- [The Law of Leaky Abstractions](#the-law-of-leaky-abstractions)
- [XKCD 1172](https://xkcd.com/1172/)
### Input-Process-Output (IPO)
[InputProcessOutput on Wikipedia](https://en.wikipedia.org/wiki/IPO_model)
Systems can be incredibly complex, but can typically be broken down into smaller parts that follow a simple pattern:
1. Input is provided
2. Some kind of processing or transformation is performed
3. Output is returned
A sort function in a programming language or system could be a classic example of the IPO pattern; where arbitrary input is sorted based on a predicate and returned back. A web server could be modelled as an IPO system, where HTTP requests are transformed into HTTP responses. A highly complex Generative AI system could likewise be modelled in this way, with user input being passed through a complex model and a response being generated.
The IPO pattern is present in different forms across almost all technological domains, from [functional programming](https://en.wikipedia.org/wiki/Functional_programming) languages that explicitly follow IPO patterns to [The Unix Philosophy](#the-unix-philosophy), which suggests that highly complex systems can be built by chaining together many simple IPO programs.
See also:
- [The Unix Philosophy](#the-unix-philosophy)
### Kernighan's Law
> Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
@@ -559,6 +598,15 @@ See also:
- [Metcalfe's Law](#metcalfes-law)
- [Dunbar's Number](#dunbars-number)
### The Ringelmann Effect
[The Ringelmann effect on Wikipedia](https://en.wikipedia.org/wiki/Ringelmann_effect)
The Ringelmann Effect is the tendency of an individual to become increasingly inefficient as more and more people are involved in a task. In other words, as more individuals are added to a team, the more the average individual performance decreases. Multiple causes are believed to be at work, including loss of motivation ("[social loafing](https://en.wikipedia.org/wiki/Social_loafing)") and challenges related to coordination.
See also:
- [Brooks' Law](#brooks-law)
### The Law of Conservation of Complexity (Tesler's Law)
[The Law of Conservation of Complexity on Wikipedia](https://en.wikipedia.org/wiki/Law_of_conservation_of_complexity)
@@ -684,6 +732,18 @@ The number of links between people can be expressed as `n(n-1)/2` where n = numb
<img width="200px" alt="Complete graph; Links between people" src="./images/complete_graph.png" />
### Twyman's law
[Twyman's Law on Wikipedia](https://en.wikipedia.org/wiki/Twyman%27s_law)
> The more unusual or interesting the data, the more likely they are to have been the result of an error of one kind or another.
This law suggests that when there are particularly unusual data points, it is more likely that they are the result of errors or manipulation. For example, if a dataset of long-jump results from a sporting event showed a maximum value of 20 meters (more than twice the world record), it is more likely to be due to an error (such as recording a value in feet rather than meters) than due to an unusually long jump. It is also more likely in this case that the results could have been manipulated.
See also:
- [Sagan Standard](#TODO)
### Wadler's Law
[Wadler's Law on wiki.haskell.org](https://wiki.haskell.org/Wadler's_Law)
@@ -756,6 +816,22 @@ This principle is relevant in software engineering when removing technical debt.
The name of this principle comes from a story by [G.K. Chesterton](https://en.wikipedia.org/wiki/G._K._Chesterton). A man comes across a fence crossing the middle of the road. He complains to the mayor that this useless fence is getting in the way, and asks to remove it. The mayor asks why the fence is there in the first place. When the man says he doesn't know, the mayor says, "If you don't know its purpose, I certainly won't let you remove it. Go and find out the use of it, and then I may let you destroy it."
### Kerckhoffs's principle
[Kerckhoffs's principle on Wikipedia](https://en.wikipedia.org/wiki/Kerckhoffs%27s_principle)
> "...design your system assuming that your opponents know it in detail."
>
> _Steven M. Bellovin's formulation of Kerckhoff's Principle_
This principle of cryptography was an axiom created by cryptographer Auguste Kerckhoffs. He stated that a cryptosystem should be secure, even if everything about the system, except the key, is public knowledge. Not to be confused with [_"security through obscurity"_](#todo).
The gold standard for any secret-keeping system is that implementation details should be publicly distributed, without sacrificing or compromising security of said system.
The history of cryptography has shown that open discussion and analysis of cryptographic systems leads to better and more secure systems - as researchers are able to test for and expose potential vulnerabilities.
- [Shannon's Maxim](#todo)
### The Dead Sea Effect
[The Dead Sea Effect on Bruce F. Webster](http://brucefwebster.com/2008/04/11/the-wetware-crisis-the-dead-sea-effect/)
@@ -1094,6 +1170,7 @@ Thanks to a number of wonderful contributors, Hacker Laws is available in a numb
| [🇯🇵 JP 日本語 / Japanese](./translations/jp.md) | [Fumikazu Fujiwara](https://github.com/freddiefujiwara)| [![gitlocalized ](https://gitlocalize.com/repo/2513/ja/badge.svg)](https://gitlocalize.com/repo/2513/ja?utm_source=badge) |
| [🇰🇷 한국어 / Korean](https://github.com/codeanddonuts/hacker-laws-kr) | [Doughnut](https://github.com/codeanddonuts) | Partially complete |
| [🇱🇻 Latviešu Valoda / Latvian](./translations/lv.md) | [Arturs Jansons](https://github.com/iegik) | [![gitlocalized ](https://gitlocalize.com/repo/2513/lv/badge.svg)](https://gitlocalize.com/repo/2513/lv?utm_source=badge) |
| [🇮🇷 فارسی / Persian](./translations/fa.md) | [MohammadErfan Gooneh](https://github.com/MEgooneh) | . |
| [🇵🇱 Polski / Polish](./translations/pl.md) | [Mariusz Kogen](https://github.com/k0gen) | [![gitlocalized ](https://gitlocalize.com/repo/2513/pl/badge.svg)](https://gitlocalize.com/repo/2513/pl?utm_source=badge) |
| [🇷🇺 Русская версия / Russian](https://github.com/solarrust/hacker-laws) | [Alena Batitskaya](https://github.com/solarrust) | Partially complete |
| [🇪🇸 Castellano / Spanish](./translations/es-ES.md) | [Manuel Rubio](https://github.com/manuel-rubio) ([Sponsor](https://github.com/sponsors/manuel-rubio)) | Partially complete |

View File

@@ -1,20 +0,0 @@
# Sharing
Copy paste the below for sharing on social media. The channels are:
- [Hacker News](https://news.ycombinator.com)
- [`r/programming`](https://reddit.com/r/programming/)
- LinkedIn
- Twitter
## LinkedIn
#hackerlaws - <Law Name> - <Short Quote>
<Link>
Hacker Laws is a set of theories, principles and patterns that developers will find useful.
Thanks <person>
#hacking #programming #coding #development #computerscience #logic

119
assets/site/index.html Normal file
View File

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Hacker Laws Stack</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
margin: 0;
font-family: Arial, sans-serif;
}
#stack {
width: 400px;
height: 500px;
overflow-y: auto;
position: relative;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 10px;
}
.law-item {
text-align: left;
padding: 4px;
transition: transform 0.2s ease, opacity 0.2s;
transform-origin: left;
font-size: 16px;
color: #333;
margin: 6px 0;
position: relative;
display: flex;
align-items: center;
}
.law-item::before {
content: '';
display: block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #aaa;
margin-right: 8px;
transition: height 0.2s, background-color 0.2s;
}
</style>
</head>
<body>
<div id="stack" class="stack"></div>
<script>
const laws = [
"9091 Principle (1% Rule)", "9090 Rule", "Amdahl's Law", "The Broken Windows Theory",
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
"The KISS Principle", "YAGNI"
];
const stack = document.getElementById('stack');
const maxZoom = 1.5;
const minZoom = 0.6;
laws.forEach(title => {
const div = document.createElement('div');
div.className = 'law-item';
div.innerText = title;
stack.appendChild(div);
});
function updateScale(e) {
const items = document.querySelectorAll('.law-item');
items.forEach(item => {
const itemRect = item.getBoundingClientRect();
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
const distance = Math.abs(e.clientY - itemCenter);
const scale = Math.max(maxZoom - distance / 150, minZoom);
const opacity = Math.max(1 - distance / 300, 0.3);
item.style.transform = `scale(${scale})`;
item.style.opacity = opacity;
const dot = item.querySelector('::before');
const barHeight = Math.max(6, 30 - distance / 10);
item.style.setProperty('--dot-height', barHeight + 'px');
item.style.setProperty('--dot-color', distance < 50 ? '#333' : '#aaa');
item.querySelector('::before');
item.style.setProperty('--dot-height', barHeight + 'px');
});
}
document.addEventListener('mousemove', updateScale);
// Initial positioning
updateScale({ clientY: window.innerHeight / 2 });
</script>
<style>
.law-item::before {
height: var(--dot-height, 6px);
background-color: var(--dot-color, #aaa);
}
</style>
</body>
</html>

110
assets/site/index2.html Normal file
View File

@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Hacker Laws Stack</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
margin: 0;
font-family: Arial, sans-serif;
}
#stack {
width: 400px;
height: 500px;
overflow-y: auto;
position: relative;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 10px;
}
.law-item {
text-align: left;
padding: 2px 4px;
transition: transform 0.2s ease, opacity 0.2s;
transform-origin: left;
font-size: 15px;
color: #333;
margin: 4px 0;
position: relative;
display: flex;
align-items: center;
}
.law-item::before {
content: '';
display: block;
width: var(--bar-width, 6px);
height: 6px;
border-radius: 3px;
background-color: var(--bar-color, #aaa);
margin-right: 10px;
transition: width 0.2s, background-color 0.2s;
}
</style>
</head>
<body>
<div id="stack" class="stack"></div>
<script>
const laws = [
"9091 Principle (1% Rule)", "9090 Rule", "Amdahl's Law", "The Broken Windows Theory",
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
"The KISS Principle", "YAGNI"
];
const stack = document.getElementById('stack');
const maxZoom = 1.8;
const minZoom = 0.5;
laws.forEach(title => {
const div = document.createElement('div');
div.className = 'law-item';
div.innerText = title;
stack.appendChild(div);
});
function updateScale(e) {
const items = document.querySelectorAll('.law-item');
items.forEach(item => {
const itemRect = item.getBoundingClientRect();
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
const distance = Math.abs(e.clientY - itemCenter);
const scale = Math.max(maxZoom - distance / 120, minZoom);
const opacity = Math.max(1 - distance / 250, 0.2);
const barWidth = Math.max(6, 60 - distance / 5);
item.style.transform = `scale(${scale})`;
item.style.opacity = opacity;
item.style.setProperty('--bar-width', barWidth + 'px');
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
});
}
document.addEventListener('mousemove', updateScale);
// Initial positioning
updateScale({ clientY: window.innerHeight / 2 });
</script>
</body>
</html>

127
assets/site/index3.html Normal file
View File

@@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Hacker Laws Stack</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
margin: 0;
font-family: Arial, sans-serif;
overflow: hidden;
}
#stack-container {
width: 400px;
height: 500px;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 10px;
overflow: hidden;
position: relative;
}
#stack {
position: absolute;
width: 100%;
}
.law-item {
text-align: left;
padding: 2px 4px;
transition: transform 0.2s ease, opacity 0.2s;
transform-origin: left;
font-size: 15px;
color: #333;
margin: 4px 0;
position: relative;
display: flex;
align-items: center;
}
.law-item::before {
content: '';
display: block;
width: var(--bar-width, 6px);
height: 6px;
border-radius: 3px;
background-color: var(--bar-color, #aaa);
margin-right: 10px;
transition: width 0.2s, background-color 0.2s;
}
</style>
</head>
<body>
<div id="stack-container">
<div id="stack"></div>
</div>
<script>
const laws = [
"9091 Principle (1% Rule)", "9090 Rule", "Amdahl's Law", "The Broken Windows Theory",
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
"The KISS Principle", "YAGNI"
];
const stack = document.getElementById('stack');
const stackContainer = document.getElementById('stack-container');
const maxZoom = 1.8;
const minZoom = 0.5;
let offsetY = 0;
laws.forEach(title => {
const div = document.createElement('div');
div.className = 'law-item';
div.innerText = title;
stack.appendChild(div);
});
function updateScale() {
const items = document.querySelectorAll('.law-item');
items.forEach(item => {
const itemRect = item.getBoundingClientRect();
const containerRect = stackContainer.getBoundingClientRect();
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
const containerCenter = (containerRect.top + containerRect.bottom) / 2;
const distance = Math.abs(containerCenter - itemCenter);
const scale = Math.max(maxZoom - distance / 120, minZoom);
const opacity = Math.max(1 - distance / 300, 0.3);
const barWidth = Math.max(6, 60 - distance / 3);
item.style.transform = `scale(${scale})`;
item.style.opacity = opacity;
item.style.setProperty('--bar-width', barWidth + 'px');
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
});
}
stackContainer.addEventListener('wheel', (e) => {
e.preventDefault();
offsetY = (offsetY + e.deltaY) % stack.scrollHeight;
if (offsetY < 0) offsetY += stack.scrollHeight;
stack.style.top = `${-offsetY}px`;
updateScale();
});
document.addEventListener('mousemove', updateScale);
updateScale();
</script>
</body>
</html>

158
assets/site/index4.html Normal file
View File

@@ -0,0 +1,158 @@
<!--
Interactive Hacker Laws Stack - Specification:
1. User Experience:
- Display a vertically scrolling list of items ("laws") in a visually appealing, interactive format.
- The list infinitely loops seamlessly; scrolling beyond the first or last item cycles continuously.
- Mouse scrolling moves the entire list vertically within a fixed viewport (no internal scrollbar visible).
- The item under the mouse cursor smoothly scales up (zooms) and becomes clearly highlighted.
- Items further from the cursor scale down smoothly, fade out gradually, and become visually less prominent.
- To the left of each text item, a horizontal bar visually represents the focus, forming a bell-curve-like effect.
The bar is smallest (circular) when far from the cursor, and smoothly expands (rectangular with rounded corners) when close.
2. Sources:
- Original Interaction Design Inspiration: https://press.stripe.com/
- Data Source (list of "Hacker Laws"): https://github.com/dwmkerr/hacker-laws/
3. Technical Details:
- Implemented using plain HTML, CSS, and JavaScript without third-party libraries.
- Clearly defined parameters for customization:
- `maxZoom`: maximum scale factor for the item closest to the cursor.
- `minZoom`: minimum scale factor for items furthest from the cursor.
- Styling is clean, minimalist, and customizable via CSS variables.
This specification allows easy adjustments, maintenance, and future enhancements of the interactive list.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Hacker Laws Stack</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
margin: 0;
font-family: Arial, sans-serif;
overflow: hidden;
}
#stack-container {
width: 400px;
height: 500px;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 10px;
overflow: hidden;
position: relative;
}
#stack {
position: absolute;
width: 100%;
}
.law-item {
text-align: left;
padding: 2px 4px;
transition: transform 0.2s ease, opacity 0.2s;
transform-origin: left;
font-size: 15px;
color: #333;
margin: 4px 0;
position: relative;
display: flex;
align-items: center;
}
.law-item::before {
content: '';
display: block;
width: var(--bar-width, 6px);
height: 6px;
border-radius: 3px;
background-color: var(--bar-color, #aaa);
margin-right: 10px;
transition: width 0.2s, background-color 0.2s;
}
</style>
</head>
<body>
<div id="stack-container">
<div id="stack"></div>
</div>
<script>
const laws = [
"9091 Principle (1% Rule)", "9090 Rule", "Amdahl's Law", "The Broken Windows Theory",
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
"The KISS Principle", "YAGNI"
];
const stack = document.getElementById('stack');
const stackContainer = document.getElementById('stack-container');
const maxZoom = 1.8;
const minZoom = 0.5;
let offsetY = 0;
// Create seamless infinite scrolling
const extendedLaws = [...laws, ...laws, ...laws];
extendedLaws.forEach(title => {
const div = document.createElement('div');
div.className = 'law-item';
div.innerText = title;
stack.appendChild(div);
});
const totalHeight = stack.scrollHeight / 3;
stack.style.top = `-${totalHeight}px`;
offsetY = totalHeight;
function updateScale(e) {
const items = document.querySelectorAll('.law-item');
items.forEach(item => {
const itemRect = item.getBoundingClientRect();
const distance = e.clientY ? Math.abs(e.clientY - (itemRect.top + itemRect.bottom) / 2) : 0;
const scale = Math.max(maxZoom - distance / 120, minZoom);
const opacity = Math.max(1 - distance / 300, 0.3);
const barWidth = Math.max(6, 60 - distance / 3);
item.style.transform = `scale(${scale})`;
item.style.opacity = opacity;
item.style.setProperty('--bar-width', barWidth + 'px');
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
});
}
stackContainer.addEventListener('wheel', (e) => {
e.preventDefault();
offsetY += e.deltaY;
if (offsetY >= totalHeight * 2) offsetY -= totalHeight;
if (offsetY < totalHeight) offsetY += totalHeight;
stack.style.top = `-${offsetY}px`;
updateScale(e);
});
stackContainer.addEventListener('mousemove', updateScale);
// Initial scale update
updateScale({ clientY: window.innerHeight / 2 });
</script>
</body>
</html>

View File

@@ -1,42 +1,32 @@
#!/usr/bin/env bash
# This script prepares a `hacker-laws.md` file which is in a format ready to be
# exported to PDF or other formats for an e-book.
# This script prepares a `hacker-laws.md` file for export to PDF or e-book format.
# Require that we provide the version number and get a date.
# Require a version number and get the current date.
version=$1
date=$(date "+%Y-%m-%d")
if [ -z $version ]; then
echo "version must be specified: ./prepare-markdown-for-ebook.sh <version>"
if [ -z "$version" ]; then
echo "Usage: $0 <version>"
exit 1
fi
# Create the frontmatter.
cat << EOF > frontmatter.md
# Create `hacker-laws.md` with frontmatter and README content in one step.
cat << EOF > hacker-laws.md
---
title: "Hacker Laws"
author: "Dave Kerr, github.com/dwmkerr/hacker-laws"
subtitle: "Laws, Theories, Principles and Patterns that developers will find useful. ${version}, ${date}."
subtitle: "Laws, Theories, Principles, and Patterns that developers will find useful. ${version}, ${date}."
---
EOF
cat README.md >> hacker-laws.md
# Combine the frontmatter and the laws.
cat frontmatter.md README.md >> hacker-laws.md
# Use a single `sed` command to clean up unwanted lines and emojis in one pass.
sed -i'' -e '/💻📖.*/d' \
-e 's/❗/Warning/g' \
-e '/^\[Translations.*/d' \
-e '/\*.*/d' \
-e '/ \*.*/d' \
-e '/## Translations/,$d' hacker-laws.md
# Remove the title - we have it in the front-matter of the doc, so it will
# automatically be added to the PDF.
sed -i'' '/💻📖.*/d' hacker-laws.md
# We can't have emojis in the final content with the PDF generator we're using.
sed -i'' 's/❗/Warning/' hacker-laws.md
# Now rip out the translations line.
sed -i'' '/^\[Translations.*/d' hacker-laws.md
# # Now rip out any table of contents items.
sed -i'' '/\*.*/d' hacker-laws.md
sed -i'' '/ \*.*/d' hacker-laws.md
# Delete everything from 'Translations' onwards (we don't need the translations
# lists, related projects, etc).
sed -i'' '/## Translations/,$d' hacker-laws.md
echo "hacker-laws.md prepared successfully."