gentelella
Version:
Gentelella Admin is a free to use Bootstrap admin template
909 lines (639 loc) • 95.7 kB
HTML
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-default.css">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet">
<style id="jtd-nav-activation">
.site-nav > ul.nav-list:first-child > li:not(:nth-child(6)) > a,
.site-nav > ul.nav-list:first-child > li > ul > li a {
background-image: none;
}
.site-nav > ul.nav-list:not(:first-child) a,
.site-nav li.external a {
background-image: none;
}
.site-nav > ul.nav-list:first-child > li:nth-child(6) > a {
font-weight: 600;
text-decoration: none;
}.site-nav > ul.nav-list:first-child > li:nth-child(6) > button svg {
transform: rotate(-90deg);
}.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(6) > ul.nav-list {
display: block;
}
</style>
<script src="/gentelella/assets/js/vendor/lunr.min.js"></script>
<script src="/gentelella/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/gentelella/favicon.ico" type="image/x-icon">
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Deployment Guide | Gentelella Admin Template</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="Deployment Guide" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<meta property="og:description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<link rel="canonical" href="http://localhost:4000/gentelella/deployment/" />
<meta property="og:url" content="http://localhost:4000/gentelella/deployment/" />
<meta property="og:site_name" content="Gentelella Admin Template" />
<meta property="og:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="twitter:title" content="Deployment Guide" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebPage","description":"Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations","headline":"Deployment Guide","image":"http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg","url":"http://localhost:4000/gentelella/deployment/"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<a class="skip-to-main" href="#main-content">Skip to main content</a>
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="svg-link" viewBox="0 0 24 24">
<title>Link</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE -->
<symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link">
<title id="svg-external-link-title">(external link)</title>
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line>
</symbol>
<symbol id="svg-doc" viewBox="0 0 24 24">
<title>Document</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>
</svg>
</symbol>
<symbol id="svg-search" viewBox="0 0 24 24">
<title>Search</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</symbol>
<!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md -->
<symbol id="svg-copy" viewBox="0 0 16 16">
<title>Copy</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>
</symbol>
<symbol id="svg-copied" viewBox="0 0 16 16">
<title>Copied</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16">
<path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/>
</svg>
</symbol>
</svg>
<div class="side-bar">
<div class="site-header" role="banner">
<a href="/gentelella/" class="site-title lh-tight">
Gentelella Admin Template
</a>
<button id="menu-button" class="site-button btn-reset" aria-label="Toggle menu" aria-pressed="false">
<svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg>
</button>
</div>
<nav aria-label="Main" id="site-nav" class="site-nav">
<ul class="nav-list"><li class="nav-list-item"><a href="/gentelella/" class="nav-list-link">Gentelella Admin Template Documentation</a></li><li class="nav-list-item"><a href="/gentelella/installation/" class="nav-list-link">Installation Guide</a></li><li class="nav-list-item"><a href="/gentelella/configuration/" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/gentelella/components/" class="nav-list-link">Components Guide</a></li><li class="nav-list-item"><a href="/gentelella/performance/" class="nav-list-link">Performance Guide</a></li><li class="nav-list-item"><a href="/gentelella/deployment/" class="nav-list-link">Deployment Guide</a></li><li class="nav-list-item"><a href="/gentelella/customization/" class="nav-list-link">Customization Guide</a></li><li class="nav-list-item"><a href="/gentelella/api-integration/" class="nav-list-link">API Integration</a></li></ul>
</nav>
<footer class="site-footer">
This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.
</footer>
</div>
<div class="main" id="top">
<div id="main-header" class="main-header">
<div class="search" role="search">
<div class="search-input-wrap">
<input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search Gentelella Admin Template" aria-label="Search Gentelella Admin Template" autocomplete="off">
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label>
</div>
<div id="search-results" class="search-results"></div>
</div>
<nav aria-label="Auxiliary" class="aux-nav">
<ul class="aux-nav-list">
<li class="aux-nav-list-item">
<a href="//github.com/puikinsh/gentelella" class="site-button"
>
Gentelella on GitHub
</a>
</li>
<li class="aux-nav-list-item">
<a href="//colorlib.com" class="site-button"
>
Colorlib
</a>
</li>
</ul>
</nav>
</div>
<div class="main-content-wrap">
<div id="main-content" class="main-content">
<main>
<h1 class="no_toc" id="deployment-guide">
<a href="#deployment-guide" class="anchor-heading" aria-labelledby="deployment-guide"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Deployment Guide
</h1>
<p class="fs-6 fw-300">Complete guide to deploying Gentelella Admin Template to production environments</p>
<h2 class="no_toc text-delta" id="table-of-contents">
<a href="#table-of-contents" class="anchor-heading" aria-labelledby="table-of-contents"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Table of contents
</h2>
<ol id="markdown-toc">
<li><a href="#pre-deployment-checklist" id="markdown-toc-pre-deployment-checklist">Pre-Deployment Checklist</a> <ol>
<li><a href="#build-optimization" id="markdown-toc-build-optimization">Build Optimization</a></li>
<li><a href="#environment-configuration" id="markdown-toc-environment-configuration">Environment Configuration</a> <ol>
<li><a href="#production-environment-variables" id="markdown-toc-production-environment-variables">Production Environment Variables</a></li>
<li><a href="#build-configuration" id="markdown-toc-build-configuration">Build Configuration</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#static-hosting-platforms" id="markdown-toc-static-hosting-platforms">Static Hosting Platforms</a> <ol>
<li><a href="#netlify-deployment" id="markdown-toc-netlify-deployment">Netlify Deployment</a> <ol>
<li><a href="#method-1-git-integration-recommended" id="markdown-toc-method-1-git-integration-recommended">Method 1: Git Integration (Recommended)</a></li>
<li><a href="#method-2-manual-deploy" id="markdown-toc-method-2-manual-deploy">Method 2: Manual Deploy</a></li>
<li><a href="#netlify-configuration" id="markdown-toc-netlify-configuration">Netlify Configuration</a></li>
</ol>
</li>
<li><a href="#vercel-deployment" id="markdown-toc-vercel-deployment">Vercel Deployment</a> <ol>
<li><a href="#git-integration" id="markdown-toc-git-integration">Git Integration</a></li>
<li><a href="#manual-deployment" id="markdown-toc-manual-deployment">Manual Deployment</a></li>
<li><a href="#vercel-configuration" id="markdown-toc-vercel-configuration">Vercel Configuration</a></li>
</ol>
</li>
<li><a href="#github-pages" id="markdown-toc-github-pages">GitHub Pages</a> <ol>
<li><a href="#github-actions-deployment" id="markdown-toc-github-actions-deployment">GitHub Actions Deployment</a></li>
<li><a href="#update-vite-configuration-for-github-pages" id="markdown-toc-update-vite-configuration-for-github-pages">Update Vite Configuration for GitHub Pages</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#server-hosting" id="markdown-toc-server-hosting">Server Hosting</a> <ol>
<li><a href="#nginx-configuration" id="markdown-toc-nginx-configuration">Nginx Configuration</a> <ol>
<li><a href="#basic-setup" id="markdown-toc-basic-setup">Basic Setup</a></li>
<li><a href="#ssl-with-lets-encrypt" id="markdown-toc-ssl-with-lets-encrypt">SSL with Let’s Encrypt</a></li>
</ol>
</li>
<li><a href="#apache-configuration" id="markdown-toc-apache-configuration">Apache Configuration</a> <ol>
<li><a href="#virtual-host-setup" id="markdown-toc-virtual-host-setup">Virtual Host Setup</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#container-deployment" id="markdown-toc-container-deployment">Container Deployment</a> <ol>
<li><a href="#docker-setup" id="markdown-toc-docker-setup">Docker Setup</a> <ol>
<li><a href="#dockerfile" id="markdown-toc-dockerfile">Dockerfile</a></li>
<li><a href="#docker-nginx-configuration" id="markdown-toc-docker-nginx-configuration">Docker Nginx Configuration</a></li>
<li><a href="#docker-compose" id="markdown-toc-docker-compose">Docker Compose</a></li>
</ol>
</li>
<li><a href="#kubernetes-deployment" id="markdown-toc-kubernetes-deployment">Kubernetes Deployment</a> <ol>
<li><a href="#deployment-configuration" id="markdown-toc-deployment-configuration">Deployment Configuration</a></li>
<li><a href="#service-configuration" id="markdown-toc-service-configuration">Service Configuration</a></li>
<li><a href="#ingress-configuration" id="markdown-toc-ingress-configuration">Ingress Configuration</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#cicd-pipelines" id="markdown-toc-cicd-pipelines">CI/CD Pipelines</a> <ol>
<li><a href="#github-actions" id="markdown-toc-github-actions">GitHub Actions</a> <ol>
<li><a href="#complete-cicd-pipeline" id="markdown-toc-complete-cicd-pipeline">Complete CI/CD Pipeline</a></li>
</ol>
</li>
<li><a href="#gitlab-cicd" id="markdown-toc-gitlab-cicd">GitLab CI/CD</a></li>
</ol>
</li>
<li><a href="#monitoring-and-maintenance" id="markdown-toc-monitoring-and-maintenance">Monitoring and Maintenance</a> <ol>
<li><a href="#health-checks" id="markdown-toc-health-checks">Health Checks</a> <ol>
<li><a href="#basic-health-check-endpoint" id="markdown-toc-basic-health-check-endpoint">Basic Health Check Endpoint</a></li>
<li><a href="#service-worker-health-check" id="markdown-toc-service-worker-health-check">Service Worker Health Check</a></li>
</ol>
</li>
<li><a href="#error-tracking" id="markdown-toc-error-tracking">Error Tracking</a> <ol>
<li><a href="#sentry-integration" id="markdown-toc-sentry-integration">Sentry Integration</a></li>
</ol>
</li>
<li><a href="#performance-monitoring" id="markdown-toc-performance-monitoring">Performance Monitoring</a></li>
</ol>
</li>
<li><a href="#security-considerations" id="markdown-toc-security-considerations">Security Considerations</a> <ol>
<li><a href="#content-security-policy" id="markdown-toc-content-security-policy">Content Security Policy</a></li>
<li><a href="#environment-secrets" id="markdown-toc-environment-secrets">Environment Secrets</a></li>
<li><a href="#https-enforcement" id="markdown-toc-https-enforcement">HTTPS Enforcement</a></li>
</ol>
</li>
<li><a href="#troubleshooting" id="markdown-toc-troubleshooting">Troubleshooting</a> <ol>
<li><a href="#common-deployment-issues" id="markdown-toc-common-deployment-issues">Common Deployment Issues</a> <ol>
<li><a href="#1-build-failures" id="markdown-toc-1-build-failures">1. Build Failures</a></li>
<li><a href="#2-asset-loading-issues" id="markdown-toc-2-asset-loading-issues">2. Asset Loading Issues</a></li>
<li><a href="#3-api-connection-issues" id="markdown-toc-3-api-connection-issues">3. API Connection Issues</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#next-steps" id="markdown-toc-next-steps">Next Steps</a></li>
</ol><hr />
<h2 id="pre-deployment-checklist">
<a href="#pre-deployment-checklist" class="anchor-heading" aria-labelledby="pre-deployment-checklist"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Pre-Deployment Checklist
</h2>
<h3 id="build-optimization">
<a href="#build-optimization" class="anchor-heading" aria-labelledby="build-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Build Optimization
</h3>
<p>Before deploying, ensure your build is optimized:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Run production build</span>
npm run build
<span class="c"># Analyze bundle sizes</span>
npm run build:analyze
<span class="c"># Run performance optimizations</span>
npm run optimize
<span class="c"># Test production build locally</span>
npm run preview
</code></pre></div></div>
<h3 id="environment-configuration">
<a href="#environment-configuration" class="anchor-heading" aria-labelledby="environment-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Environment Configuration
</h3>
<h4 id="production-environment-variables">
<a href="#production-environment-variables" class="anchor-heading" aria-labelledby="production-environment-variables"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Production Environment Variables
</h4>
<p>Create <code class="language-plaintext highlighter-rouge">.env.production</code>:</p>
<pre><code class="language-env"># API Configuration
VITE_API_URL=https://api.yoursite.com
VITE_APP_NAME=Gentelella Admin
VITE_DEBUG_MODE=false
# CDN Configuration
VITE_CDN_URL=https://cdn.yoursite.com
VITE_ASSETS_URL=https://assets.yoursite.com
# Performance Settings
VITE_PRELOAD_MODULES=charts,forms
VITE_ENABLE_SERVICE_WORKER=true
# Analytics
VITE_GA_TRACKING_ID=UA-XXXXXXXX-X
VITE_HOTJAR_ID=XXXXXXX
</code></pre>
<h4 id="build-configuration">
<a href="#build-configuration" class="anchor-heading" aria-labelledby="build-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Build Configuration
</h4>
<p>Ensure <code class="language-plaintext highlighter-rouge">vite.config.js</code> has production optimizations:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="k">default</span> <span class="nx">defineConfig</span><span class="p">({</span>
<span class="na">base</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/your-app-path/</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// Set if not deploying to root</span>
<span class="na">build</span><span class="p">:</span> <span class="p">{</span>
<span class="c1">// Output directory</span>
<span class="na">outDir</span><span class="p">:</span> <span class="dl">'</span><span class="s1">dist</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">// Asset directory</span>
<span class="na">assetsDir</span><span class="p">:</span> <span class="dl">'</span><span class="s1">assets</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">// Source maps for production debugging</span>
<span class="na">sourcemap</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_ENV</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">development</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">// Minification</span>
<span class="na">minify</span><span class="p">:</span> <span class="dl">'</span><span class="s1">terser</span><span class="dl">'</span><span class="p">,</span>
<span class="na">terserOptions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">compress</span><span class="p">:</span> <span class="p">{</span>
<span class="na">drop_console</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">drop_debugger</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">// Chunk size warning limit</span>
<span class="na">chunkSizeWarningLimit</span><span class="p">:</span> <span class="mi">1000</span><span class="p">,</span>
<span class="na">rollupOptions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">output</span><span class="p">:</span> <span class="p">{</span>
<span class="c1">// Manual chunk splitting for optimal loading</span>
<span class="na">manualChunks</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">vendor-core</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">bootstrap</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">@popperjs/core</span><span class="dl">'</span><span class="p">],</span>
<span class="dl">'</span><span class="s1">vendor-charts</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">chart.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">morris.js</span><span class="dl">'</span><span class="p">],</span>
<span class="dl">'</span><span class="s1">vendor-forms</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">select2</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">tempus-dominus</span><span class="dl">'</span><span class="p">],</span>
<span class="dl">'</span><span class="s1">vendor-tables</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">datatables.net</span><span class="dl">'</span><span class="p">],</span>
<span class="dl">'</span><span class="s1">vendor-utils</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">dayjs</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">nprogress</span><span class="dl">'</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div><hr />
<h2 id="static-hosting-platforms">
<a href="#static-hosting-platforms" class="anchor-heading" aria-labelledby="static-hosting-platforms"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Static Hosting Platforms
</h2>
<h3 id="netlify-deployment">
<a href="#netlify-deployment" class="anchor-heading" aria-labelledby="netlify-deployment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Netlify Deployment
</h3>
<h4 id="method-1-git-integration-recommended">
<a href="#method-1-git-integration-recommended" class="anchor-heading" aria-labelledby="method-1-git-integration-recommended"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Method 1: Git Integration (Recommended)
</h4>
<ol>
<li><strong>Connect Repository</strong>
<ul>
<li>Push your code to GitHub/GitLab/Bitbucket</li>
<li>Connect repository in Netlify dashboard</li>
</ul>
</li>
<li><strong>Configure Build Settings</strong>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Build command: npm run build
Publish directory: dist
</code></pre></div> </div>
</li>
<li><strong>Environment Variables</strong>
Set in Netlify dashboard under Site Settings → Environment Variables:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>VITE_API_URL=https://api.yoursite.com
VITE_APP_NAME=Gentelella Admin
NODE_VERSION=18
</code></pre></div> </div>
</li>
<li><strong>Custom Domain</strong>
<ul>
<li>Add custom domain in Site Settings → Domain Management</li>
<li>Configure DNS records</li>
</ul>
</li>
</ol>
<h4 id="method-2-manual-deploy">
<a href="#method-2-manual-deploy" class="anchor-heading" aria-labelledby="method-2-manual-deploy"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Method 2: Manual Deploy
</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Build the project</span>
npm run build
<span class="c"># Install Netlify CLI</span>
npm <span class="nb">install</span> <span class="nt">-g</span> netlify-cli
<span class="c"># Deploy to Netlify</span>
netlify deploy <span class="nt">--prod</span> <span class="nt">--dir</span><span class="o">=</span>dist
</code></pre></div></div>
<h4 id="netlify-configuration">
<a href="#netlify-configuration" class="anchor-heading" aria-labelledby="netlify-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Netlify Configuration
</h4>
<p>Create <code class="language-plaintext highlighter-rouge">netlify.toml</code>:</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[build]</span>
<span class="py">command</span> <span class="p">=</span> <span class="s">"npm run build"</span>
<span class="py">publish</span> <span class="p">=</span> <span class="s">"dist"</span>
<span class="nn">[build.environment]</span>
<span class="py">NODE_VERSION</span> <span class="p">=</span> <span class="s">"18"</span>
<span class="nn">[[redirects]]</span>
<span class="py">from</span> <span class="p">=</span> <span class="s">"/*"</span>
<span class="py">to</span> <span class="p">=</span> <span class="s">"/index.html"</span>
<span class="py">status</span> <span class="p">=</span> <span class="mi">200</span>
<span class="nn">[[headers]]</span>
<span class="py">for</span> <span class="p">=</span> <span class="s">"/assets/*"</span>
<span class="nn">[headers.values]</span>
<span class="py">Cache-Control</span> <span class="p">=</span> <span class="s">"public, max-age=31536000, immutable"</span>
<span class="nn">[[headers]]</span>
<span class="py">for</span> <span class="p">=</span> <span class="s">"/*.html"</span>
<span class="nn">[headers.values]</span>
<span class="py">Cache-Control</span> <span class="p">=</span> <span class="s">"public, max-age=3600"</span>
</code></pre></div></div>
<h3 id="vercel-deployment">
<a href="#vercel-deployment" class="anchor-heading" aria-labelledby="vercel-deployment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Vercel Deployment
</h3>
<h4 id="git-integration">
<a href="#git-integration" class="anchor-heading" aria-labelledby="git-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Git Integration
</h4>
<ol>
<li><strong>Connect Repository</strong>
<ul>
<li>Import project from GitHub/GitLab</li>
<li>Vercel auto-detects Vite configuration</li>
</ul>
</li>
<li><strong>Build Configuration</strong>
Vercel automatically detects these settings:
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"buildCommand"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npm run build"</span><span class="p">,</span><span class="w">
</span><span class="nl">"outputDirectory"</span><span class="p">:</span><span class="w"> </span><span class="s2">"dist"</span><span class="p">,</span><span class="w">
</span><span class="nl">"installCommand"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npm install"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div> </div>
</li>
<li><strong>Environment Variables</strong>
Set in Vercel dashboard:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>VITE_API_URL=https://api.yoursite.com
VITE_APP_NAME=Gentelella Admin
</code></pre></div> </div>
</li>
</ol>
<h4 id="manual-deployment">
<a href="#manual-deployment" class="anchor-heading" aria-labelledby="manual-deployment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Manual Deployment
</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install Vercel CLI</span>
npm <span class="nb">install</span> <span class="nt">-g</span> vercel
<span class="c"># Deploy</span>
vercel <span class="nt">--prod</span>
</code></pre></div></div>
<h4 id="vercel-configuration">
<a href="#vercel-configuration" class="anchor-heading" aria-labelledby="vercel-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Vercel Configuration
</h4>
<p>Create <code class="language-plaintext highlighter-rouge">vercel.json</code>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"builds"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"src"</span><span class="p">:</span><span class="w"> </span><span class="s2">"package.json"</span><span class="p">,</span><span class="w">
</span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@vercel/static-build"</span><span class="p">,</span><span class="w">
</span><span class="nl">"config"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"distDir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"dist"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"routes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"handle"</span><span class="p">:</span><span class="w"> </span><span class="s2">"filesystem"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"src"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/(.*)"</span><span class="p">,</span><span class="w">
</span><span class="nl">"dest"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/index.html"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/assets/(.*)"</span><span class="p">,</span><span class="w">
</span><span class="nl">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Cache-Control"</span><span class="p">,</span><span class="w">
</span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"public, max-age=31536000, immutable"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<h3 id="github-pages">
<a href="#github-pages" class="anchor-heading" aria-labelledby="github-pages"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> GitHub Pages
</h3>
<h4 id="github-actions-deployment">
<a href="#github-actions-deployment" class="anchor-heading" aria-labelledby="github-actions-deployment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> GitHub Actions Deployment
</h4>
<p>Create <code class="language-plaintext highlighter-rouge">.github/workflows/deploy.yml</code>:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">Deploy to GitHub Pages</span>
<span class="na">on</span><span class="pi">:</span>
<span class="na">push</span><span class="pi">:</span>
<span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="nv">main</span> <span class="pi">]</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="na">deploy</span><span class="pi">:</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span>
<span class="na">permissions</span><span class="pi">:</span>
<span class="na">contents</span><span class="pi">:</span> <span class="s">read</span>
<span class="na">pages</span><span class="pi">:</span> <span class="s">write</span>
<span class="na">id-token</span><span class="pi">:</span> <span class="s">write</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Checkout</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v3</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Setup Node.js</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/setup-node@v3</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">node-version</span><span class="pi">:</span> <span class="s1">'</span><span class="s">18'</span>
<span class="na">cache</span><span class="pi">:</span> <span class="s1">'</span><span class="s">npm'</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install dependencies</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">npm ci</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">npm run build</span>
<span class="na">env</span><span class="pi">:</span>
<span class="na">VITE_BASE_URL</span><span class="pi">:</span> <span class="s">/your-repo-name/</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Setup Pages</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/configure-pages@v3</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Upload artifact</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/upload-pages-artifact@v2</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">path</span><span class="pi">:</span> <span class="s">./dist</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Deploy to GitHub Pages</span>
<span class="na">id</span><span class="pi">:</span> <span class="s">deployment</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/deploy-pages@v2</span>
</code></pre></div></div>
<h4 id="update-vite-configuration-for-github-pages">
<a href="#update-vite-configuration-for-github-pages" class="anchor-heading" aria-labelledby="update-vite-configuration-for-github-pages"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Update Vite Configuration for GitHub Pages
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// vite.config.js</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">defineConfig</span><span class="p">({</span>
<span class="na">base</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_ENV</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">production</span><span class="dl">'</span>
<span class="p">?</span> <span class="dl">'</span><span class="s1">/your-repo-name/</span><span class="dl">'</span>
<span class="p">:</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">// ... rest of configuration</span>
<span class="p">});</span>
</code></pre></div></div><hr />
<h2 id="server-hosting">
<a href="#server-hosting" class="anchor-heading" aria-labelledby="server-hosting"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Server Hosting
</h2>
<h3 id="nginx-configuration">
<a href="#nginx-configuration" class="anchor-heading" aria-labelledby="nginx-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Nginx Configuration
</h3>
<h4 id="basic-setup">
<a href="#basic-setup" class="anchor-heading" aria-labelledby="basic-setup"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Basic Setup
</h4>
<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># /etc/nginx/sites-available/gentelella</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">yoursite.com</span> <span class="s">www.yoursite.com</span><span class="p">;</span>
<span class="kn">root</span> <span class="n">/var/www/gentelella/dist</span><span class="p">;</span>
<span class="kn">index</span> <span class="s">index.html</span><span class="p">;</span>
<span class="c1"># Gzip compression</span>
<span class="kn">gzip</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">gzip_vary</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">gzip_min_length</span> <span class="mi">1024</span><span class="p">;</span>
<span class="kn">gzip_types</span>
<span class="nc">text/plain</span>
<span class="nc">text/css</span>
<span class="nc">text/xml</span>
<span class="nc">text/javascript</span>
<span class="nc">application/javascript</span>
<span class="nc">application/xml</span><span class="s">+rss</span>
<span class="nc">application/json</span><span class="p">;</span>
<span class="c1"># Security headers</span>
<span class="kn">add_header</span> <span class="s">X-Frame-Options</span> <span class="s">"SAMEORIGIN"</span> <span class="s">always</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">X-XSS-Protection</span> <span class="s">"1</span><span class="p">;</span> <span class="kn">mode=block"</span> <span class="s">always</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">X-Content-Type-Options</span> <span class="s">"nosniff"</span> <span class="s">always</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">Referrer-Policy</span> <span class="s">"no-referrer-when-downgrade"</span> <span class="s">always</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">Content-Security-Policy</span> <span class="s">"default-src</span> <span class="s">'self'</span> <span class="s">http:</span> <span class="s">https:</span> <span class="s">data:</span> <span class="s">blob:</span> <span class="s">'unsafe-inline'"</span> <span class="s">always</span><span class="p">;</span>
<span class="c1"># Cache static assets</span>
<span class="kn">location</span> <span class="p">~</span><span class="sr">*</span> <span class="err">\</span><span class="s">.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)</span>$ <span class="p">{</span>
<span class="kn">expires</span> <span class="s">1y</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">Cache-Control</span> <span class="s">"public,</span> <span class="s">immutable"</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># Handle SPA routing</span>
<span class="kn">location</span> <span class="n">/</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="n">/index.html</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># API proxy (if needed)</span>
<span class="kn">location</span> <span class="n">/api/</span> <span class="p">{</span>
<span class="kn">proxy_pass</span> <span class="s">http://localhost:8080/</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="nv">$host</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Real-IP</span> <span class="nv">$remote_addr</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-Proto</span> <span class="nv">$scheme</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="ssl-with-lets-encrypt">
<a href="#ssl-with-lets-encrypt" class="anchor-heading" aria-labelledby="ssl-with-lets-encrypt"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> SSL with Let’s Encrypt
</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install Certbot</span>
<span class="nb">sudo </span>apt <span class="nb">install </span>certbot python3-certbot-nginx
<span class="c"># Get SSL certificate</span>
<span class="nb">sudo </span>certbot <span class="nt">--nginx</span> <span class="nt">-d</span> yoursite.com <span class="nt">-d</span> www.yoursite.com
<span class="c"># Auto-renewal (add to crontab)</span>
0 12 <span class="k">*</span> <span class="k">*</span> <span class="k">*</span> /usr/bin/certbot renew <span class="nt">--quiet</span>
</code></pre></div></div>
<h3 id="apache-configuration">
<a href="#apache-configuration" class="anchor-heading" aria-labelledby="apache-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Apache Configuration
</h3>
<h4 id="virtual-host-setup">
<a href="#virtual-host-setup" class="anchor-heading" aria-labelledby="virtual-host-setup"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Virtual Host Setup
</h4>
<div class="language-apache highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /etc/apache2/sites-available/gentelella.conf</span>
<span class="p"><</span><span class="nl">VirtualHost</span><span class="sr"> *:80</span><span class="p">>
</span> <span class="nc">ServerName</span> yoursite.com
<span class="nc">ServerAlias</span> www.yoursite.com
<span class="nc">DocumentRoot</span> /var/www/gentelella/dist
<span class="c"># Enable compression</span>
<span class="nc">LoadModule</span> deflate_module modules/mod_deflate.so
<span class="p"><</span><span class="nl">Location</span><span class="sr"> /</span><span class="p">>
</span> <span class="nc">SetOutputFilter</span> DEFLATE
<span class="nc">SetEnvIfNoCase</span> <span class="ss">Request_URI</span> \
<span class="err">\.(?:</span>gif|jpe?g|png)$ no-gzip dont-vary
<span class="nc">SetEnvIfNoCase</span> <span class="ss">Request_URI</span> \
<span class="err">\.(?:</span>exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
<span class="p"></</span><span class="nl">Location</span><span class="p">>
</span>
<span class="c"># Cache static assets</span>
<span class="p"><</span><span class="nl">LocationMatch</span><span class="sr"> "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$"</span><span class="p">>
</span> <span class="nc">ExpiresActive</span> <span class="ss">On</span>
<span class="nc">ExpiresDefault</span> "access plus 1 year"
<span class="nc">Header</span> <span class="ss">append</span> Cache-Control "public, immutable"
<span class="p"></</span><span class="nl">LocationMatch</span><span class="p">>
</span>
<span class="c"># Handle SPA routing</span>
<span class="p"><</span><span class="nl">Directory</span><span class="sr"> /var/www/gentelella/dist</span><span class="p">>
</span> <span class="nc">RewriteEngine</span> <span class="ss">On</span>
<span class="nc">RewriteBase</span> /
<span class="nc">RewriteRule</span> ^index\.html$ - [L]
<span class="nc">RewriteCond</span> %{REQUEST_FILENAME} !-f
<span class="nc">RewriteCond</span> %{REQUEST_FILENAME} !-d
<span class="nc">RewriteRule</span> . /index.html [L]
<span class="p"></</span><span class="nl">Directory</span><span class="p">>
</span>
<span class="nc">ErrorLog</span> ${APACHE_LOG_DIR}/gentelella_error.log
<span class="nc">CustomLog</span> ${APACHE_LOG_DIR}/gentelella_access.log combined
<span class="p"></</span><span class="nl">VirtualHost</span><span class="p">>
</span></code></pre></div></div><hr />
<h2 id="container-deployment">
<a href="#container-deployment" class="anchor-heading" aria-labelledby="container-deployment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Container Deployment
</h2>
<h3 id="docker-setup">
<a href="#docker-setup" class="anchor-heading" aria-labelledby="docker-setup"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Docker Setup
</h3>
<h4 id="dockerfile">
<a href="#dockerfile" class="anchor-heading" aria-labelledby="dockerfile"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Dockerfile
</h4>
<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Build stage</span>
<span class="k">FROM</span><span class="w"> </span><span class="s">node:18-alpine</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="s">build-stage</span>
<span class="k">WORKDIR</span><span class="s"> /app</span>
<span class="k">COPY</span><span class="s"> package*.json ./</span>
<span class="k">RUN </span>npm ci <span class="nt">--only</span><span class="o">=</span>production
<span class="k">COPY</span><span class="s"> . .</span>
<span class="k">RUN </span>npm run build
<span class="c"># Production stage</span>
<span class="k">FROM</span><span class="w"> </span><span class="s">nginx:alpine</span><span