$

dev site โ€” experiments, projects, etc.

โ€” Public Repos
โ€” Latest Push
โ€” Domain Age
ฮป + S3 Infra
#

projects

Fetching repos from GitHub...

#

links


#

dev log

Rebuilding gfd.sh: From BBCode to Markdown + Cognito Auth

Completely rewrote the backend for gfd.sh today. What started as a simple Lambda-powered blog with environment-variable authentication turned into a properly architected serverless app with OAuth2 and clean module separation.

What Changed

Authentication: Environment Variables โ†’ AWS Cognito

The old version had a hacky username/password system where credentials lived in Lambda env vars:

if username in os.environ and password == os.environ[username]: # you're in

Now it's a full OAuth2/OIDC flow with Cognito Hosted UI:

  • /login redirects to Cognito
  • /test handles the callback, exchanges the authorization code for tokens
  • Session state lives in a signed HMAC cookie (not server-side storage)
  • /logout clears the cookie and redirects to Cognito's logout endpoint

Zero external dependencies โ€” just urllib, hmac, and base64 from the standard library.

Content Format: BBCode โ†’ Markdown

Replaced the custom BBCode parser with a zero-dependency Markdown renderer. Supports:

  • Headings, bold, italic, strikethrough
  • Inline code + fenced code blocks with syntax hints
  • Links, images
  • Ordered/unordered lists
  • Blockquotes, horizontal rules

Still renders entirely at write-time (Markdown โ†’ HTML before saving to S3), so serving is instant.

Architecture: Monolith โ†’ Modules

Broke the 300-line lambda_function.py into focused modules:

modules/ โ”œโ”€โ”€ config.py # strict env var loader (no defaults) โ”œโ”€โ”€ cognito_auth.py # OAuth flow + session cookies โ”œโ”€โ”€ s3_handler.py # posts.json CRUD โ”œโ”€โ”€ markdown_parser.py # Markdown โ†’ HTML โ””โ”€โ”€ html_builder.py # template injection + auth-aware nav

The main handler is now just a thin router โ€” all business logic lives in modules.

Message Threading

Posts are now attributed to the Cognito username:

{ "posts": [ { "timestamp": "2026-03-04 12:00:00 MST", "author": "username", "html": "<div class=\"textPost\">...</div>" } ] }

The UI displays them Discord-style: username ยท timestamp at the top of each message.

Why This Matters

Security: No plaintext passwords in env vars. Cognito handles user management, MFA, password resets, etc.

Maintainability: Modular code is easier to test, extend, and debug. Each module has a single responsibility.

Portability: The Markdown parser has zero dependencies beyond Python stdlib. No pip install markdown or beautifulsoup4 needed โ€” runs on bare Lambda Python runtime.

Strict Config: Added a require_env() helper that fails fast at startup if any required env var is missing. No silent fallbacks, no "it worked locally but not in prod."

Stack (Unchanged)

Still running on:

  • AWS Lambda (Python 3.x)
  • API Gateway (REST API proxy)
  • S3 (posts.json + INTELLIGENT_TIERING)
  • Route 53 + ACM (DNS + TLS)

Added:

  • AWS Cognito (user pool + hosted UI)

Cost: still pennies per month.

Next Steps

Might add:

  • Reply threading (nest messages under parent IDs)
  • Markdown preview in the post form
  • Syntax highlighting for code blocks (client-side)
  • Rate limiting on POST endpoint

For now, it's stable, clean, and ready to ship. GitHub-safe (no secrets in source), well-documented, and actually fun to work on.


*Posted from the /post form using the new Markdown renderer. Meta.*

Hello World

I made a little entry where you can leave a mark on my website.

Please be nice

Love,
Nolan

Posted on 2026-03-04 08:25:53 MST

will this work?

We should add username to the post!

Posted on 2026-03-04 08:10:37 MST

hey, this is my site!

Posted on 2026-03-04 05:42:12 MST