This content originally appeared on DEV Community and was authored by Georges HELOUSSATO
Ever wanted to connect a Shopify app to your own backend? Here’s a complete walkthrough to get both servers running on your local machine and talking to each other.
What We’re Building
- Shopify App: Handles webhooks from Shopify stores
- NestJS Backend: Processes webhook data and handles business logic
- Connection: Shopify app forwards order data to NestJS API
Let’s get both servers up and running!
Part 1: Setting Up the Shopify App
Step 1: Create the Shopify App
Open your terminal and run:
npm init @shopify/app@latest
Answer the prompts:
-
App name:
bridge-app
(or any name you prefer) -
Type:
Public: An app built for a wide merchant audience
-
Template:
Remix (TypeScript)
-
Package manager:
npm
Step 2: Navigate to Your App
cd bridge-app
Step 3: Configure Permissions and Webhooks
Edit the shopify.app.toml
file:
nano shopify.app.toml
Find this line:
scopes = "write_products"
Replace it with:
scopes = "write_products,read_orders,write_orders"
Then find this section:
[[webhooks.subscriptions]]
topics = [ "app/scopes_update" ]
uri = "/webhooks/app/scopes_update"
Add after it:
[[webhooks.subscriptions]]
topics = [ "orders/create" ]
uri = "/webhooks/orders/create"
Save and exit: Ctrl + X
, then Y
, then Enter
Step 4: Start the Shopify App
shopify app dev
Follow the prompts:
- Create or select a development store
- Allow automatic URL updates (
Y
) - The app will start and give you a preview URL
Keep this terminal open – your Shopify app is now running!
Part 2: Setting Up the NestJS Backend
Step 1: Open a New Terminal
Important: Keep your Shopify terminal running and open a new terminal window.
Step 2: Create NestJS Project
# Install NestJS CLI globally
npm i -g @nestjs/cli
# Create new project
nest new bridgeapp-api
# Navigate to project
cd bridgeapp-api
Step 3: Create the Webhook Controller
Create a new directory:
mkdir src/webhook
Create the controller file:
touch src/webhook/webhook.controller.ts
Edit the file:
nano src/webhook/webhook.controller.ts
Add this code:
import { Controller, Post, Body, Headers, Logger } from '@nestjs/common';
@Controller('webhook')
export class WebhookController {
private readonly logger = new Logger(WebhookController.name);
@Post('shopify/order')
handleShopifyOrder(
@Body() body: any,
@Headers() headers: any,
) {
this.logger.log('🔔 WEBHOOK RECEIVED!');
this.logger.log('📦 Headers:', JSON.stringify(headers, null, 2));
this.logger.log('📊 Body:', JSON.stringify(body, null, 2));
return { status: 'OK', message: 'Webhook received!' };
}
}
Save and exit: Ctrl + X
, then Y
, then Enter
Step 4: Update App Module
Edit the main app module:
nano src/app.module.ts
Replace the content with:
import { Module } from '@nestjs/common';
import { WebhookController } from './webhook/webhook.controller';
@Module({
controllers: [WebhookController],
})
export class AppModule {}
Save and exit: Ctrl + X
, then Y
, then Enter
Step 5: Start NestJS
npm run start:dev
Keep this terminal open too – your NestJS API is now running on http://localhost:3000
!
Part 3: Connecting Shopify to NestJS
Step 1: Create the Bridge
In your Shopify app terminal (the first one), create a new webhook file:
touch app/routes/webhooks.orders.create.tsx
Edit this file:
nano app/routes/webhooks.orders.create.tsx
Add this code:
import type { ActionFunctionArgs } from "@remix-run/node";
import { authenticate } from "../shopify.server";
export const action = async ({ request }: ActionFunctionArgs) => {
const { topic, shop, session, admin, payload } = await authenticate.webhook(request);
console.log("🔔 SHOPIFY WEBHOOK RECEIVED!");
console.log("📊 Topic:", topic);
console.log("🏪 Shop:", shop);
console.log("📦 Order:", JSON.stringify(payload, null, 2));
try {
console.log("➡ Sending to NestJS...");
const response = await fetch('http://localhost:3000/webhook/shopify/order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
shop: shop,
order: payload
})
});
if (response.ok) {
console.log("✅ Successfully sent to NestJS");
} else {
console.log("❌ Error sending to NestJS:", response.status);
}
} catch (error) {
console.log("❌ Connection error:", error);
}
return new Response("OK", { status: 200 });
};
Save and exit: Ctrl + X
, then Y
, then Enter
Part 4: Testing the Connection
Step 1: Install Your App
In your browser, go to the preview URL shown in your Shopify terminal. Install the app on your development store.
Step 2: Test with Direct API Call
In a third terminal, test your NestJS API directly:
curl -X POST http://localhost:3000/webhook/shopify/order \
-H "Content-Type: application/json" \
-d '{
"shop": "test-shop.myshopify.com",
"order": {
"id": 123,
"name": "#1001",
"customer": {
"first_name": "John",
"phone": "+1234567890"
}
}
}'
You should see logs in your NestJS terminal!
Step 3: Test End-to-End
- Go to your Shopify admin
- Navigate to Orders → Create order
- Add a product and customer
- Create the order
- Watch both terminals for logs!
What You Should See
Terminal 1 (Shopify App):
🔔 SHOPIFY WEBHOOK RECEIVED!
📊 Topic: orders/create
🏪 Shop: your-store.myshopify.com
➡ Sending to NestJS...
✅ Successfully sent to NestJS
Terminal 2 (NestJS API):
[WebhookController] 🔔 WEBHOOK RECEIVED!
[WebhookController] 📦 Headers: {...}
[WebhookController] 📊 Body: {"shop": "...", "order": {...}}
Troubleshooting Common Issues
“Connection refused” Error
- Check: Is NestJS running on port 3000?
-
Test:
curl http://localhost:3000/webhook/shopify/order
No Webhook Received
- Check: Did you save the webhook file correctly?
-
Try: Restart your Shopify app (
Ctrl+C
thenshopify app dev
)
Port Already in Use
-
NestJS: Change port in
main.ts
to 3001 -
Update: Shopify webhook URL to
localhost:3001
Your Local Development Setup
Congratulations! You now have:
Shopify app running and receiving webhooks
NestJS backend processing webhook data
Communication between both servers
Local development environment ready for building features
Next Steps
Now that both servers are talking, you can:
- Add business logic to your NestJS webhook handler
- Integrate external APIs (WhatsApp, email, SMS)
- Add database to store and process data
- Build frontend components for your Shopify app
- Deploy to production when ready
Keeping Everything Running
Terminal Management:
-
Terminal 1:
shopify app dev
(keep running) -
Terminal 2:
npm run start:dev
in NestJS folder (keep running) - Terminal 3: Available for testing commands
When you restart:
- Start NestJS first (
npm run start:dev
) - Start Shopify app second (
shopify app dev
) - Both should reconnect automatically
That’s it! You now have a complete local development setup with Shopify and NestJS talking to each other. Happy coding!
Questions about the setup? Drop them in the comments below!
This content originally appeared on DEV Community and was authored by Georges HELOUSSATO