Skip to content

Frontend Application (Next.js)

Complete guide to deploying and managing the Next.js frontend application with server-side rendering and optimal performance.

The frontend is a modern Next.js application optimized for production deployment in Kubernetes. It provides a fast, SEO-friendly user interface with server-side rendering capabilities.

Frontend Deployment:
├── Next.js Container (SSR Application)
├── Persistent Volume (Build Cache)
├── Auto-scaling (HPA)
└── Ingress (SSL/TLS)
  • Framework: Next.js 13+ with App Router
  • Runtime: Node.js 18+ LTS
  • Rendering: Server-Side Rendering (SSR) and Static Generation
  • Styling: Modern CSS-in-JS or Tailwind CSS
  • TypeScript: Full type safety
  • Server-Side Rendering: Improved SEO and initial page load
  • Static Generation: Pre-built pages for optimal performance
  • Image Optimization: Next.js built-in image optimization
  • Build Cache: Persistent volume for faster builds
  • Progressive Web App: PWA capabilities enabled
frontend:
image: ghcr.io/hsm00/myproject-mono/frontend:latest
port: 3000
resources:
requests:
cpu: 300m
memory: 400Mi
limits:
cpu: 600m
memory: 2Gi

The frontend uses environment variables for configuration:

NEXT_PUBLIC_APP_URL=https://myproject.com
NEXT_PUBLIC_BACKEND_URL=https://app.myproject.com
NODE_ENV=production
NEXT_PUBLIC_GOOGLE_API_KEY=[your-google-api-key]
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=[your-stripe-key]
NEXT_PUBLIC_REVERB_HOST=app.myproject.com
NEXT_PUBLIC_REVERB_APP_KEY=[your-reverb-key]
NEXT_PUBLIC_REVERB_PORT=443
NEXT_PUBLIC_REVERB_SCHEME=https
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 10
periodSeconds: 5

The frontend uses a persistent volume to cache Next.js build artifacts:

persistence:
enabled: true
accessMode: ReadWriteOnce
size: 10Gi
mountPath: /app/.next/cache

Benefits:

  • Faster subsequent builds
  • Reduced memory usage
  • Improved deployment times
  • Better resource utilization
volumes:
- name: cache-volume
persistentVolumeClaim:
claimName: frontend-cache
volumeMounts:
- name: cache-volume
mountPath: /app/.next/cache
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 80
# Optional memory-based scaling
targetMemoryUtilizationPercentage: 70
  • Scale Up: When CPU > 80% for 2 minutes
  • Scale Down: When CPU < 50% for 5 minutes
  • Max Surge: 1 pod at a time
  • Max Unavailable: 0 (zero-downtime scaling)

For traffic-based scaling:

behavior:
scaleUp:
stabilizationWindowSeconds: 120
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
  • Primary Domain: myproject.com
  • WWW Alias: www.myproject.com
  • SSL/TLS: Automatic Let’s Encrypt certificates
ingress:
enabled: true
className: traefik
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: letsencrypt
traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
hosts:
- host: myproject.com
paths:
- path: /
pathType: Prefix
- host: www.myproject.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myproject-tls
hosts:
- myproject.com
- www.myproject.com

Automatic HTTP to HTTPS redirection:

# Traefik middleware for HTTPS redirect
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-https
spec:
redirectScheme:
scheme: https
permanent: true

Optimized Next.js configuration for production:

next.config.js
const nextConfig = {
output: "standalone",
experimental: {
serverComponentsExternalPackages: [],
},
images: {
domains: ["static.myproject.com"],
formats: ["image/webp", "image/avif"],
},
compress: true,
poweredByHeader: false,
};
module.exports = nextConfig;
// Optimized image component usage
import Image from "next/image";
<Image
src="/hero-image.jpg"
alt="Hero Image"
width={800}
height={600}
priority
sizes="(max-width: 768px) 100vw, 50vw"
/>;
  • Static assets with long-term caching
  • Incremental Static Regeneration (ISR)
  • Optimized bundle splitting
  • API response caching
  • Client-side navigation caching
  • Service worker for offline support
  • Meta Tags: Dynamic meta tag generation
  • Structured Data: JSON-LD schema markup
  • Sitemap: Automatic sitemap generation
  • Robots.txt: Search engine directives
  • Google Analytics: Page view tracking
  • Performance Monitoring: Core Web Vitals
  • User Behavior: Custom event tracking
  • Multi-language Support: English and German
  • Locale Routing: Automatic locale detection
  • Content Translation: Localized content management
  • Service Worker: Offline functionality
  • App Manifest: Install prompt
  • Push Notifications: User engagement
  • Background Sync: Data synchronization
