Backend: A separate Django service (already working) with APIs that can “upsert” a Shop/Partner when the app is installed.
Shopify Admin App: A separate project created via Shopify CLI (shopify app init) using the React Router template. This app is embedded in the Shopify Admin and is where I want to keep all the Admin UI code the merchant sees (home page, routes, components, etc.).
Single repo for Admin UI: I prefer not to spin up a separate frontend project; I want to keep the Admin UI inside the Shopify CLI app project (and possibly add POS UI extensions in the same app later).
Local dev: Both services run locally. I’ve got the Shopify app running, but it’s not talking to the Django backend yet (HTTPS/CORS/tunneling confusion).
What I want it to do
On install, the Shopify app should finish OAuth and then call the Django APIs to create/record the shop (and any partner data) in the DB.
After installation, the embedded Admin app should load a simple home page showing that the “Shop was created” (basic proof the loop works).
I want a clear answer on where to put URLs (Application URL, Redirect URL) and which file(s) in the Shopify CLI app should perform the “after-install → call Django” step—while keeping the Admin UI in the same CLI app project.
Later, you’ll add a POS extension in the same app.
Currently, I’m using Cloudflare to get an HTTPS URL, so let’s call my ‘https://xxx.trycloudflare.com/’ as my backend running locally with a tunnel URL.
Problem:
Separation of concerns confusion: The Shopify CLI app comes with its own Node/Express (or Remix) server for OAuth and API routes. I’m unsure how that should coordinate with my separate Django backend.
Networking in local dev: My Shopify app is accessible via a tunnel (e.g., shopify app dev URL), but your Django backend might be on http://localhost:8000 (no public HTTPS). The Admin app can’t reliably call it without exposing it over HTTPS and handling CORS.
Auth context for calls: You’re unsure from where to call Django—during OAuth server-side (right after token exchange) or client-side from the embedded React app using a session token—and what headers/verification are expected.
Which URLs go where: The mapping between application_url, OAuth callback(s), and internal routes.
@JordanFinners hey, My Django backend is part of a larger ecosystem—it serves multiple front-ends and user types. The Shopify admin app (and later the POS extension) is just one of those front-ends that communicates with the same backend.
I have a similar set up, where a core API is serving multiple projects, including a Shopify Admin and extensions, and other frontends that are not Shopify specific.
Your life will be a lot easier if you take the time to set up a single monorepo.
You can keep your Django project as a subdirectory in this project, and the Shopify Admin app can be a “sibling” to this Django project, but communicate over API.
I highly recommend using ngrok or a tunneling service that offers static URLs for tunneling. That way you can keep URLs straight as you need to connect the Shopify Admin to your Django API during install, as well as potentially proxy requests to it from the Shopify frontend.
Then you can use the Shopify CLI to generate extensions in this same monorepo in a separate extensions directory. Those extensions will communicate with either your Shopify Admin app, or potentially just Django directly.
@Dylan this is our plan(thought):
Our Django backend is already a full-blown, heavy-usage service that supports multiple front-ends and user types. Because it’s critical and in production, we don’t plan to move or merge it into the Shopify Admin app project. For our Shopify integration, we will build the Admin app and the POS extension within a single front-end project (via the Shopify CLI), and that project will call our existing Django backend over its APIs. This keeps the backend separate, stable and scalable, while letting the Shopify-specific UI live in one place.
You’ll need to use an HTTP API to communicate from the extensions and Shopify Admin API to your Django Admin.
I’m making recommendations on how to organize your projects code and establish a HTTP tunnel to communicate back to your Django app from the Shopify Admin app and Shopify extensions.
I already have a Django backend service running (on localhost:8000 locally) and accessible via a Cloudflare tunnel: https://tamil-established-essence-korean.trycloudflare.com.
This Django backend is fully built and in heavy use; it supports multiple front-ends, not just our Shopify app. So I cannot merge it or copy it into the Shopify app project.
I will keep the Shopify Admin app and any future POS extension together (in the same project codebase). They will communicate with my Django backend over its APIs.
What I need to figure out is:
In my shopify.app.toml file for the Shopify CLI app, what should the application_url be?
What should the redirect_urls be (for OAuth callback)?
Which URLs go into the webhook config?
My goal: when someone installs the Shopify app:
The app does the OAuth handshake and token exchange.
After OAuth, the Shopify app calls the Django onboarding endpoint (/shopify-partners/onboarding on my backend, via Cloudflare tunnel) to create the shop + partner records.
Then the merchant is shown a Home page in the Shopify Admin app, which will show data from the backend (or simply “successfully installed”).
Right now the install process is unstable: sometimes the install logic works and shops are created; sometimes the app crashes or loads nothing. I suspect some mis-configuration in the shopify.app.toml or the network routing between the tunnel + OAuth + backend call.
For clarity: In the Django backend my onboarding endpoint lives at: https://tamil-established-essence-korean.trycloudflare.com/shopify-partners/onboarding
It accepts the shop domain + token and returns the shop details (if existing) or creates a new record.
So what I need your help with is: exactly what application_url, redirect_urls, and webhook uris must look like in shopify.app.toml given my tunnels above (Shopify app tunnel and Django backend tunnel). Once I set them correctly, I want to test locally (shopify app dev + cloudflare tunnel) and get a stable install → onboarding flow working.
Thanks again for your help — I’m ready to set this up step by step.
The application_url is the home page of your Shopify admin app.
The redirect_uris are for OAuth.
It’s really up to you how you’d like to handle that.
If I were you, I’d opt to use Shopify’s managed installs and skip trying to implement OAuth by hand. That’s probably most of your problems right now.
Instead, you could set the application_url to be your Shopify Admin app, it handles Shopify session token management, and you can use the Shopify Admin App as a simple client that interfaces to your Django app or directly to your database to store merchant records.
@Dylan so you are saying ‘application_url’ will be the home page of my Shopify admin app?
That’s correct.
What exactly will be the URL?
Whatever you define it to be in your shopify.app.toml . It’s really up to you. If you want to host your Shopify Admin app on a subdomain of your production domain, or as a subpath with a reverse proxy in front. The sky is the limit.
Hey @Dylan I know it might be too much to ask. I’m still srtuggling to understand it. Would it be possible for you to get on a virtual meet and i could show you my implementation and then you could help me fix the issue. I know it will take your time but if you could, let me know, i can share the virtual meet details. Other than that, as per your advice, i can try a few things to understand it well. Thanks a lot for the support.
Yes, Shopify app development has a learning curve.
What you’re aiming for is definitely possible, I do something very similar, with Shopify being a single frontend among many.
I give my time and expertise freely on this forum, just because I enjoy helping others. But for a 1:1 private consultation I’d have to charge for my time, I’m sure you understand.
Feel free to email me at dylan [ at ] getverdict.com if that interests you. But otherwise, happy to continue our chat on the forum.
Given your setup I’d recommend having everything in your TOML file point just to your Shopify App backend, and let that make any API calls to your Django application.
If you try and mix your URLs between the two I think it’ll end up being a load of complexity and confusion for you.
I have similar setup but my backend is .net core api. I did face problems when i was setting up the frontend to talk to backend.
here is what i did to make it work.
Frontend:
I leave the toml file as is.
I created a .env file which has all my backend config and api url
Backend:
I run my backend api for example and its on port 5000
I then open another powershell and run cloudflared tunnel --url localhost:5000
once i get the cloudflare url, i update my .env file.
Clarifying application_url for dev vs. production (embedded app)
Context:
I’m building an embedded app. During development, I’ve been calling my own backend from the embedded Admin UI and everything works. When I got ready to ship, I noticed my app had stopped loading because the application_url wasn’t pointing at a stable, deployed URL yet (I was still on a tunnel/local setup).
What I think is correct:
In dev, it’s fine to keep application_url (in shopify.app.toml) pointing at the local/tunnel URL that Shopify CLI spins up.
For production, I should deploy my app and then set application_url to the stable, public base URL of my embedded app (and make sure the App URL / Allowed redirection URL(s) in the Partners dashboard match).
Questions:
When I’m ready for a stable release, what exactly should application_url be set to—do I point it to my deployed app’s base URL (the page that renders the embedded Admin shell/App Bridge)? Any gotchas for embedded apps? (e.g., ensuring ?host= is handled, CSP, etc.)
What’s the recommended deployment approach? (I’m planning to host my backend + embedded UI on a stable domain and keep the same path structure I used in dev.) Any best practices around tunnels vs. deployed domains, and keeping redirect URLs in sync?
How do teams usually handle dev vs. prod URLs?
Maintain separate apps (one dev/staging app, one production app) and switch between them shopify app config use?
Or use multiple TOML configs (e.g., shopify.app.staging.toml) and pick the right one per environment? I’ve seen this suggested, but would love an official stance/tips.
What I’m trying to confirm:
For production, application_url should be the stable, deployed URL that serves the embedded app shell (App Bridge v4, handles host param, etc.).
For development, continue to use a tunnel via Shopify CLI.
Keep App URL and Allowed redirection URL(s) in the Partner dashboard aligned with whichever environment I’m running (dev/staging/prod).
If I’m missing a best practice (like a better pattern for multi-env apps or how to structure the embedded entry route), please point me to the current recommended docs. Thanks!