Setting Up Shopify App + NestJS Backend: A Step-by-Step Local Development Guide



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

  1. Go to your Shopify admin
  2. Navigate to Orders → Create order
  3. Add a product and customer
  4. Create the order
  5. 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 then shopify 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:

  1. Add business logic to your NestJS webhook handler
  2. Integrate external APIs (WhatsApp, email, SMS)
  3. Add database to store and process data
  4. Build frontend components for your Shopify app
  5. 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:

  1. Start NestJS first (npm run start:dev)
  2. Start Shopify app second (shopify app dev)
  3. 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