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.
- 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, andinventory_levels/updatewebhooks 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)
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/VariantLinkpair the two catalogs by ID, andSyncEvent/ProviderOperation/SyncJobrecord 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.
- React Router 7 (framework mode) for routing and SSR
@shopify/shopify-app-react-routerfor Shopify OAuth, sessions, and webhooks- Prisma + Postgres for session storage and the cached Square catalog
- Polaris web components (
s-*elements) for the embedded admin UI
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.
- 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.
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.
- Plan handles are a hardcoded allowlist.
app/.server/shopify/app-pricing.tsaccepts onlyquadru-monthlyandshopify-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.
-
Clone the repo and install dependencies:
git clone https://github.com/ifrederico/quadru.git cd quadruapp npm install -
Copy
.env.exampleto.envand fill it in. You'll need a Shopify Partner app and a Square developer app;.env.exampledocuments every variable, including how to generate the secrets. -
Copy
shopify.app.toml.exampletoshopify.app.tomland fill in your app'sclient_id. If you develop against a separate dev app (recommended), also copyshopify.app.dev.toml.exampletoshopify.app.dev.tomlwith the dev app'sclient_id; both files are gitignored, so repeat this on every machine you develop from. -
Run the dev server:
npm run dev
npm test
npm run typecheckAGPL-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.
None. This project is not maintained. Issues and pull requests may go unread.