Skip to content
This repository was archived by the owner on Oct 22, 2026. It is now read-only.
dosbenjaminPublic archive

About

Merge Catalog helps merchants that use Shopify to normalize product descriptions, extract structured product data into metafields

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

51 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Merge Catalog

Merge Catalog is a Shopify operations app built for Merge Studio. It helps merchants normalize product descriptions, extract structured product data into metafields, review every proposed change, and apply only explicitly approved updates.

It is deliberately not a general-purpose AI copywriting tool. The product is designed around controlled catalog maintenance, evidence-aware suggestions, and a complete application history.

Product workflow

  1. A merchant selects up to 25 products with Shopify's Resource Picker.
  2. Merge Catalog snapshots the current product data before processing.
  3. Background jobs normalize descriptions and extract selected structured fields.
  4. The merchant edits, approves, or rejects descriptions and metafields separately.
  5. A separate background job applies only approved changes through the Shopify Admin GraphQL API.
  6. History records the result and provenance of every application attempt.

Merge Catalog never writes AI output to Shopify automatically.

Current features

  • Operational dashboard for catalog jobs and status counts.
  • Cleanup jobs limited to 25 products.
  • Configurable description normalization and metafield extraction scopes.
  • Optional per-shop brand tone guidance.
  • Product snapshots captured before processing.
  • OpenAI-backed description normalization and structured extraction.
  • Zod validation before AI output is persisted.
  • Per-field confidence, source, evidence, and review status.
  • Manual editing and separate approval for descriptions and metafields.
  • Dynamic Shopify metafield mappings and definition management.
  • Selective application through Shopify Admin GraphQL mutations.
  • Job cancellation and rejection without Shopify writes.
  • Apply history with source summaries and Shopify responses.
  • Internal per-shop usage and estimated OpenAI cost tracking.

Technology

  • Shopify embedded app using Remix, React, TypeScript, and Vite.
  • Shopify Polaris and App Bridge.
  • Shopify Admin GraphQL API.
  • Prisma with PostgreSQL 18.
  • pg-boss for snapshot, AI-processing, and apply queues.
  • OpenAI behind an AiProvider abstraction.
  • zod for structured AI-output validation.
  • devenv and Nix for the local development environment.
  • Docker Compose for production deployment.

Prerequisites

  • Nix
  • devenv
  • A Shopify Partner account and development store
  • A Shopify app configuration linked through Shopify CLI
  • An OpenAI API key

Codex, Git, curl, and OpenSSL are inherited from the host when available; they are not project-level Nix dependencies.

Local setup

Enter the reproducible development shell:

devenv shell

The shell provides Node.js 24, pnpm, Shopify CLI, and PostgreSQL 18. Install JavaScript dependencies:

pnpm install

Create the local environment file:

cp .env.example .env

Replace all placeholder credentials in .env. devenv supplies the local database URL as:

postgresql://merge_catalog@127.0.0.1:5432/merge_catalog

Start PostgreSQL in a separate terminal:

devenv up

Generate the Prisma client and apply development migrations:

pnpm prisma generate
pnpm prisma migrate dev

Link the local checkout to the intended Shopify app if needed:

pnpm config:link

Start Shopify development mode:

pnpm dev

Shopify CLI manages authentication, the development tunnel, callback URLs, and the embedded-app launch flow.

Environment variables

Variable Required Purpose
SHOPIFY_API_KEY Yes Shopify app client ID.
SHOPIFY_API_SECRET Yes Shopify app client secret.
SHOPIFY_APP_URL Yes outside Shopify CLI dev Public application and callback URL.
SCOPES Yes Shopify access scopes; defaults to write_products.
DATABASE_URL Yes PostgreSQL connection used by Prisma and pg-boss.
OPENAI_API_KEY Yes OpenAI API credential used by the initial AI provider.
OPENAI_MODEL No Model override; defaults to gpt-4.1-mini.
HOST No Local runtime host override.
PORT No Application port; defaults to 3000.
SHOP_CUSTOM_DOMAIN No Optional custom shop domain.
INTERNAL_USAGE_VIEW_ENABLED No Enables the internal usage page outside development.
INTERNAL_USAGE_ALLOWED_SHOPS No Comma-separated allowlist for the internal usage page.

Never commit .env, Shopify credentials, OpenAI keys, or production database credentials.

Development commands

pnpm dev                 # Run Shopify development mode
pnpm test                # Run the Vitest suite
pnpm lint                # Run ESLint
pnpm build               # Build client and server bundles
pnpm exec tsc --noEmit   # Type-check without emitting files
pnpm prisma format       # Format the Prisma schema
pnpm prisma generate     # Generate Prisma Client
pnpm prisma migrate dev  # Create or apply development migrations

After meaningful backend, Prisma, or route changes, run:

pnpm lint
pnpm build
pnpm exec tsc --noEmit

For Prisma changes, also run pnpm prisma format and pnpm prisma generate. Database changes must always use migrations; do not edit PostgreSQL manually or reintroduce SQLite.

Architecture and safety boundaries

The Remix action that creates a cleanup job only validates the selection and enqueues work. Long-running processing runs through three pg-boss queues:

catalog-cleanup
    -> snapshot selected Shopify products
    -> catalog-ai-processing
       -> validate and persist drafts
       -> merchant review
          -> catalog-apply-approved
             -> apply approved Shopify updates

The main boundaries are intentional:

  • Always snapshot before processing.
  • Keep batches at or below 25 products.
  • Do not run batch processing inside Remix loaders or actions.
  • AI processing never writes directly to Shopify.
  • Description and metafield approvals remain separate.
  • Shopify mutations live behind focused server-side services.
  • Only merchant-approved changes are eligible for application.
  • ApplyResult preserves status, errors, Shopify responses, and source history.

Data model

The core Prisma records are:

  • Shop and ShopUsage
  • CatalogJob and CatalogJobItem
  • ProductSnapshot
  • ProductDraft and ExtractedField
  • MetafieldMapping
  • AiRun
  • ApplyResult

Snapshots, product JSON, variants, metafields, extracted values, AI inputs and outputs, source summaries, and Shopify responses use PostgreSQL JSONB fields.

Application screens

  • Dashboard
  • New Cleanup Job
  • Job Progress
  • Review Queue
  • Metafield Settings
  • History and Apply Result detail
  • Internal Usage, restricted to development or explicitly allowlisted shops

Production deployment

The root Dockerfile builds a minimal multi-stage Node.js 24 image. The root compose.yaml runs the application with PostgreSQL 18 and expects an existing external cloudflared-net network for reverse-proxy access.

Set the required production variables, create the external network if it does not already exist, and start the stack:

docker network create cloudflared-net
docker compose up -d --build

Prisma Client is generated while the image is built, and the production container applies pending migrations before starting Remix. Keep production secrets outside the repository.

Project documentation

Product scope

The v1 product intentionally excludes full catalog synchronization, automatic scheduling, SEO scoring, keyword research, complex rollback, merchant prompt builders, fine-tuning, unlimited batches, and mass automatic metafield-definition creation.

About

Merge Catalog helps merchants that use Shopify to normalize product descriptions, extract structured product data into metafields

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages