Compare commits
No commits in common. "3af91e8a9d3019d57e165650bf05f1479662616a" and "2c17a3e4e3e71030aeb3b16c81ba648cc3bfb08b" have entirely different histories.
3af91e8a9d
...
2c17a3e4e3
@ -1,7 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
.astro
|
||||
.git
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
@ -1,2 +0,0 @@
|
||||
COMPOSE_PROJECT_NAME=mcwaddams-site
|
||||
DOMAIN=mcwaddams.mcp.website
|
||||
24
Caddyfile
@ -1,24 +0,0 @@
|
||||
:8080 {
|
||||
root * /srv
|
||||
file_server
|
||||
|
||||
handle /health {
|
||||
respond "OK" 200
|
||||
}
|
||||
|
||||
# SPA-style fallback for clean URLs
|
||||
try_files {path} {path}/ {path}.html /index.html
|
||||
|
||||
# Cache static assets aggressively
|
||||
@static path *.css *.js *.svg *.png *.webp *.jpg *.jpeg *.gif *.ico *.woff *.woff2
|
||||
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||
|
||||
# Security headers
|
||||
header {
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "DENY"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
}
|
||||
|
||||
encode gzip zstd
|
||||
}
|
||||
21
Dockerfile
@ -1,21 +0,0 @@
|
||||
# Stage 1: Build the Astro/Starlight site
|
||||
FROM node:22-alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: Serve static files with Caddy
|
||||
FROM caddy:2-alpine
|
||||
|
||||
COPY --from=build /app/dist /srv
|
||||
COPY Caddyfile /etc/caddy/Caddyfile
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget -qO- http://127.0.0.1:8080/health || exit 1
|
||||
28
Makefile
@ -1,28 +0,0 @@
|
||||
.PHONY: build up down restart logs status clean
|
||||
|
||||
build:
|
||||
docker compose build
|
||||
|
||||
up: build
|
||||
docker compose up -d
|
||||
@echo "Waiting for container to start..."
|
||||
@sleep 3
|
||||
docker compose logs --tail=20
|
||||
|
||||
down:
|
||||
docker compose down
|
||||
|
||||
restart:
|
||||
docker compose down
|
||||
docker compose up -d --build
|
||||
@sleep 3
|
||||
docker compose logs --tail=20
|
||||
|
||||
logs:
|
||||
docker compose logs -f
|
||||
|
||||
status:
|
||||
docker compose ps
|
||||
|
||||
clean:
|
||||
docker compose down --rmi local --volumes
|
||||
@ -99,7 +99,6 @@ export default defineConfig({
|
||||
{
|
||||
label: 'Community',
|
||||
items: [
|
||||
{ label: 'The Gallery', slug: 'community/gallery', badge: { text: 'New', variant: 'success' } },
|
||||
{ label: 'Feedback', slug: 'community/feedback' },
|
||||
{ label: 'Flair Leaderboard', slug: 'community/leaderboard' },
|
||||
{ label: 'Credits', slug: 'community/credits' },
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
services:
|
||||
site:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- caddy
|
||||
labels:
|
||||
caddy: ${DOMAIN}
|
||||
caddy.reverse_proxy: "{{upstreams 8080}}"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 3s
|
||||
start_period: 5s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
caddy:
|
||||
external: true
|
||||
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 145 KiB |
@ -1,37 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="filmGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1a1a2e"/>
|
||||
<stop offset="100%" style="stop-color:#16213e"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="reelGold" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#f59e0b"/>
|
||||
<stop offset="100%" style="stop-color:#d97706"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Badge background -->
|
||||
<circle cx="50" cy="50" r="48" fill="url(#filmGradient)" stroke="#f59e0b" stroke-width="3"/>
|
||||
|
||||
<!-- Film reel -->
|
||||
<circle cx="50" cy="50" r="30" fill="none" stroke="url(#reelGold)" stroke-width="4"/>
|
||||
<circle cx="50" cy="50" r="8" fill="url(#reelGold)"/>
|
||||
|
||||
<!-- Film reel holes -->
|
||||
<circle cx="50" cy="28" r="5" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="2"/>
|
||||
<circle cx="50" cy="72" r="5" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="2"/>
|
||||
<circle cx="28" cy="50" r="5" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="2"/>
|
||||
<circle cx="72" cy="50" r="5" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="2"/>
|
||||
|
||||
<!-- Diagonal holes -->
|
||||
<circle cx="34.5" cy="34.5" r="4" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="1.5"/>
|
||||
<circle cx="65.5" cy="34.5" r="4" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="1.5"/>
|
||||
<circle cx="34.5" cy="65.5" r="4" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="1.5"/>
|
||||
<circle cx="65.5" cy="65.5" r="4" fill="#1a1a2e" stroke="url(#reelGold)" stroke-width="1.5"/>
|
||||
|
||||
<!-- Film strip accents -->
|
||||
<rect x="10" y="85" width="8" height="6" rx="1" fill="url(#reelGold)" opacity="0.8"/>
|
||||
<rect x="22" y="85" width="8" height="6" rx="1" fill="url(#reelGold)" opacity="0.8"/>
|
||||
<rect x="70" y="85" width="8" height="6" rx="1" fill="url(#reelGold)" opacity="0.8"/>
|
||||
<rect x="82" y="85" width="8" height="6" rx="1" fill="url(#reelGold)" opacity="0.8"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 59 KiB |
@ -5,6 +5,8 @@ description: How Milton Waddams became the patron saint of legacy document proce
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# The Backstory
|
||||
|
||||
> *"I was told I could listen to the radio at a reasonable volume from nine to eleven..."*
|
||||
|
||||
## The Relocation
|
||||
|
||||
@ -5,6 +5,8 @@ description: The open source projects and cultural references that make mcwaddam
|
||||
|
||||
import { Aside, Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
|
||||
|
||||
# Credits & Attributions
|
||||
|
||||
> *"It's not just about me and my dream of doing nothing."*
|
||||
|
||||
mcwaddams stands on the shoulders of giants — both technical and cinematic.
|
||||
@ -131,8 +133,6 @@ For creating Office Space and giving the tech industry a shared vocabulary for d
|
||||
|
||||
The hero image — featuring THE actual film slate and red Swingline from production — is courtesy of [Mike Judge on X](https://x.com/MikeJudge).
|
||||
|
||||
Additional Office Space screenshots and character images sourced from the [Office Space Wiki](https://officespace.fandom.com/wiki/Office_Space_Wiki). Initech logo from the [Initech wiki page](https://officespace.fandom.com/wiki/Initech). Box of Flair merchandise image from the [Office Space Box of Flair wiki page](https://officespace.fandom.com/wiki/Office_Space_Box_of_Flair).
|
||||
|
||||
### Swingline
|
||||
|
||||
For actually manufacturing a red stapler after the movie came out. Sometimes life imitates art. (Fun fact: the prop department painted a black stapler red because Swingline didn't make that color in 1999.)
|
||||
|
||||
@ -5,6 +5,8 @@ description: Found a bug? Have an idea? We want to hear it.
|
||||
|
||||
import { Aside, Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
|
||||
|
||||
# Feedback
|
||||
|
||||
> *"Excuse me, I believe you have my bug report..."*
|
||||
|
||||
We want to hear from you — bugs, feature requests, or just letting us know what works.
|
||||
|
||||
@ -1,212 +0,0 @@
|
||||
---
|
||||
title: The Gallery
|
||||
description: A tribute to the film that inspired it all.
|
||||
---
|
||||
|
||||
import { Aside, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
> *"I'd say in a given week I probably only do about fifteen minutes of real, actual work."*
|
||||
|
||||
Welcome to the mcwaddams gallery — a loving tribute to Office Space (1999), the film that understands corporate life better than any management consultant ever could.
|
||||
|
||||
---
|
||||
|
||||
## The Initech Crew
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Peter.webp" alt="Peter Gibbons" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I did nothing. I did absolutely nothing, and it was everything I thought it could be."</p>
|
||||
<small>Peter Gibbons</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/peter-zen.webp" alt="Peter in his zen state" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I don't like my job, and I don't think I'm gonna go anymore."</p>
|
||||
<small>Post-hypnotherapy Peter</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Peter-Computing-Surprised.webp" alt="Peter surprised at computer" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I have eight different bosses right now."</p>
|
||||
<small>The moment of realization</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Management
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Peter-Lumberg-At-Cubicle.webp" alt="Lumbergh at Peter's cubicle" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Yeahhh, I'm gonna need you to come in on Saturday..."</p>
|
||||
<small>Bill Lumbergh</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/TheBobs.webp" alt="The Bobs" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"What would you say... you do here?"</p>
|
||||
<small>The Bobs — efficiency experts</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/management-disapproval.webp" alt="Management disapproval" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"We're gonna have to go ahead and move you downstairs into Storage B."</p>
|
||||
<small>The look of corporate disappointment</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Lumbergh-cake-sign.webp" alt="Lumbergh with cake sign" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Hello Peter, what's happening?"</p>
|
||||
<small>Passive-aggressive celebration</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## The Iconic Scenes
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Printer.webp" alt="The printer destruction scene" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"PC LOAD LETTER? What the f*** does that mean?!"</p>
|
||||
<small>The printer gets what it deserves</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/stapler-theft.webp" alt="Milton's stapler" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I believe you have my stapler..."</p>
|
||||
<small>The red Swingline</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Ohface.webp" alt="The O-Face" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"O-O-O-OHHHHH!"</p>
|
||||
<small>Drew's... moment</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Cakepass.webp" alt="The cake scene" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Milton, we're gonna need you to move your desk again..."</p>
|
||||
<small>Another office milestone ignored</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Chotchkie's & The Flair
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Stan.webp" alt="Stan the manager" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"We need to talk about your flair."</p>
|
||||
<small>Stan — the flair enforcer</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/box-of-flair.webp" alt="Box of flair" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"You know, the Nazis had pieces of flair they made the Jews wear."</p>
|
||||
<small>The official flair collection</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/fu-Flair.webp" alt="Joanna's statement" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"There's my flair."</p>
|
||||
<small>Joanna's final day at Chotchkie's</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/chotchkies-logo.webp" alt="Chotchkie's logo" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Sounds like somebody's got a case of the Mondays."</p>
|
||||
<small>Where dreams go to die</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## The Supporting Cast
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Lawrence.webp" alt="Lawrence" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Hey Peter, man, check out Channel 9!"</p>
|
||||
<small>Lawrence — the neighbor</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Lawrence-couch.webp" alt="Lawrence on the couch" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Two chicks at the same time, man."</p>
|
||||
<small>Lawrence's dream</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Nina.webp" alt="Nina" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Uh-oh. Sounds like somebody's got a case of the Mondays."</p>
|
||||
<small>Nina — the cheerful coworker</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/peter-hard-hat-samir-michael-GroupPic.webp" alt="Peter, Samir, and Michael Bolton" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Why should I change? He's the one who sucks."</p>
|
||||
<small>The crew at work</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Initech
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin: 2rem 0;">
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/Initech.webp" alt="Initech building" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Corporate accounts payable, Nina speaking. Just a moment."</p>
|
||||
<small>Initech — where TPS reports are born</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/peter-initech-sign.webp" alt="Peter arriving at Initech" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"Every single day of my life has been worse than the day before it."</p>
|
||||
<small>Another day at Initech</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/empty-office.webp" alt="Empty Initech office" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I'd like to move us right along to a Peter Gibbons."</p>
|
||||
<small>The cubicle farm</small>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="/burned-stapler-recover.webp" alt="Milton's stapler recovered" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);" />
|
||||
<p style="margin-top: 0.5rem; font-style: italic;">"I could set the building on fire..."</p>
|
||||
<small>The stapler survived</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
<Aside type="note" title="Attribution">
|
||||
All images are from Office Space (1999), directed by Mike Judge. Copyright © 20th Century Fox. Used for educational and tribute purposes. mcwaddams is not affiliated with 20th Century Fox.
|
||||
</Aside>
|
||||
|
||||
<div style="text-align: center; margin-top: 2rem; font-style: italic; opacity: 0.7;">
|
||||
|
||||
*"I don't like my job, and I don't think I'm gonna go anymore."*
|
||||
|
||||
<br/>
|
||||
|
||||
<small>— Peter Gibbons, speaking for all of us</small>
|
||||
|
||||
</div>
|
||||
@ -5,6 +5,8 @@ description: Who's got the most pieces of documentation flair?
|
||||
|
||||
import { Aside, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
# Flair Leaderboard
|
||||
|
||||
<div style="display: flex; justify-content: center; margin: 2rem 0;">
|
||||
<img src="/chotchkies-logo.webp" alt="Chotchkie's Bar & Grill" style="max-width: 300px; border-radius: 8px;" />
|
||||
</div>
|
||||
@ -17,49 +19,46 @@ We don't require 37 pieces of flair like Brian. Just the minimum — but we enco
|
||||
|
||||
## Your Collection
|
||||
|
||||
Click the **flair counter** in the bottom-right corner of any page to see your collection. Badges are earned by spending 15+ seconds reading each page.
|
||||
Click the **flair counter** in the bottom-right corner of any page to see your collection. Badges are earned by spending 3+ seconds reading each page.
|
||||
|
||||
## Available Flair (13 Badges)
|
||||
## Available Flair (12 Badges)
|
||||
|
||||
<CardGrid>
|
||||
<Card title="📄 I Was Told There Would Be Extraction" icon="document">
|
||||
Start your mcwaddams journey (homepage)
|
||||
<Card title="📄 First Extraction" icon="document">
|
||||
Visit the homepage
|
||||
</Card>
|
||||
<Card title="🔴 Basement Dweller" icon="puzzle">
|
||||
Learn about Milton and the legacy documents
|
||||
Read the backstory
|
||||
</Card>
|
||||
<Card title="🖨️ PC Load Letter" icon="setting">
|
||||
Successfully install mcwaddams
|
||||
Complete installation
|
||||
</Card>
|
||||
<Card title="☕ Case of the Mondays" icon="rocket">
|
||||
Complete the quick start guide
|
||||
Finish quick start
|
||||
</Card>
|
||||
<Card title="📋 TPS Report Expert" icon="list-format">
|
||||
Read the complete tools reference
|
||||
Browse tools reference
|
||||
</Card>
|
||||
<Card title="👔 The Bobs Approved" icon="approve-check">
|
||||
Understand the architecture
|
||||
Study architecture
|
||||
</Card>
|
||||
<Card title="📝 Did You Get The Memo?" icon="information">
|
||||
Check the test dashboard
|
||||
<Card title="📝 Memo Received" icon="information">
|
||||
Check test dashboard
|
||||
</Card>
|
||||
<Card title="😮 O Face" icon="star">
|
||||
Witness the torture test results
|
||||
<Card title="🔥 Jump to Conclusions" icon="warning">
|
||||
Survive torture tests
|
||||
</Card>
|
||||
<Card title="🔴 I Have Your Stapler" icon="heart">
|
||||
Find the credits and attributions
|
||||
<Card title="⭐ Flair Enthusiast" icon="star">
|
||||
View leaderboard
|
||||
</Card>
|
||||
<Card title="🎲 Jump to Conclusions" icon="warning">
|
||||
Complete your first extraction tutorial
|
||||
<Card title="🎖️ Credit Where Due" icon="heart">
|
||||
Read the credits
|
||||
</Card>
|
||||
<Card title="📊 Spreadsheet Survivor" icon="open-book">
|
||||
Master table extraction
|
||||
<Card title="📚 Legacy Handler" icon="open-book">
|
||||
Learn legacy formats
|
||||
</Card>
|
||||
<Card title="🎖️ 37 Pieces of Flair" icon="external">
|
||||
Discover the flair leaderboard
|
||||
</Card>
|
||||
<Card title="🎬 Cinema Enthusiast" icon="star">
|
||||
Explore the Office Space gallery
|
||||
<Card title="🌐 Cloud Connect" icon="external">
|
||||
Use hosted MCP
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
@ -67,7 +66,7 @@ Click the **flair counter** in the bottom-right corner of any page to see your c
|
||||
|
||||
## The Goal
|
||||
|
||||
Collect all 13 pieces of flair. Brian from accounting has 37, but we only ask for the minimum.
|
||||
Collect all 12 pieces of flair. Brian from accounting has 37, but we only ask for the minimum.
|
||||
|
||||
<Aside type="tip" title="Persistence">
|
||||
Your flair collection is stored in localStorage — it persists across sessions but stays on your device.
|
||||
|
||||
@ -5,6 +5,8 @@ description: How mcwaddams processes Office documents behind the scenes.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Architecture
|
||||
|
||||
> *"So I was sitting in my cubicle today, and I realized... every document format is worse than the one before it."*
|
||||
|
||||
mcwaddams is designed around a single principle: **never silently fail**. When extraction works, you get content. When it doesn't, you get a clear explanation why.
|
||||
|
||||
@ -5,6 +5,8 @@ description: How mcwaddams tries multiple methods to extract your documents.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Fallback Strategy
|
||||
|
||||
> *"We fixed the glitch."*
|
||||
|
||||
When the primary extraction method fails, mcwaddams automatically tries alternatives.
|
||||
|
||||
@ -5,6 +5,8 @@ description: The architectural decision behind mcwaddams's modular structure.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Why Mixins?
|
||||
|
||||
> *"What would you say... you do here?"*
|
||||
|
||||
mcwaddams uses Python mixins to organize 20 tools into logical groups without creating multiple MCP servers.
|
||||
|
||||
@ -5,6 +5,8 @@ description: How MCP resources enable on-demand document access.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Resource System
|
||||
|
||||
> *"I was told I could fetch chapters at a reasonable rate..."*
|
||||
|
||||
The MCP resource system lets you access parts of indexed documents without reprocessing.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Get statistical analysis and data quality insights from spreadsheet
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Analyze Excel Data
|
||||
|
||||
> *"I did nothing and it was everything I thought it could be."*
|
||||
|
||||
Get comprehensive insights from Excel spreadsheets including statistics, data types, and quality checks.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Transform Word documents into clean Markdown.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Convert to Markdown
|
||||
|
||||
> *"Why should I change? The document format's the one who sucks."*
|
||||
|
||||
Convert Word documents to Markdown while preserving structure, headings, lists, and tables.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Get structured table data from Word documents in multiple formats.
|
||||
|
||||
import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||
|
||||
# Extract Tables from Word Documents
|
||||
|
||||
> *"We need to talk about your table extraction..."*
|
||||
|
||||
Word documents often contain important data locked in tables. mcwaddams extracts them as structured data you can actually use.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Use mcwaddams without installing anything locally.
|
||||
|
||||
import { Aside, Code, Tabs, TabItem, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
# Connect to Hosted Server
|
||||
|
||||
> *"I was told there would be no installation..."*
|
||||
|
||||
Don't want to install anything? Connect to our hosted mcwaddams server via HTTP.
|
||||
@ -14,7 +16,7 @@ Don't want to install anything? Connect to our hosted mcwaddams server via HTTP.
|
||||
<Tabs>
|
||||
<TabItem label="Claude Code">
|
||||
```bash
|
||||
claude mcp add mcwaddams-hosted --transport http "https://mcwaddams.l.supported.systems/mcp"
|
||||
claude mcp add mcwaddams-hosted --transport http "https://mcwaddams.supported.systems/mcp"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="MCP Settings JSON">
|
||||
@ -24,7 +26,7 @@ Don't want to install anything? Connect to our hosted mcwaddams server via HTTP.
|
||||
"mcwaddams": {
|
||||
"transport": {
|
||||
"type": "streamable-http",
|
||||
"url": "https://mcwaddams.l.supported.systems/mcp"
|
||||
"url": "https://mcwaddams.supported.systems/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,7 +38,7 @@ Don't want to install anything? Connect to our hosted mcwaddams server via HTTP.
|
||||
from mcp import ClientSession
|
||||
from mcp.client.streamable_http import streamable_http_client
|
||||
|
||||
async with streamable_http_client("https://mcwaddams.l.supported.systems/mcp") as (read, write):
|
||||
async with streamable_http_client("https://mcwaddams.supported.systems/mcp") as (read, write):
|
||||
async with ClientSession(read, write) as session:
|
||||
await session.initialize()
|
||||
tools = await session.list_tools()
|
||||
@ -73,7 +75,7 @@ All 20+ mcwaddams tools are available via the hosted server:
|
||||
| Feature | Hosted | Local (uvx) |
|
||||
|---------|--------|-------------|
|
||||
| Installation | None | `uvx mcwaddams` |
|
||||
| File Access | URL + base64 upload | Local + URL |
|
||||
| File Access | URL only | Local + URL |
|
||||
| Speed | Network latency | Instant |
|
||||
| Privacy | Files processed on server | Files stay local |
|
||||
| Availability | Requires internet | Works offline |
|
||||
@ -82,13 +84,9 @@ All 20+ mcwaddams tools are available via the hosted server:
|
||||
When using the hosted server, your documents are transmitted to and processed on our server. For sensitive documents, use the local installation instead.
|
||||
</Aside>
|
||||
|
||||
## Uploading Documents
|
||||
## Using with URLs
|
||||
|
||||
The hosted server cannot access files on your local machine. Instead, you have two options:
|
||||
|
||||
### Option 1: URL Reference
|
||||
|
||||
If your document is already hosted online:
|
||||
The hosted server can process documents from URLs directly:
|
||||
|
||||
```python
|
||||
# Extract text from a public document
|
||||
@ -97,77 +95,7 @@ result = await session.call_tool("extract_text", {
|
||||
})
|
||||
```
|
||||
|
||||
### Option 2: Base64 Upload
|
||||
|
||||
For local files, encode them as base64 and pass via `file_content`:
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Python">
|
||||
```python
|
||||
import base64
|
||||
from pathlib import Path
|
||||
|
||||
# Read and encode your document
|
||||
doc_path = Path("my-report.docx")
|
||||
file_content = base64.b64encode(doc_path.read_bytes()).decode("utf-8")
|
||||
|
||||
# Call the tool with file_content
|
||||
result = await session.call_tool("extract_text", {
|
||||
"file_path": "my-report.docx", # Used for extension detection
|
||||
"file_content": file_content
|
||||
})
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
// Read and encode your document
|
||||
const docBuffer = readFileSync('my-report.docx');
|
||||
const fileContent = docBuffer.toString('base64');
|
||||
|
||||
// Call the tool with file_content
|
||||
const result = await session.callTool("extract_text", {
|
||||
file_path: "my-report.docx", // Used for extension detection
|
||||
file_content: fileContent
|
||||
});
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="Bash/curl">
|
||||
```bash
|
||||
# Encode document to base64
|
||||
FILE_CONTENT=$(base64 -w 0 my-report.docx)
|
||||
|
||||
# Call via HTTP (simplified example)
|
||||
curl -X POST https://mcwaddams.l.supported.systems/mcp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"method\": \"tools/call\",
|
||||
\"params\": {
|
||||
\"name\": \"extract_text\",
|
||||
\"arguments\": {
|
||||
\"file_path\": \"my-report.docx\",
|
||||
\"file_content\": \"$FILE_CONTENT\"
|
||||
}
|
||||
}
|
||||
}"
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<Aside type="note" title="file_path Still Required">
|
||||
When using `file_content`, the `file_path` parameter is still required but only used for extension detection. The server uses the extension to determine the correct processing method.
|
||||
</Aside>
|
||||
|
||||
### All Tools Support Upload
|
||||
|
||||
Every tool that accepts `file_path` also accepts `file_content`:
|
||||
|
||||
- `extract_text` - Extract text with base64 upload
|
||||
- `extract_images` - Extract images with base64 upload
|
||||
- `convert_to_markdown` - Convert Word docs to Markdown
|
||||
- `analyze_excel_data` - Analyze uploaded spreadsheets
|
||||
- And all other document tools...
|
||||
This is particularly useful for processing documents already hosted online.
|
||||
|
||||
## Self-Hosting
|
||||
|
||||
@ -183,16 +111,10 @@ services:
|
||||
- MCP_TRANSPORT=streamable-http
|
||||
- MCP_HOST=0.0.0.0
|
||||
- MCP_PORT=8000
|
||||
# Enable local file access (disabled by default for security)
|
||||
# - MCP_ALLOW_LOCAL_FILES=true
|
||||
ports:
|
||||
- "8000:8000"
|
||||
```
|
||||
|
||||
<Aside type="tip" title="Local File Access">
|
||||
By default, hosted servers only accept URLs and `file_content` uploads. If you're self-hosting on a trusted network and want to access local files, set `MCP_ALLOW_LOCAL_FILES=true`.
|
||||
</Aside>
|
||||
|
||||
### With Caddy Reverse Proxy
|
||||
|
||||
Clone the repo and use our docker-compose with caddy-docker-proxy labels:
|
||||
|
||||
@ -5,6 +5,8 @@ description: Work with documents that exceed token limits.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Handle Pagination
|
||||
|
||||
> *"Yeah, I'm gonna need you to go ahead and come in on Saturday for page 2..."*
|
||||
|
||||
Documents over 25,000 tokens are automatically paginated. Use cursors to fetch subsequent pages.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Extract documents directly from HTTP/HTTPS URLs.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Process URLs
|
||||
|
||||
> *"We fixed the glitch... by caching the download."*
|
||||
|
||||
All tools accept HTTP/HTTPS URLs directly. Files are cached for 1 hour.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Get mcwaddams up and running in under a minute.
|
||||
|
||||
import { Tabs, TabItem, Aside, Steps } from '@astrojs/starlight/components';
|
||||
|
||||
# Installation
|
||||
|
||||
> *"PC Load Letter? What the f*** does that mean?"*
|
||||
|
||||
Don't worry. This is simpler than fixing the printer.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Extract your first document in 60 seconds.
|
||||
|
||||
import { Aside, Steps, Code } from '@astrojs/starlight/components';
|
||||
|
||||
# Quick Start
|
||||
|
||||
> *"I'll be honest with you, I love his music. I do. I'm a Michael Bolton fan."*
|
||||
|
||||
Let's get you extracting documents faster than you can say "TPS report cover sheet."
|
||||
|
||||
@ -5,6 +5,8 @@ description: Specialized tools for Excel spreadsheet processing.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Excel Tools
|
||||
|
||||
These 3 tools are specialized for `.xlsx`, `.xls`, and `.csv` files.
|
||||
|
||||
## analyze_excel_data
|
||||
|
||||
@ -5,6 +5,8 @@ description: Complete list of supported Office document formats.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Format Support
|
||||
|
||||
mcwaddams supports all major Microsoft Office formats, both modern and legacy.
|
||||
|
||||
## Modern Formats (2007+)
|
||||
|
||||
@ -5,6 +5,8 @@ description: Resource URIs for on-demand document access.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# MCP Resources
|
||||
|
||||
After indexing a document, access content via MCP resource URIs.
|
||||
|
||||
## Resource URI Schemes
|
||||
|
||||
@ -5,6 +5,8 @@ description: Complete reference for all 20 mcwaddams MCP tools.
|
||||
|
||||
import { Aside, Badge, Tabs, TabItem, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
# All Tools Reference
|
||||
|
||||
> *"I'm going to need you to go ahead and read the documentation..."*
|
||||
|
||||
mcwaddams provides **20 tools** organized into three categories. Each tool follows the same pattern: pass a file path (local or URL), get structured data back.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Tools that work across all Office document formats.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Universal Tools
|
||||
|
||||
These 7 tools work with all supported formats: `.docx`, `.doc`, `.xlsx`, `.xls`, `.pptx`, `.ppt`, `.csv`.
|
||||
|
||||
## extract_text
|
||||
|
||||
@ -5,6 +5,8 @@ description: Specialized tools for Word document processing.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Word Tools
|
||||
|
||||
These 10 tools are specialized for `.docx` and `.doc` files.
|
||||
|
||||
## convert_to_markdown
|
||||
|
||||
@ -5,6 +5,8 @@ description: Test coverage philosophy and metrics.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Coverage Report
|
||||
|
||||
> *"Looks like you've been missing a lot of work lately."*
|
||||
> *"I wouldn't say I've been missing it, Bob."*
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@ description: "Did you get the memo about the TPS reports?"
|
||||
|
||||
import { Aside, Badge, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
# TPS Reports: Test Dashboard
|
||||
|
||||
> *"Yeah, I'm gonna need you to go ahead and come in on Saturday..."*
|
||||
|
||||
<Aside type="danger" title="TPS = Testing Painful Stuff">
|
||||
|
||||
@ -5,6 +5,8 @@ description: "301 random Office documents walked into a bar..."
|
||||
|
||||
import { Aside, Badge, Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
# Torture Test Results
|
||||
|
||||
> *"I'm gonna need you to come in on Saturday... and Sunday too."*
|
||||
|
||||
We grabbed 301 random Office documents from a real filesystem — no cherry-picking, no sanitizing, just raw production files from someone's decade-old archive.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Extract text from an Office document in 60 seconds.
|
||||
|
||||
import { Aside, Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||
|
||||
# Your First Extraction
|
||||
|
||||
> *"I'll be honest with you, I love extracting documents. I do. I'm a mcwaddams fan."*
|
||||
|
||||
Let's get you extracting documents faster than you can say "TPS report cover sheet."
|
||||
|
||||
@ -5,6 +5,8 @@ description: Efficiently access huge documents without loading everything at onc
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Indexing Large Documents
|
||||
|
||||
> *"It's not that I'm lazy, it's that I just don't care about loading 500 pages at once."*
|
||||
|
||||
For documents over 25,000 tokens, the indexing system enables on-demand fetching through MCP resources.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Handle .doc, .xls, and .ppt files from the basement archives.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Working with Legacy Formats
|
||||
|
||||
> *"I was told I could keep my legacy documents at a reasonable location from nine to eleven..."*
|
||||
|
||||
Legacy formats (`.doc`, `.xls`, `.ppt`) require special handling. mcwaddams uses OLE Compound Document parsing to extract content from files dating back to 1997.
|
||||
|
||||
@ -5,6 +5,8 @@ description: Access document content through the MCP resource protocol.
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
# Using MCP Resources
|
||||
|
||||
> *"The thing is, Bob, it's not that I'm lazy, it's that I just don't want to load everything."*
|
||||
|
||||
MCP resources let you fetch specific parts of indexed documents without reprocessing.
|
||||
|
||||
@ -97,14 +97,6 @@
|
||||
"placeholder": "🎖️",
|
||||
"image": "/flair/flair-badge.svg",
|
||||
"description": "Discovered the flair leaderboard"
|
||||
},
|
||||
{
|
||||
"id": "gallery",
|
||||
"path": "/community/gallery/",
|
||||
"name": "Cinema Enthusiast",
|
||||
"placeholder": "🎬",
|
||||
"image": "/flair/cinema.svg",
|
||||
"description": "Explored the Office Space gallery"
|
||||
}
|
||||
],
|
||||
"completionMessage": "You've got more than the minimum 15 pieces of flair!",
|
||||
|
||||