ReleasedAstro · Cloudflare · Stripe

Handmade commerce,
without handmade operations.

Wooly Topic had fourteen years of products, photographs, options, and buyer trust on Etsy. We moved that history into a first-party shop, then built the owner a back office that runs orders, content, customer follow-up, and Pinterest from one place.

The Wooly Topic wordmark laid over an arrangement of colourful needle-felted planets
The outcome

A mature Etsy shop became an owned system.

The storefront is the visible half. Behind it is the machinery needed to take real money, keep the catalogue current, answer customers, recover from failure, and bring people back without asking the owner to become a systems operator.

13
products moved
72
variants preserved
474
reviews brought across
119
catalogue pins queued
The commerce spine

One path from product choice to a finished order.

Product and option data came from a resumable Etsy extraction, but Etsy-shaped data stops at the import boundary. The shop reads its own catalogue model; checkout prices every item again on the server; and the Stripe webhook is the only authority that creates a paid order.

From there the same record drives confirmation mail, the owner's fulfilment screen, a no-login customer status link, tracking, refunds, and the later review request. Each step has one durable source of truth instead of a chain of copied notes.

  1. Browsecatalogue + variants
  2. Payserver-priced Stripe
  3. Recordsigned webhook + D1
  4. Fulfiladmin + tracking
  5. Returnreview request + moderation
The backend is part of the product

A small shop should not need a small engineering department.

Every recurring operational task was given a place, a visible state, and a recovery path. The protected admin is deliberately plain: it is for finishing work, not admiring a dashboard.

  • Orders and fulfilment

    Paid orders land in D1 from a signed, idempotent Stripe webhook. The admin moves each order through production, adds tracking, sends shipment mail, and can issue and reconcile refunds.

  • Catalogue control

    Prices, variant prices, primary photography, ordering, visibility, and uploads can change from the admin. Storefront display and server-side checkout read the same overrides, so the price shown and charged cannot drift.

  • Reviews and follow-up

    A daily worker finds fulfilled orders old enough for a review request. One-time links gate submissions; photographs live in R2; moderation decides what reaches product pages and the homepage.

  • Content and correspondence

    Newsletter posts, contact-form messages, routed email, and social reels sit beside the commerce tools. Customer mail is stored durably before it is forwarded to the working inbox.

  • Backups that announce failure

    A second Worker exports the D1 database to R2 every Monday and retains twelve snapshots. The dashboard calls out an overdue backup instead of making silence look healthy.

  • Access that fails closed

    Cloudflare Access protects the back office, and the Worker verifies the identity rather than trusting that a header happens to exist. Missing policy or binding means no admin data is read.

A large orange needle-felted planet holding a nested set of smaller felted planets
Nesting Solar System
A round yellow and orange needle-felted sun on a white background
Needle Felted Sun
Pinterest and social publishing

A queue that protects the cadence—and tells the truth.

The pipeline handles catalogue photography, newsletter images, and vertical video without turning a scheduled Worker into a black box. The owner can see what is next, publish one immediately, inspect failures, change the destination board, or safely seed the catalogue again.

  1. Choose the source

    Seed from the current catalogue, attach a published newsletter, or upload a vertical reel with a generated cover frame.

    Catalogue · Newsletter · Reel
  2. Create durable work

    The queue records what should be published and gives every selected destination its own status, attempt count, error, and eventual external ID.

    Queued
  3. Take the next normal slot

    Cloudflare cron opens one slot at 13:00, 17:00, and 21:00 UTC. A newsletter or reel takes priority over a catalogue pin without creating a fourth post that day.

    Scheduled
  4. Publish or process

    Image Pins publish in one request. Video is registered, streamed from R2, marked as working, and checked every ten minutes until Pinterest finishes processing it.

    Working
  5. Record the truth

    Success stores Pinterest's ID and timestamp. Failure keeps a readable reason and retries, then moves aside after three attempts so one bad asset cannot block the queue.

    Published · Failed
Fresh at publish time

The catalogue queue stores pointers, not stale ads.

A queued row identifies the product, offer, and photograph. Title, description, link, alt text, current price, and current image URL are composed when the slot opens. An admin price or gallery edit therefore reaches a future Pin without rebuilding or reseeding it.

OAuth that can survive

Rotating credentials live where the Worker can rotate them.

The fixed Pinterest app secret stays a Worker secret. Short-lived access and refresh tokens live in a single constrained D1 record, because a Worker cannot rewrite its own deployment secrets. The chosen board and actual granted scopes are visible in the admin.

One shared social model

Content and destinations are separate records.

A newsletter or reel is stored once; each destination owns its delivery state. Pinterest is implemented today. Instagram and TikTok appear in the reel composer as explicitly unavailable backends, so the interface communicates the roadmap without pretending they already post.

The deployed shape

Static where possible. Stateful where necessary.

Astro and Cloudflare Workers serve the storefront. D1 holds operational state; R2 holds customer uploads, reels, raw mail, and backups; Stripe handles payment; Resend handles transactional mail. A second Worker owns cron and inbound email because those events need entry points the Astro adapter does not expose.

Storefront
Astro 7 · Cloudflare Workers
State
D1 · R2
Commerce
Stripe Checkout · signed webhooks
Operations
Cloudflare Access · cron · Email Routing
Reach
Merchant feed · IndexNow · Pinterest API
See it in use

The shop is live.

The felt is handmade in Glencoe, Ontario. The system around it no longer has to be.

Visit woolytopic.com