Terminal window
# Basic deployment
helm upgrade --install frontend ./frontend \
--namespace production \
--create-namespace
# Deploy specific version
helm upgrade --install frontend ./frontend \
--namespace production \
--set image.tag=v1.2.3
# Deploy with custom domain
helm upgrade --install frontend ./frontend \
--namespace production \
--set ingress.hosts[0].host=yourdomain.com
Terminal window
# Rolling update
helm upgrade frontend ./frontend \
--namespace production \
--set image.tag=v1.2.4 \
--wait --timeout=10m
# Force restart
kubectl rollout restart deployment/frontend -n production
Terminal window
# Check pod status
kubectl get pods -n production -l app.kubernetes.io/name=frontend
# Check deployment status
kubectl rollout status deployment/frontend -n production
# Test application
curl -I https://myproject.com
Terminal window
# View application logs
kubectl logs -f deployment/frontend -n production
# Check recent logs
kubectl logs --tail=100 deployment/frontend -n production
# Filter logs by level
kubectl logs deployment/frontend -n production | grep ERROR

Key metrics to monitor:

  • Response Time: Page load performance
  • First Contentful Paint (FCP): Initial rendering time
  • Largest Contentful Paint (LCP): Largest element rendering
  • Time to Interactive (TTI): Interactivity readiness
  • Cumulative Layout Shift (CLS): Visual stability
Terminal window
# Application health
curl https://myproject.com
# Check SSL certificate
curl -vI https://myproject.com 2>&1 | grep -A 2 "SSL certificate"
# Lighthouse performance check
lighthouse https://myproject.com --output=json
Terminal window
# Check pod events
kubectl describe pod frontend-xxx -n production
# Check container logs
kubectl logs frontend-xxx -n production
# Check resource usage
kubectl top pod frontend-xxx -n production
Terminal window
# Check persistent volume
kubectl get pv
kubectl describe pvc frontend-cache -n production
# Clear build cache
kubectl exec -it deployment/frontend -n production -- rm -rf /app/.next/cache/*
Terminal window
# Check certificate status
kubectl get certificate -n production
kubectl describe certificate myproject-tls -n production
# Check cert-manager logs
kubectl logs -f deployment/cert-manager -n cert-manager
Terminal window
# Check HPA status
kubectl get hpa -n production
kubectl describe hpa frontend -n production
# Monitor resource usage
kubectl top pods -n production -l app.kubernetes.io/name=frontend
Terminal window
# Interactive shell
kubectl exec -it deployment/frontend -n production -- sh
# Check Next.js build
kubectl exec -it deployment/frontend -n production -- ls -la /app/.next
# Verify environment variables
kubectl exec -it deployment/frontend -n production -- env | grep NEXT_PUBLIC
next.config.js
const securityHeaders = [
{
key: "Content-Security-Policy",
value:
"default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline';",
},
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
];
module.exports = {
async headers() {
return [
{
source: "/(.*)",
headers: securityHeaders,
},
];
},
};
Terminal window
# Sensitive variables (use Kubernetes Secrets)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY # Safe (public)
STRIPE_SECRET_KEY # Dangerous (use Secret)
NEXT_PUBLIC_GOOGLE_API_KEY # Safe (public, restricted)
  • HTTPS Only: All traffic encrypted
  • HSTS Headers: HTTP Strict Transport Security
  • Secure Cookies: HttpOnly and Secure flags
custom-values.yaml
image:
tag: "v1.2.3"
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
resources:
requests:
cpu: 500m
memory: 800Mi
limits:
cpu: 1000m
memory: 2Gi
ingress:
hosts:
- host: yourdomain.com
- host: www.yourdomain.com
Terminal window
# Production deployment
helm upgrade --install frontend-prod ./frontend \
--namespace production \
--values values-production.yaml
# Staging deployment
helm upgrade --install frontend-staging ./frontend \
--namespace staging \
--values values-staging.yaml \
--set ingress.hosts[0].host=staging.yourdomain.com
  • Monitor application performance
  • Check error rates and logs
  • Verify SSL certificate status
  • Update dependencies
  • Review performance metrics
  • Check build cache utilization
  • Security updates
  • Performance optimization
  • Capacity planning review
Terminal window
# Configuration backup
kubectl get configmap frontend-config -o yaml > backup-frontend-config.yaml
# Persistent volume backup
kubectl create job --from=cronjob/backup-pvc backup-frontend-cache
# Restore configuration
kubectl apply -f backup-frontend-config.yaml
// Update branding in layout.tsx
export const metadata = {
title: "Your SaaS Application",
description: "Your application description",
icons: {
icon: "/favicon.ico",
shortcut: "/favicon-16x16.png",
apple: "/apple-touch-icon.png",
},
};
// Add custom components to src/components/
export interface CustomButtonProps {
variant: 'primary' | 'secondary'
children: React.ReactNode
}
export const CustomButton: React.FC<CustomButtonProps> = ({
variant,
children
}) => {
return (
<button className={`btn btn-${variant}`}>
{children}
</button>
)
}

The Next.js frontend provides a modern, performant user interface optimized for SEO and user experience.