> ## Content Index
> Fetch the complete content index at: https://www.gowthamaraja.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Deploying and Optimizing Sitecore Marketplace Apps: Production Best Practices
- URL: https://www.gowthamaraja.com/sitecore-marketplace-production-apps-nextjs/
- Published: 2026-03-06T15:26:00.000Z
- Updated: 2026-03-06T15:27:15.000Z
- Author: Gowtham
- Tags: Sitecore Marketplace, Next.js, Sitecore, SitecoreAI

We've built our Marketplace app, integrated it with XM Cloud APIs, and tested it locally. Now comes the most critical part—deploying to production and making sure it performs flawlessly for your users.

This final part covers everything from deployment strategies to performance optimization, security best practices, and preparing for the public Marketplace.

## Table of Contents

1. [Preparing for Production](#preparing-for-production)
2. [Deployment Strategy Overview](#deployment-strategy-overview)
3. [Deploying to Vercel](#deploying-to-vercel)
4. [Deploying to Netlify](#deploying-to-netlify)
5. [Deploying to Azure Static Web Apps](#deploying-to-azure-static-web-apps)
6. [Updating Your App Registration](#updating-your-app-registration)
7. [Performance Optimization](#performance-optimization)
8. [Security Best Practices](#security-best-practices)
9. [Monitoring and Analytics](#monitoring-and-analytics)
10. [Common Production Issues](#common-production-issues)
11. [Publishing to Public Marketplace](#publishing-to-public-marketplace)
12. [Final Checklist](#final-checklist)

---

## Preparing for Production

Before deploying, let's make sure your app is production-ready.

### Pre-Deployment Checklist

**Code Quality:**

- Remove all `console.log` statements (or use proper logging)
- Fix all TypeScript errors and warnings
- Run ESLint and fix issues
- Test all features thoroughly
- Handle edge cases and error states

**Performance:**

- Optimize images and assets
- Implement code splitting where needed
- Remove unused dependencies
- Test bundle size (`npm run build`)

**Security:**

- No hardcoded secrets or API keys
- Environment variables properly configured
- Input validation on all user inputs
- XSS protection in place

**UX/UI:**

- Loading states for all async operations
- Error messages are user-friendly
- Responsive design tested on mobile/tablet/desktop
- Accessibility basics covered (keyboard navigation, ARIA labels)

### Environment Variables Setup

Create `.env.production`:

bash

```bash
NEXT_PUBLIC_APP_ENV=production
NEXT_PUBLIC_API_TIMEOUT=10000
NEXT_PUBLIC_SENTRY_DSN=your-sentry-dsn # if using Sentry
```

Add `.env.local` to `.gitignore`:

bash

```bash
# .gitignore
.env.local
.env.*.local
node_modules/
.next/
```

---

## Deployment Strategy Overview

You have three main hosting options:

| Platform    | Best For     | Pros                                          | Cons                      |
| ----------- | ------------ | --------------------------------------------- | ------------------------- |
| **Vercel**  | Next.js apps | Zero config, automatic, great DX              | Vendor lock-in            |
| **Netlify** | Static sites | Easy, good free tier                          | Less Next.js optimization |
| **Azure**   | Enterprise   | Full control, integration with Azure services | More complex setup        |

For this guide, we'll cover all three, but **Vercel is recommended** for Next.js apps.

---

## Deploying to Vercel

Vercel is built by the creators of Next.js, making it the smoothest option.

### Step 1: Push to GitHub

bash

```bash
# Initialize git if you haven't
git init

# Add all files
git add .

# Commit
git commit -m "Production ready app"

# Create repository on GitHub, then:
git remote add origin https://github.com/yourusername/sitecore-analytics-app.git
git push -u origin main
```

### Step 2: Deploy to Vercel

1. Go to [vercel.com](https://vercel.com/?ref=gowthamaraja.com)
2. Click **"New Project"**
3. Import your GitHub repository
4. Vercel auto-detects Next.js settings:
  - Framework Preset: **Next.js**
  - Build Command: `npm run build`
  - Output Directory: `.next`
5. Add environment variables:
  - `NEXT_PUBLIC_APP_ENV`: `production`
6. Click **"Deploy"**

### Step 3: Get Your Production URL

After deployment completes (usually 2-3 minutes), you'll get a URL like:

```
https://sitecore-analytics-app.vercel.app
```

### Vercel-Specific Optimizations

**1\. Enable Edge Functions (optional)**

For global performance, enable edge runtime:

typescript

```typescript
// src/app/standalone/page.tsx
export const runtime = 'edge'; // Run on the edge
```

**2\. Configure Caching**

Add to `next.config.js`:

javascript

```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    domains: ['placehold.co'], // Add your image domains
  },
  headers: async () => [
    {
      source: '/:path*',
      headers: [
        {
          key: 'Cache-Control',
          value: 'public, max-age=3600, must-revalidate',
        },
      ],
    },
  ],
};

module.exports = nextConfig;
```

---

## Deploying to Netlify

Netlify is another excellent option with a generous free tier.

### Step 1: Push to GitHub

Same as Vercel—push your code to GitHub.

### Step 2: Deploy to Netlify

1. Go to [netlify.com](https://netlify.com/?ref=gowthamaraja.com)
2. Click **"Add new site"** → **"Import an existing project"**
3. Connect your GitHub repository
4. Configure build settings:
  - Build command: `npm run build`
  - Publish directory: `.next`
5. Add environment variables in **Site settings → Environment variables**
6. Click **"Deploy site"**

### Step 3: Configure Next.js on Netlify

Install the Netlify Next.js plugin:

bash

```bash
npm install -D @netlify/plugin-nextjs
```

Create `netlify.toml`:

toml

```toml
[build]
  command = "npm run build"
  publish = ".next"

[[plugins]]
  package = "@netlify/plugin-nextjs"
```

Redeploy after adding this configuration.

---

## Deploying to Azure Static Web Apps

For enterprise deployments, Azure provides robust infrastructure.

### Step 1: Create Azure Static Web App

1. Log into [Azure Portal](https://portal.azure.com/?ref=gowthamaraja.com)
2. Create **Static Web App** resource
3. Connect to GitHub repository
4. Configure build:
  - App location: `/`
  - API location: (leave empty)
  - Output location: `.next`

### Step 2: Configure GitHub Actions

Azure automatically creates a GitHub Actions workflow. Update it:

yaml

```yaml
name: Azure Static Web Apps CI/CD

on:
  push:
    branches:
      - main

jobs:
  build_and_deploy_job:
    runs_on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Build And Deploy
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: "upload"
          app_location: "/"
          output_location: ".next"
```

### Step 3: Add Environment Variables

In Azure Portal:

1. Go to your Static Web App
2. Navigate to **Configuration**
3. Add application settings:
  - `NEXT_PUBLIC_APP_ENV`: `production`

---

## Updating Your App Registration

Once deployed, update your app in Developer Studio.

### Step 1: Edit App Configuration

1. Log into Cloud Portal
2. Go to **Developer Studio**
3. Find your app and click **"Edit"**

### Step 2: Update Deployment URL

Change from:

```
http://localhost:3000/standalone
```

To your production URL:

```
https://sitecore-analytics-app.vercel.app/standalone
```

### Step 3: Add Production Logo

Replace placeholder with your actual app logo:

1. Upload a 512x512px PNG to your hosting
2. Update **App Logo URL** with the production URL

### Step 4: Test Production App

1. Save changes
2. Open your app from Cloud Portal navigation
3. Verify everything works:
  - SDK initializes successfully
  - Data loads correctly
  - No console errors
  - All features functional

---

## Performance Optimization

Let's make sure your app loads fast and runs smoothly.

### Bundle Size Optimization

**1\. Analyze Your Bundle**

bash

```bash
npm install -D @next/bundle-analyzer
```

Update `next.config.js`:

javascript

```javascript
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

module.exports = withBundleAnalyzer({
  // your existing config
});
```

Run analysis:

bash

```bash
ANALYZE=true npm run build
```

**2\. Code Splitting**

Split large components:

typescript

```typescript
import dynamic from 'next/dynamic';

// Lazy load heavy components
const AnalyticsChart = dynamic(() => import('@/components/AnalyticsChart'), {
  loading: () => <div>Loading chart...</div>,
  ssr: false, // Disable SSR for client-only components
});
```

**3\. Optimize Images**

Use Next.js Image component:

typescript

```typescript
import Image from 'next/image';

<Image
  src="/logo.png"
  alt="App Logo"
  width={512}
  height={512}
  priority // For above-fold images
/>
```

### Data Fetching Optimization

**1\. Implement Caching**

typescript

```typescript
// Simple in-memory cache
const cache = new Map<string, { data: any; timestamp: number }>();

async function fetchWithCache(key: string, fetchFn: () => Promise<any>, ttl = 300000) {
  const cached = cache.get(key);
  
  if (cached && Date.now() - cached.timestamp < ttl) {
    return cached.data;
  }
  
  const data = await fetchFn();
  cache.set(key, { data, timestamp: Date.now() });
  return data;
}

// Usage
const stats = await fetchWithCache('content-stats', async () => {
  const xmc = await initializeXMC(client);
  return xmc.graphQL.query({ query });
}, 300000); // 5 minutes
```

**2\. Debounce API Calls**

typescript

```typescript
import { debounce } from 'lodash';

const debouncedSearch = debounce(async (searchTerm: string) => {
  const results = await searchContent(searchTerm);
  setSearchResults(results);
}, 500); // Wait 500ms after user stops typing
```

### Runtime Performance

**1\. Memoize Expensive Calculations**

typescript

```typescript
import { useMemo } from 'react';

const expensiveCalculation = useMemo(() => {
  return items.reduce((acc, item) => {
    // Complex calculation
    return acc + item.value;
  }, 0);
}, [items]); // Only recalculate when items change
```

**2\. Virtual Lists for Large Data**

bash

```bash
npm install react-window
```

typescript

```typescript
import { FixedSizeList } from 'react-window';

function ItemList({ items }) {
  return (
    <FixedSizeList
      height={600}
      itemCount={items.length}
      itemSize={50}
      width="100%"
    >
      {({ index, style }) => (
        <div style={style}>{items[index].name}</div>
      )}
    </FixedSizeList>
  );
}
```

---

## Security Best Practices

Security is non-negotiable for production apps.

### Input Validation

typescript

```typescript
// Sanitize user input
function sanitizeInput(input: string): string {
  return input
    .trim()
    .replace(/[<>]/g, '') // Remove HTML tags
    .substring(0, 200); // Limit length
}

// Validate before using
function handleUserInput(value: string) {
  const sanitized = sanitizeInput(value);
  
  if (!/^[a-zA-Z0-9\s-]+$/.test(sanitized)) {
    throw new Error('Invalid characters in input');
  }
  
  return sanitized;
}
```

### Content Security Policy

Add to `next.config.js`:

javascript

```javascript
const nextConfig = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: [
              "default-src 'self'",
              "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
              "style-src 'self' 'unsafe-inline'",
              "img-src 'self' data: https:",
              "connect-src 'self' https://*.sitecore.com",
            ].join('; '),
          },
        ],
      },
    ];
  },
};
```

### Rate Limiting

Implement rate limiting for API calls:

typescript

```typescript
class RateLimiter {
  private requests: number[] = [];
  private limit: number;
  private window: number;

  constructor(limit: number, windowMs: number) {
    this.limit = limit;
    this.window = windowMs;
  }

  async checkLimit(): Promise<boolean> {
    const now = Date.now();
    this.requests = this.requests.filter(time => now - time < this.window);
    
    if (this.requests.length >= this.limit) {
      return false;
    }
    
    this.requests.push(now);
    return true;
  }
}

// Usage
const limiter = new RateLimiter(10, 60000); // 10 requests per minute

async function fetchData() {
  if (!await limiter.checkLimit()) {
    throw new Error('Rate limit exceeded. Please try again later.');
  }
  
  // Make API call
}
```

---

## Monitoring and Analytics

Track your app's performance and usage.

### Error Tracking with Sentry

bash

```bash
npm install @sentry/nextjs
```

Create `sentry.client.config.ts`:

typescript

```typescript
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NEXT_PUBLIC_APP_ENV,
  tracesSampleRate: 1.0,
});
```

Wrap your app:

typescript

```typescript
import { ErrorBoundary } from '@sentry/nextjs';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <ErrorBoundary fallback={<ErrorFallback />}>
      <Component {...pageProps} />
    </ErrorBoundary>
  );
}
```

### Custom Analytics

Track user interactions:

typescript

```typescript
// lib/analytics.ts
export function trackEvent(
  event: string,
  properties?: Record<string, any>
) {
  if (typeof window === 'undefined') return;
  
  // Send to your analytics service
  console.log('Event:', event, properties);
  
  // Example: Google Analytics
  if (window.gtag) {
    window.gtag('event', event, properties);
  }
}

// Usage
trackEvent('content_exported', {
  format: 'csv',
  itemCount: 150,
});
```

---

## Common Production Issues

### Issue 1: CORS Errors

**Symptom:** API calls fail with CORS errors

**Solution:** Ensure your deployment URL is added to allowed origins in API configuration.

### Issue 2: Environment Variables Not Working

**Symptom:** `process.env.NEXT_PUBLIC_*` is undefined

**Solution:**

- Rebuild after adding environment variables
- Verify variables start with `NEXT_PUBLIC_`
- Check they're added in hosting platform settings

### Issue 3: Hydration Errors

**Symptom:** "Hydration failed" errors in console

**Solution:**

typescript

```typescript
// Use useEffect for client-only rendering
const [mounted, setMounted] = useState(false);

useEffect(() => {
  setMounted(true);
}, []);

if (!mounted) return null;
```

### Issue 4: Slow Initial Load

**Symptom:** App takes 5+ seconds to load

**Solution:**

- Enable code splitting
- Optimize bundle size
- Use CDN for static assets
- Implement proper caching headers

---

## Publishing to Public Marketplace

Once the public Marketplace launches fully, you can publish your app.

### Requirements for Public Apps

1. **Documentation**
  - Clear README with setup instructions
  - Screenshots and demo video
  - Support contact information
2. **Quality Standards**
  - No critical bugs
  - Responsive design
  - Proper error handling
  - Accessibility compliance
3. **Pricing Model**
  - Free
  - Freemium (basic free, premium paid)
  - Paid subscription
  - One-time purchase

### Publishing Process

1. **Test Thoroughly**
  - Get beta users to test
  - Fix all reported issues
  - Document known limitations
2. **Create Marketing Materials**
  - App icon (512x512px)
  - Screenshots (various sizes)
  - Demo video (2-3 minutes)
  - Feature highlights
  - Use case examples
3. **Submit for Review**
  - In Developer Studio, change app type to "Public"
  - Complete listing information
  - Submit for Sitecore review
  - Wait for approval (typically 5-7 business days)
4. **Launch and Promote**
  - Announce on social media
  - Write blog post
  - Submit to Sitecore community
  - Engage with early adopters

---

## Final Checklist

Before considering your app production-ready:

### Development

- All features tested and working
- No TypeScript errors
- ESLint warnings resolved
- Code reviewed and optimized

### Performance

- Bundle size under 1MB initial load
- First Contentful Paint < 2s
- Time to Interactive < 5s
- Lighthouse score > 90

### Security

- No hardcoded secrets
- Input validation implemented
- CSP headers configured
- Rate limiting in place

### User Experience

- Loading states for all async operations
- Error messages are helpful
- Responsive on all devices
- Keyboard navigation works
- Color contrast meets WCAG AA

### Deployment

- Deployed to production hosting
- Custom domain configured (optional)
- SSL certificate active
- Environment variables set
- App registration updated in Developer Studio

### Monitoring

- Error tracking configured
- Analytics implemented
- Performance monitoring active
- Uptime monitoring setup

---

## Conclusion

You've made it! You now have the complete knowledge to:

1. **Build** sophisticated Marketplace apps from scratch
2. **Integrate** with XM Cloud APIs and extension points
3. **Deploy** to production hosting platforms
4. **Optimize** for performance and security
5. **Monitor** and maintain your apps

### What's Next for You?

**Immediate Actions:**

- Deploy your first app to production
- Share it with your team
- Gather user feedback
- Iterate and improve

**Long-term Goals:**

- Build apps for the public Marketplace
- Create a portfolio of Sitecore extensions
- Contribute to the Sitecore community
- Potentially build a business around Marketplace apps

### Resources to Bookmark

- [Sitecore Marketplace Documentation](https://doc.sitecore.com/mp/?ref=gowthamaraja.com)
- [Marketplace SDK Reference](https://doc.sitecore.com/mp/en/developers/sdk/?ref=gowthamaraja.com)
- [Sitecore Developer Portal](https://developers.sitecore.com/?ref=gowthamaraja.com)
- [Marketplace Starter Kit](https://github.com/Sitecore/marketplace-starter?ref=gowthamaraja.com)
- [Blok Design System](https://blok.sitecore.com/?ref=gowthamaraja.com)

---

## Thank You!

This three-part series covered everything from "What is Sitecore Marketplace?" to "How do I deploy a production app?"

If you found this helpful:

- Share it with your developer community
- Try building your own Marketplace app
- Let me know what you build!

**Questions? Feedback? Success stories?** Drop them in the comments below. I read every single one.

Happy coding, and see you in the Marketplace! 🚀

---

**Missed the earlier parts?**

- [Part 1: Getting Started with Sitecore Marketplace →](https://www.gowthamaraja.com/building-production-ready-sitecore-marketplace-apps-with-next-js)
- [Part 2: Building Production-Ready Apps →](https://www.gowthamaraja.com/sitecore-marketplace-getting-started-nextjs)