JT
  • Home
  • Projects
  • Extras
  • Contact

© 2026 Joshua Tjhie. All rights reserved.

GitHubLinkedInEmail
Back to Projects
  1. Home
  2. Projects
  3. Dotdeck (Placeholder)
2024-05-18

Dotdeck (Placeholder)

A hub for sharing copy-pastable developer decks — dotfiles, CLI tweaks, and snippets.

Full-stack web app that makes it easy to publish, browse, search, and discuss scoped configuration snippets called "decks".

Next.jsExpressMySQLTooling
Dotdeck (Placeholder)

Quick Stats

Role: Full-Stack Developer
Duration: Ongoing
Next.js 14Express 4MySQLJWT / TanStack Query

Links

Live SiteAPI Docs

Dotdeck

Dotdeck is live. The write-up below covers the architecture, feature decisions, and lessons from building the first production full-stack project I've shipped solo.

My previous approach to sharing dotfiles was a monolithic repo nobody could navigate. Dotdeck trims that pain by focusing on standalone, copy-pastable "decks" you can browse, search, fork, and discuss without peeling through hundreds of commits.

Problem space

Finding a single snippet buried in a six-year-old forum thread is exhausting. GitHub Gist is too loose — no tagging, no discovery, no discussion adjacent to the code. Dotdeck fills the gap:

  • Decks are intentionally scoped: title, tags, description, and one or more code blocks.
  • Built-in reactions and threaded comments keep discussion near the snippet.
  • Full-text search with pagination makes discovery fast.

Feature overview

Dotdeck homepage
Homepage deck feed — cards show title, tags, like count, and language badge.

Core features shipped:

  • Authentication with JWT (register / login) and role-based access control — admin, mod, user.
  • Like / dislike counts with optimistic UI updates via TanStack Query.
  • Threaded comments with real-time count badges.
  • Image uploads (WebP, compressed via Sharp) for deck thumbnails.
  • Admin panel for managing tags, decks, users, and audit logs.
  • Fully documented OpenAPI 3.0 spec via Swagger at /docs.

Architecture

LayerTech
Front-endNext.js 14, React 18, TypeScript, Tailwind, shadcn/ui, TanStack Query
Back-endExpress 4, MySQL, multer + Sharp, JSON Web Tokens
Dev / opsCampus:Cloud Node instances, pnpm workspace toolchain

The monorepo splits into apps/web (Next.js) and apps/api (Express). Shared types live in packages/types so API responses and client expectations can't drift.

Deck schema


Authentication flow

  1. Client POSTs credentials to /auth/login.
  2. API validates against bcrypt hash, issues a short-lived accessToken and a httpOnly refreshToken cookie.
  3. TanStack Query's defaultOptions.queries.onError intercepts 401s and triggers a silent token refresh before retrying.

Image pipeline

Uploaded thumbnails go through a Sharp pipeline before storage:

# resize to 800×600 max, convert to WebP at quality 80
sharp(buffer)
  .resize(800, 600, { fit: 'inside' })
  .webp({ quality: 80 })
  .toBuffer()

Average upload size dropped from ~1.2 MB (raw PNG) to ~85 KB (WebP) — a 93 % reduction with no perceptible quality loss at card thumbnail sizes.

Deck creation flow — drag-and-drop upload, tag selection, and live preview.

What I'd do differently

  • MySQL → PostgreSQL — full-text search in MySQL required custom FULLTEXT indexes that fight the ORM. Postgres tsvector is cleaner.
  • Separate read replicas — the admin audit log query is expensive and doesn't need to hit the write primary.
  • Rate limiting from day one — added it in week three after a stress test revealed the comment endpoint had no throttling.

Using inline code for the key design tension: keeping the refreshToken in an httpOnly cookie means the client can't read it — but it also can't detect expiry proactively, which is why the interceptor retry pattern was necessary.

Building the whole stack yourself means every trade-off is yours to own — which is exactly the point.

Visit Dotdeck

Have thoughts?

Curious what others see or think

Feel free to reach out or leave feedback

Share Feedback

Prefer email? joshuatjhie@pm.me