Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quadru — Square Item Library for Shopify

Quadru is discontinued and is no longer operated as a hosted service.

Shopify no longer accepts apps that connect to a point-of-sale system outside of Shopify (App Store Requirement 1.1.8). Quadru is such an app, so it was withdrawn from the Shopify App Store in August 2026.

The code is published here under AGPL-3.0. You can run it yourself. That rule governs what Shopify lists in its App Store — it does not stop a merchant from installing their own app on their own store.

Project page: https://quadruapp.vercel.app

Quadru connects a Shopify merchant's Square Item Library to their Shopify admin. Compare both catalogs side by side, import Square items into Shopify as draft products, export Shopify products to Square, and declare rules for what belongs on which platform — with inventory for every variant visible on both sides.

Features

  • Connect a Square account via Square's own OAuth
  • Catalog page compares both catalogs side by side — synced, drifting, Shopify-only, and Square-only, with per-variant price and stock checks
  • Import Square items into Shopify as draft products, one confirmed click at a time; export Shopify products to Square the same way
  • Durable product links keep imported/exported pairs matched; SKUs only suggest matches, the merchant confirms them
  • Rules declare what lives only in Shopify or only in Square; the Catalog flags anything that breaks a rule
  • Inventory page shows every variant's stock on both platforms, searchable by product or SKU, with CSV export
  • Optional two-way inventory synchronization keeps linked variants aligned at the merchant's mapped Square and Shopify locations
  • Shopify Sidekick tools provide a catalog overview, look up a SKU, and suggest a new SKU from the store's existing naming patterns
  • Shopify products are crawled from the Admin API and kept in a durable snapshot, so Compare and Inventory read one local copy instead of re-crawling the store on every page load; products/update, products/delete, and inventory_levels/update webhooks keep it current
  • Item detail view: variations, prices, and inventory per location
  • Manual refresh with durable logs, so you can see what happened and when
  • Multi-tenant: every shop's data and Square connection is isolated
  • Square access and refresh tokens are encrypted at rest (AES-256-GCM)

What the database holds

Quadru is not a stateless proxy over the two APIs. It keeps a working copy of both catalogs, plus the operational records the sync engine needs to make a retried write safe to replay:

  • Both catalogs. The Square cache (items, variations, SKUs, prices, categories, locations, per-location inventory) and the Shopify snapshot (ShopifyCatalogSnapshot: every variant's title, SKU, price, inventory quantity, product type and status, timestamps, and image URLs).
  • A SKU index for Sidekick (SidekickSkuEntry): per SKU, the product and variant name, category, status, inventory, price, and currency.
  • Raw webhook payloads (WebhookInbox): each verified delivery is stored byte-for-byte before it is processed, so a retry replays what was actually delivered. Catalog and inventory payloads can contain titles, SKUs, prices, and quantities.
  • Links and write records: ProductLink/VariantLink pair the two catalogs by ID, and SyncEvent/ProviderOperation/SyncJob record every inventory write, including the exact request body sent to the provider.

Detailed operational records are rolled into per-day counts and deleted after DETAILED_RECORD_RETENTION_DAYS (30 days); the per-day counts hold no payload, token, or product detail. Uninstalling deletes all of it.

The canonical, single-source description lives in app/lib/data-practices.ts: the /privacy page renders from it, app/.server/retention.ts takes its window from the same constant, and tests/data-practices.test.ts fails the build if the two drift apart. A new store added to prisma/schema.prisma belongs there in the same change.

Tech stack

Running your own instance

Quadru is a long-lived Node process. It elects a Postgres-backed leader and runs its background workers inside the web process, so it needs a host that keeps a process alive.

Suitable: a VPS with systemd (see ops/systemd/quadruapp.service), Docker on any host, Render, Railway, or Fly.io.

Not suitable: Vercel, Netlify, Cloudflare Workers, or any serverless target. Request-scoped functions freeze after responding, which strands the leader lease and breaks in-process safety locks that prevent double-applying stock.

What you need

  • Postgres 15 or later
  • A Shopify Partner account, and your own public app
  • A Shopify Partner API token — the billing gate is asserted at boot
  • Shopify App Pricing plans configured on your app
  • A Square developer application
  • Optional: an Alibaba Cloud Model Studio key for the SKU suggestion feature. The app degrades gracefully without it.

Configuration

Copy .env.example to .env and fill it in. Every required variable is documented in that file. Generate the two encryption keys with openssl rand -hex 32.

Copy shopify.app.toml.example to shopify.app.toml and set your own client ID, handle, and URLs.

Known issues for self-hosters

  • Plan handles are a hardcoded allowlist. app/.server/shopify/app-pricing.ts accepts only quadru-monthly and shopify-test. Your Partner plan will have a different handle, and every shop is denied until you change it. This needs to become environment-driven.
  • The marketing and legal routes (/, /terms, /privacy, /changelog) carry Quadru's own copy. Replace them with your own before serving them to anyone.

Quickstart (local dev)

  1. Clone the repo and install dependencies:

    git clone https://github.com/ifrederico/quadru.git
    cd quadruapp
    npm install
  2. Copy .env.example to .env and fill it in. You'll need a Shopify Partner app and a Square developer app; .env.example documents every variable, including how to generate the secrets.

  3. Copy shopify.app.toml.example to shopify.app.toml and fill in your app's client_id. If you develop against a separate dev app (recommended), also copy shopify.app.dev.toml.example to shopify.app.dev.toml with the dev app's client_id; both files are gitignored, so repeat this on every machine you develop from.

  4. Run the dev server:

    npm run dev

Testing

npm test
npm run typecheck

License

AGPL-3.0. See LICENSE. Run it freely; if you modify it and offer it over a network, publish your modifications under the same license.

Original code copyright © 2026 ifrederico. Contributors keep ownership of their contributions under the terms in CONTRIBUTING.md.

The "Quadru" name and logo are not covered by that license — forks should use their own branding. "Square" and "Shopify" are trademarks of their respective owners.

Support

None. This project is not maintained. Issues and pull requests may go unread.

About

Square Item Library for Shopify — compare, import, and sync a Square catalog with Shopify. Discontinued; source published under AGPL-3.0 for self-hosting.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages