Inspired by Laurie Hérault's article and Coding With Lewis' YouTube video
- What is FaxMeMaybe?
- Why Is This Over-Engineered?
- Architecture Overview
- Technology Explained (For Beginners)
- Features
- How It Works
- Project Structure
- Configuration
- Usage
- Contributing
- License
- Acknowledgments
FaxMeMaybe is a purposefully over-engineered TODO and reminder system that takes a simple concept, which is "send yourself a reminder", and turns it into a distributed, cloud-native, edge-computing masterpiece that physically prints your TODOs on thermal paper.
Instead of using a simple note-taking app, FaxMeMaybe:
- 📝 Accepts TODOs through a beautiful web interface
- 🌐 Runs on the edge using Cloudflare Workers
- 📋 Syncs with Todoist as the source of truth
- 🎨 Renders tickets using a headless browser (Puppeteer)
- 💾 Stores ID mappings in Cloudflare D1 (SQLite at the edge)
- 📤 Sends print jobs to AWS SQS
- 🍓 Polls messages on a Raspberry Pi
- 🖨️ Physically prints your TODO on a thermal printer
This is engineering for the sake of engineering, and I have learned alot from it! 🎉
Because we can! But also because it's a fantastic learning project that demonstrates:
- Modern web development practices
- Cloud infrastructure and edge computing
- Serverless architecture
- Message queue patterns
- Hardware integration
- CI/CD pipelines
- Full-stack development
I did not know most of these technologies before starting this project. By combining them into a single, silly application, I was able to learn how they all work together in a real-world scenario.
┌─────────────────────────────────────────────────────────────────┐
│ USER │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ React Frontend (Vite + TypeScript) │ │
│ │ • shadcn/ui components • Dark/Light mode • QR codes │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Cloudflare Workers (Edge Runtime - Hono) │ │
│ │ • API endpoints • Rate limiting • Authentication │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Todoist │ │ R2 Storage │ │ Puppeteer │ │
│ │ (Storage) │ │ (Tickets) │ │ (Headless) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────────┐ │
│ │ │ AWS SQS │ │
│ │ │ Message Queue │ │
│ │ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌───────────────────────────────────┐ │
│ │ D1 Database │ │ Raspberry Pi Client (Python) │ │
│ │ (ID Mapping)│ │ • SQS Polling • Image Download │ │
│ └─────────────┘ └───────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Thermal Printer │ │
│ │ (USB Device) │ │
│ └─────────────────┘ │
│ │
│ ┌───────────────────────────────────┐ │
│ │ GitHub Actions (CI/CD) │ │
│ │ • Auto-deploy on push │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- ✅ Beautiful, responsive React UI with dark/light mode
- ✅ Real-time TODO submission with validation
- ✅ Importance levels (Low, Medium, High, Urgent, Critical) with 🔥 indicators
- ✅ Optional due dates with natural language support ("tomorrow", "next Friday")
- ✅ Optional sender information and description
- ✅ Todoist label selection with color support
- ✅ Live counter showing total TODOs sent
- ✅ Admin dashboard for managing TODOs
- ✅ Todoist as the source of truth for all TODOs
- ✅ Automatic project creation ("FaxMeMaybe" project)
- ✅ Label sync from your Todoist account
- ✅ Priority mapping (importance levels → Todoist priorities)
- ✅ Natural language due date parsing
- ✅ Two-way sync via webhooks (optional)
- ✅ Direct links to tasks in Todoist app
- ✅ Automatic ticket generation with QR codes
- ✅ Labels displayed on printed tickets
- ✅ Printable ticket view optimized for thermal printers
- ✅ QR code leads to ViewTodo page for easy completion tracking
- ✅ Tickets stored as images in R2 storage
- ✅ Access TODO details via QR code or direct link
- ✅ View labels, description, and due dates
- ✅ Mark TODOs as complete with one click (syncs to Todoist)
- ✅ Direct link to open task in Todoist
- ✅ Beautiful themed UI matching the main app
- ✅ No authentication required (perfect for QR code access)
- ✅ Rate limiting (10 requests per minute)
- ✅ Input validation and sanitization
- ✅ CORS configuration
- ✅ Edge computing for global low latency
- ✅ SQLite database at the edge (D1)
- ✅ Automated deployments via GitHub Actions
- ✅ Automatic server rebuild on code changes
- ✅ SQS message polling on Raspberry Pi
- ✅ Automatic ticket rendering and storage
- ✅ USB thermal printer support
- ✅ Automatic paper size detection
- ✅ Image preprocessing for optimal print quality
- ✅ Error handling and retry logic
- Visit
remind.deadpackets.pw - Fill out the TODO form (importance, message, due date, labels, sender)
- Click "Send TODO"
- The form validates input and sends a POST request to the API
- Cloudflare Worker receives the request
- Rate limiting checks (max 10 per minute)
- Task is created in Todoist (in "FaxMeMaybe" project)
- A mapping (QR UUID → Todoist ID) is saved to D1 database
- A headless browser (Puppeteer) renders a ticket page as an image
- The ticket image is uploaded to R2 storage
- A message is sent to AWS SQS with the image URL
- Python client continuously polls SQS for new messages
- When a message arrives, it downloads the ticket image
- The image is preprocessed (resized, converted to 1-bit)
- The USB thermal printer receives the data and prints!
- The printed ticket includes a QR code
- Scanning it opens the ViewTodo page
- User can see full TODO details (including labels and description)
- Clicking "Mark as Complete" updates Todoist
- The TODO is now tracked as done in both FaxMeMaybe and Todoist!
FaxMeMaybe/
├── 📂 fax-me-maybe-server/ # Cloudflare Workers backend + React frontend
│ ├── 📂 src/
│ │ ├── 📂 worker/ # Hono backend (TypeScript)
│ │ │ ├── index.ts # Main API routes
│ │ │ ├── rate-limit.ts # Rate limiting middleware
│ │ │ ├── api.types.ts # TypeScript type definitions
│ │ │ └── 📂 services/
│ │ │ └── todoist.ts # Todoist API integration
│ │ ├── 📂 react-app/ # React frontend
│ │ │ ├── App.tsx # Main TODO submission page
│ │ │ ├── AdminDashboard.tsx # Admin panel for managing TODOs
│ │ │ ├── TodoTicket.tsx # Printable ticket view
│ │ │ ├── ViewTodo.tsx # QR code accessible TODO viewer
│ │ │ └── main.tsx # React router setup
│ │ ├── 📂 components/ # shadcn/ui components
│ │ │ └── ui/ # Reusable UI components
│ │ │ ├── label-selector.tsx # Todoist label picker
│ │ │ └── smart-date-input.tsx # Natural language date input
│ │ └── 📂 lib/
│ │ └── utils.ts # Utility functions
│ ├── 📂 public/ # Static assets
│ │ ├── og-image.png # OpenGraph preview image
│ │ └── flame.svg # Logo/icon
│ ├── 📂 migrations/ # D1 database migrations
│ │ └── 0001_todoist_integration.sql # Todoist mapping table
│ ├── package.json # Node.js dependencies
│ ├── wrangler.json # Cloudflare Workers configuration
│ ├── vite.config.ts # Vite build configuration
│ └── tsconfig.json # TypeScript configuration
│
├── 📂 fax-me-maybe-client/ # Raspberry Pi printer client
│ ├── main.py # SQS polling and printer control
│ ├── pyproject.toml # Python dependencies
│ ├── Dockerfile # Container configuration
│ └── docker-compose.yml # Docker Compose setup
│
├── 📂 .github/
│ └── 📂 workflows/ # GitHub Actions CI/CD
│ ├── build-server-on-push.yml # Auto-deploy server
│ └── build-client-on-push.yml # Build client
│
├── LICENSE # MIT License
├── README.md # You are here! 👋
└── TODO.md # Project roadmap
- Node.js 24+ (for the server)
- Python 3.14+ (for the client)
- npm or yarn (package manager)
- Cloudflare account (free tier works!)
- AWS account (for SQS)
- Raspberry Pi (optional, for physical printing)
- USB Thermal Printer (optional)
name: Your worker namecompatibility_date: Cloudflare runtime versionroutes: Custom domain mappingd1_databases: Database binding (for ID mappings)r2_buckets: Storage bindingbrowser: Puppeteer browser binding
| Variable | Description | Required |
|---|---|---|
TODOIST_API_TOKEN |
Your Todoist API token | Yes |
TODOIST_PROJECT_NAME |
Todoist project name (default: "FaxMeMaybe") | No |
TODOIST_WEBHOOK_SECRET |
Secret for webhook verification | No |
HONO_API_KEY |
API key for protected endpoints | Yes |
AWS_ACCESS_KEY_ID |
AWS credentials for SQS | Yes |
AWS_SECRET_ACCESS_KEY |
AWS credentials for SQS | Yes |
AWS_REGION |
AWS region for SQS | Yes |
SQS_QUEUE_URL |
SQS queue URL | Yes |
- Get your API token from Todoist Developer Settings
- Set the secret:
wrangler secret put TODOIST_API_TOKEN - (Optional) Configure webhook at Todoist App Console pointing to
/api/webhooks/todoist
Edit src/worker/rate-limit.ts:
simple: {
limit: 10, // Max requests
period: 60 // Time window (seconds)
}- Create an SQS queue in AWS Console
- Set visibility timeout to 60 seconds
- Enable server-side encryption (optional)
- Copy the queue URL to
.dev.vars
- Visit your deployed site (e.g.,
remind.deadpackets.pw) - Select importance level (🔥 Low → 🔥🔥🔥🔥🔥 Critical)
- Enter your TODO message (max 64 characters)
- (Optional) Add a description (max 500 characters)
- (Optional) Set a due date (supports natural language like "tomorrow", "next Friday")
- (Optional) Select labels from your Todoist account
- (Optional) Add your name in "From" field
- Click "Send TODO"
- Your TODO is created in Todoist and queued for printing!
- Navigate to
/admin - View all pending and completed TODOs (synced from Todoist)
- See labels, descriptions, and due dates
- Filter by completion status or labels
- Mark items as complete/incomplete (syncs to Todoist)
- Open tasks directly in Todoist
- Delete TODOs
- Print a TODO ticket
- Scan the QR code with your phone
- View full TODO details
- Click "Mark as Complete" when done
POST /api/todos # Create new TODO (syncs to Todoist)
GET /api/todos/count # Get total TODO count
GET /api/todos/:id # Get TODO by ID (fetches from Todoist)
GET /api/todos/:id/complete # Mark TODO as complete (syncs to Todoist)
GET /api/todos # List all TODOs from Todoist
GET /api/labels # Get available Todoist labels
PATCH /api/todos/:id/incomplete # Mark as incomplete (syncs to Todoist)
DELETE /api/todos/:id # Delete TODO (removes from Todoist)
POST /api/webhooks/todoist # Todoist webhook receiver
curl -X POST https://remind.deadpackets.pw/api/todos \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"todo": "Review the design mockups",
"importance": 3,
"description": "Check the new landing page designs",
"dueDate": "next Friday",
"labels": ["work", "design"],
"from": "Design Team"
}'Contributions are welcome! This is a learning project, so don't be shy.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Laurie Hérault - Original inspiration from "A receipt printer cured my procrastination"
- Coding With Lewis - YouTube tutorial that sparked the idea
- Cloudflare - For amazing edge computing tools
- python-escpos - For making thermal printer integration easy
- shadcn/ui - For beautiful, accessible components
- The open-source community ❤️
If you found this project helpful or entertaining, give it a ⭐!