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!
Top comments (0)