Back to projects

Ecommerce for a client

In development

Sublime Ecommerce

An online store for a sticker, sublimated T-shirt, DTF, and vinyl business: an admin-managed catalog, orders, custom orders with Custom Lab, and self-hosted deployment on a VPS.

A client project, in development. Features run in staging; the store already lives on the client's domain, in maintenance mode while the real catalog is loaded. It started on Vercel with a managed database, and I migrated it to a self-managed VPS.

Outcome: 298automated tests in the repository, over 18 versioned database migrations.

  • Next.js
  • TypeScript
  • PostgreSQL
  • Docker
  • Traefik

Architecture

Infrastructure on the VPS
  1. DomainStore on the client's domain; password-protected stagingDNS
  2. ProxyAutomatic HTTPS and routing by domain; www redirects to the main domainTraefik
  3. AppOne container per environment, built with its own configurationNext.js · Docker
  4. DatabaseOne database per environment, unreachable from the internetPostgreSQL
  5. BackupsDaily, with an encrypted off-server copy and a tested restorerclone · Drive

Feature status

Implemented in staging

  • Catalog managed from an admin panel: categories, images, variants, prices, and stock with auditing.
  • Orders with stock reservation and rule-based shipping.
  • Sublime Custom Lab: stickers with background removal, outline, and automatic sheet layout; the server generates the PNG and the PSD for the plotter.
  • T-shirt Custom Lab: own or catalog design, placement, and size; the server generates the mockup and a 300 dpi print file.
  • Customer accounts, points of sale, and a home page editable from the panel.
  • Custom orders copied automatically to Google Drive, plus a notification queue.

Production infrastructure

  • Migration from Vercel and a managed database to a VPS with Docker Compose.
  • Automatic staging deploys on push; the store is deployed by hand.
  • Daily backups: 14 days on the server and 60 days encrypted on Google Drive.
  • Maintenance mode: the public sees a notice page while the panel stays available.

Pending

  • Payments with Mercado Pago, subject to client approval.
  • Customer emails and password recovery, once a provider is chosen.
  • AI background removal in Custom Lab.
  • Opening the store to the public.

Architecture

  • Next.js App Router with strict TypeScript, in standalone mode inside Docker.
  • PostgreSQL with versioned migrations; each catalog change, its stock movement, and its audit entry are saved in a single SQL statement.
  • Files on disk with public and private paths; custom order attachments can only be downloaded from the panel.
  • Admin authorization checked on the server for every page and action.

Deployment decisions

  • One image per environment: some pages are generated at build time and need that environment's configuration, passed as a secret and never stored in the image.
  • Pull-based deploys: the VPS reads GitHub with a read-only key, and GitHub holds no server credentials.
  • Traefik shared with other services on the same VPS: each app only adds its labels.
  • The database only listens on the server itself; it is never exposed to the internet.

Code sample

Pull-based automatic deploy (excerpt)bash
# Runs every minute: deploy the watched branch when it has a new commit.
git --git-dir="$REPO" fetch --quiet --prune origin "+refs/heads/$BRANCH:refs/heads/$BRANCH"
SHA=$(git --git-dir="$REPO" rev-parse "refs/heads/$BRANCH")

[ "$SHA" = "$(cat .deployed-sha 2>/dev/null)" ] && exit 0   # already live
[ "$SHA" = "$(cat .last-attempt 2>/dev/null)" ] && exit 0   # failed once, wait for a new commit
echo "$SHA" > .last-attempt

NEW=$(mktemp -d "$ROOT/.src.XXXXXX")
git --git-dir="$REPO" archive "$SHA" | tar -x -C "$NEW"
mv "$ROOT/src" "$ROOT/src.previous" && mv "$NEW" "$ROOT/src"

if bash "$ROOT/src/deploy/deploy-staging.sh"; then
  echo "$SHA" > .deployed-sha
else
  echo "deploy failed: staging keeps the previous version"
fi

Case limits

  • The store is not open to the public yet: it is in maintenance mode.
  • There are no online payments; they depend on client approval.
  • No sales or business data from the client is published.

Links