🪟 Windows TippsAndroid 17: Neue Version ist hier – Das ist alles neu(16.09.2026 um 11:40 Uhr)
🕵️ Hacking12 Best CASB Solutions Compared (2026): Features & Pricing(16.09.2026 um 09:31 Uhr)
🕵️ Hacking12 Best CIEM Tools Compared (2026): Features & Pricing(16.09.2026 um 09:37 Uhr)
🪟 Windows TippsAndroid 17: Neue Version ist hier – Das ist alles neu(16.09.2026 um 11:40 Uhr)
🕵️ Hacking12 Best CASB Solutions Compared (2026): Features & Pricing(16.09.2026 um 09:31 Uhr)
🕵️ Hacking12 Best CIEM Tools Compared (2026): Features & Pricing(16.09.2026 um 09:37 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 4 Min Lesezeit
0

6 things I learned building an app for Shopify's new native B2B

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

This spring, Shopify quietly did something big: native B2B — Companies, catalogs, net terms — became available on all plans, not just Plus. Millions of stores can now sell wholesale without a $2k/month subscription or a heavyweight app suite.



I spent the last month building a small app on top of these APIs (Tradelane, it handles the wholesale application/approval flow that Shopify left out). Here's what I wish I'd known on day one.






1. One email = one company contact. Plan for it.



The constraint that bit me hardest: a customer email can only be the main contact of one company. If a buyer applies twice, or a merchant re-approves someone whose email is already attached to another company, companyCreate succeeds but the contact assignment fails silently unless you handle it.



My fix: treat "approved, but contact not assigned" as a first-class state with a clear message to the merchant, instead of pretending the whole operation failed. Partial success with an explanation beats a rollback nobody understands.






2. The app proxy is underrated for public-facing features



If your app needs a public page on the merchant's storefront (forms, portals, status pages), Shopify's app proxy gives you a route at store.com/apps/your-app/... that forwards to your server with an HMAC signature. Same origin as the storefront, no CORS, no theme code.



Two practical notes: authenticate.public.appProxy(request) (in the Remix/React Router template) gives you the shop and an admin API client, and because the page is same-origin you can later embed it in a theme app extension with a plain <iframe> — no postMessage gymnastics.






3. React escapes your <style> tags. Yes, really.



I shipped a form whose fonts silently fell back to Times New Roman. The culprit:




CODE
<style>{`
body { font-family: -apple-system, "Segoe UI", sans-serif; }
`
}</style>






React escapes text children — including inside <style> — so "Segoe UI" becomes &quot;Segoe UI&quot;, which is invalid CSS, which invalidates the whole declaration. Border-radius from the same stylesheet worked fine, so it took me days to notice. Same thing breaks url("data:...") values.



The fix is the escape hatch that exists precisely for this (spaces added between the braces so this renders on dev.to — in real code they'd be together):




CODE
<style dangerouslySetInnerHTML={ { __html: `...` } } />









4. Validate EU VAT numbers with VIES — it's free and merchants love it



If your app touches B2B in Europe, the EU's VIES service validates VAT numbers (and returns the registered business name) via a free API. Fake wholesale applications are more common than I expected, and "VAT valid ✓" next to an application turned out to be one of the most-mentioned features in feedback.



Cache the result — VIES is slow and occasionally down, so check once per application and store valid | invalid | unavailable.






5. hCaptcha over Turnstile for multi-tenant storefronts



My form renders on any merchant's domain via the app proxy. Cloudflare Turnstile wants per-hostname configuration; hCaptcha sitekeys work on any hostname by default. For a multi-tenant Shopify app, that's the whole decision. (Also: append ?hl=en to the script URL, or the widget renders in the visitor's browser language while the rest of your form is English.)






6. Fire-and-forget your emails, but never your writes



Every notification email in my submit path is void sendEmail().catch(log) — if the email provider hiccups, the application still saves and the buyer still sees the success page. A missed email is a degraded state; a lost application is a lost customer. Decide explicitly which failures are allowed to break the request and which aren't.






The gap, if you're looking for one: native B2B handles pricing, catalogs and payment terms well, but onboarding is still rough. The free Forms app can take applications, yet it creates the Company before approval (junk piles up in the admin), skips VAT validation, and doesn't assign catalogs. That's the hole I built Tradelane into. If you're building on the Companies API and hit something weird, my DMs are open. Happy to compare notes.

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
2 Quellen
CVE-2026-88255 | ZenHive mpp up to 0.16.1 Duplicate Submission Gate lib/mpp/replay.ex reserve_hash_atomic input validation (EUVD-2026-80256)
1 Quelle
Android 17: Neue Version ist hier – Das ist alles neu
1 Quelle
Die entscheidende Hürde: Xpeng will deutsch und nicht chinesisch sein
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten 6 things I learned building an app for Shopify's new native B2B

Thematisch verwandte Begriffe: things, learned, building, Shopifys · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...