Install Frontend
Frontend Installation Guide
Section titled âFrontend Installation GuideâThis guide covers setting up the client-facing website that consumes content from your Stelo CMS backend.
Prerequisites
Section titled âPrerequisitesâBefore starting, ensure you have:
- Stelo CMS Backend running (see Backend Installation)
- Node.js 18+ installed
- pnpm or npm package manager
- Git for version control
- Access to CMS API endpoints
Development Setup
Section titled âDevelopment Setupâ1. Clone the Frontend Template
Section titled â1. Clone the Frontend Templateâ# Clone the frontend templategit clone https://github.com/your-username/template-stelo-frontend.git client-project-frontendcd client-project-frontend
# Remove the original git historyrm -rf .gitgit initgit add .git commit -m "Initial commit from Stelo frontend template"2. Install Dependencies
Section titled â2. Install Dependenciesâ# Using pnpm (recommended)pnpm install
# Or using npmnpm install3. Environment Configuration
Section titled â3. Environment ConfigurationâCopy the environment template and configure your variables:
cp .env.example .env.localEdit .env.local with your configuration:
# CMS API ConfigurationNEXT_PUBLIC_CMS_URL="http://localhost:3000" # Your CMS backend URLCMS_API_TOKEN="your-api-token" # For server-side requests
# Site ConfigurationNEXT_PUBLIC_SITE_URL="http://localhost:3001"NEXT_PUBLIC_SITE_NAME="Client Site Name"
# Analytics (Optional)NEXT_PUBLIC_GA_ID="G-XXXXXXXXXX"NEXT_PUBLIC_GTM_ID="GTM-XXXXXXX"
# Email Contact Form (Optional)SMTP_HOST="smtp.gmail.com"SMTP_PORT="587"SMTP_USER="contact@client-domain.com"SMTP_PASSWORD="your-app-password"
# SEO & SocialNEXT_PUBLIC_DEFAULT_OG_IMAGE="/images/og-default.jpg"NEXT_PUBLIC_TWITTER_HANDLE="@clienthandle"4. Configure API Connection
Section titled â4. Configure API ConnectionâUpdate the tRPC client configuration in src/lib/trpc.ts:
import { createTRPCNext } from '@trpc/next';import { httpBatchLink } from '@trpc/client';import type { AppRouter } from '../../../stelo-cms/src/app/api/trpc/route';
function getBaseUrl() { if (typeof window !== 'undefined') return ''; if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; return `http://localhost:${process.env.PORT ?? 3001}`;}
export const trpc = createTRPCNext<AppRouter>({ config() { return { links: [ httpBatchLink({ url: `${process.env.NEXT_PUBLIC_CMS_URL}/api/trpc`, headers() { return { Authorization: `Bearer ${process.env.CMS_API_TOKEN}`, }; }, }), ], }; }, ssr: false,});5. Internationalization Setup
Section titled â5. Internationalization SetupâConfigure supported locales in src/middleware.ts:
import createMiddleware from 'next-intl/middleware';
export default createMiddleware({ // A list of all locales that are supported locales: ['en', 'fr', 'es'],
// Used when no locale matches defaultLocale: 'en'});
export const config = { // Match only internationalized pathnames matcher: ['/', '/(fr|es)/:path*']};Create locale message files:
# Create message directoriesmkdir -p messages
# Create message files for each localetouch messages/en.json messages/fr.json messages/es.jsonExample messages/en.json:
{ "navigation": { "home": "Home", "about": "About", "services": "Services", "contact": "Contact" }, "common": { "readMore": "Read More", "contactUs": "Contact Us", "loading": "Loading..." }, "pages": { "home": { "title": "Welcome to Our Website", "subtitle": "We provide excellent services" } }}6. Start Development Server
Section titled â6. Start Development Serverâ# Start the development serverpnpm dev
# The frontend will be available at:# http://localhost:30017. Test API Connection
Section titled â7. Test API ConnectionâCreate a test page to verify CMS connection:
import { trpc } from '@/lib/trpc';
export default async function TestPage() { const pages = await trpc.pages.getAll.query();
return ( <div> <h1>CMS Connection Test</h1> <p>Found {pages.length} pages in CMS</p> <ul> {pages.map((page) => ( <li key={page.id}>{page.title.en}</li> ))} </ul> </div> );}Production Deployment
Section titled âProduction Deploymentâ1. Choose Deployment Platform
Section titled â1. Choose Deployment PlatformâOption A: Vercel (Recommended)
Section titled âOption A: Vercel (Recommended)â# Install Vercel CLInpm i -g vercel
# Deploy to Vercelvercel
# Follow the prompts to configure your projectOption B: Coolify (Same VPS as CMS)
Section titled âOption B: Coolify (Same VPS as CMS)â# In your Coolify dashboard:# 1. Create new application# 2. Connect Git repository# 3. Set build pack to Node.js# 4. Configure environment variables2. Production Environment Variables
Section titled â2. Production Environment Variablesâ# CMS API ConfigurationNEXT_PUBLIC_CMS_URL="https://cms.client-domain.com"CMS_API_TOKEN="production-api-token"
# Site ConfigurationNEXT_PUBLIC_SITE_URL="https://client-domain.com"NEXT_PUBLIC_SITE_NAME="Client Name"
# AnalyticsNEXT_PUBLIC_GA_ID="G-REAL-ID"NEXT_PUBLIC_GTM_ID="GTM-REAL-ID"
# EmailSMTP_HOST="smtp.client-domain.com"SMTP_PORT="587"SMTP_USER="noreply@client-domain.com"SMTP_PASSWORD="production-password"3. Build Configuration
Section titled â3. Build ConfigurationâOptimize next.config.js for production:
/** @type {import('next').NextConfig} */const withNextIntl = require('next-intl/plugin')('./src/i18n.ts');
const nextConfig = { // Image optimization images: { domains: ['your-cms-domain.com', 'fra1.digitaloceanspaces.com'], formats: ['image/webp', 'image/avif'], },
// Compression compress: true,
// Static export for better performance output: 'export', trailingSlash: true,
// Security headers async headers() { return [ { source: '/(.*)', headers: [ { key: 'X-Frame-Options', value: 'DENY', }, { key: 'X-Content-Type-Options', value: 'nosniff', }, { key: 'Referrer-Policy', value: 'origin-when-cross-origin', }, ], }, ]; },};
module.exports = withNextIntl(nextConfig);4. Domain Configuration
Section titled â4. Domain ConfigurationâDNS Settings
Section titled âDNS SettingsâType: AName: @Value: your-vercel-ip (or VPS IP)TTL: 300
Type: AName: wwwValue: your-vercel-ip (or VPS IP)TTL: 300SSL Certificate
Section titled âSSL Certificateâ- Vercel: Automatic SSL via Letâs Encrypt
- Coolify: Automatic SSL configuration
Performance Optimization
Section titled âPerformance Optimizationâ1. Image Optimization
Section titled â1. Image OptimizationâConfigure Next.js Image component:
import Image from 'next/image';import { useState } from 'react';
interface OptimizedImageProps { src: string; alt: string; width: number; height: number; className?: string;}
export default function OptimizedImage({ src, alt, width, height, className,}: OptimizedImageProps) { const [isLoading, setLoading] = useState(true);
return ( <Image src={src} alt={alt} width={width} height={height} className={`${className} ${ isLoading ? 'blur-sm' : 'blur-0' } transition-all duration-300`} onLoadingComplete={() => setLoading(false)} priority={false} /> );}2. Static Generation
Section titled â2. Static GenerationâConfigure static page generation:
import { trpc } from '@/lib/trpc';
// Generate static paths for all pagesexport async function generateStaticParams() { const pages = await trpc.pages.getPublished.query();
return pages.map((page) => ({ slug: page.slug, }));}
// Static generation with revalidationexport const revalidate = 3600; // Revalidate every hour3. SEO Optimization
Section titled â3. SEO OptimizationâCreate SEO component:
import Head from 'next/head';import { useTranslations } from 'next-intl';
interface SEOProps { title?: string; description?: string; image?: string; url?: string;}
export default function SEO({ title, description, image, url }: SEOProps) { const t = useTranslations('seo');
const siteTitle = process.env.NEXT_PUBLIC_SITE_NAME; const fullTitle = title ? `${title} | ${siteTitle}` : siteTitle; const metaDescription = description || t('defaultDescription'); const ogImage = image || process.env.NEXT_PUBLIC_DEFAULT_OG_IMAGE; const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
return ( <Head> <title>{fullTitle}</title> <meta name="description" content={metaDescription} />
{/* Open Graph */} <meta property="og:title" content={fullTitle} /> <meta property="og:description" content={metaDescription} /> <meta property="og:image" content={ogImage} /> <meta property="og:url" content={url || siteUrl} /> <meta property="og:type" content="website" />
{/* Twitter */} <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content={fullTitle} /> <meta name="twitter:description" content={metaDescription} /> <meta name="twitter:image" content={ogImage} />
{/* Additional Meta */} <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="canonical" href={url || siteUrl} /> </Head> );}Testing & Quality Assurance
Section titled âTesting & Quality Assuranceâ1. Setup Testing
Section titled â1. Setup Testingâ# Install testing dependenciespnpm add -D @testing-library/react @testing-library/jest-dom jest jest-environment-jsdom
# Create test configurationtouch jest.config.jsJest configuration:
const nextJest = require('next/jest');
const createJestConfig = nextJest({ dir: './',});
const customJestConfig = { setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], moduleNameMapping: { '^@/(.*)$': '<rootDir>/src/$1', }, testEnvironment: 'jest-environment-jsdom',};
module.exports = createJestConfig(customJestConfig);2. Lighthouse Optimization
Section titled â2. Lighthouse OptimizationâOptimize for Core Web Vitals:
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'], display: 'swap', variable: '--font-inter',});
export default function RootLayout({ children,}: { children: React.ReactNode;}) { return ( <html lang="en" className={inter.variable}> <body className="font-sans antialiased"> {children} </body> </html> );}3. Analytics Setup
Section titled â3. Analytics Setupâimport { GoogleAnalytics } from '@next/third-parties/google';
export function Analytics() { const gaId = process.env.NEXT_PUBLIC_GA_ID;
if (!gaId) return null;
return <GoogleAnalytics gaId={gaId} />;}Troubleshooting
Section titled âTroubleshootingâCommon Issues
Section titled âCommon IssuesâAPI Connection Errors
Section titled âAPI Connection Errorsâ# Check CMS availabilitycurl https://cms.client-domain.com/api/health
# Verify API tokenecho $CMS_API_TOKENBuild Failures
Section titled âBuild Failuresâ# Clear Next.js cacherm -rf .nextpnpm buildInternationalization Issues
Section titled âInternationalization Issuesâ# Verify locale configurationcat src/middleware.tscat messages/en.jsonMaintenance
Section titled âMaintenanceâRegular Tasks
Section titled âRegular Tasksâ- Weekly: Check site performance and analytics
- Monthly: Update dependencies and security patches
- Quarterly: Review and optimize Core Web Vitals
- Annually: Audit and update SEO strategy
Monitoring
Section titled âMonitoringâ- Uptime: Set up monitoring with services like UptimeRobot
- Performance: Use Lighthouse CI for continuous monitoring
- Analytics: Regular review of Google Analytics data
- Errors: Set up error tracking with Sentry
Next Steps
Section titled âNext StepsâAfter successful frontend installation:
- Configure Content - Set up your content structure in CMS
- Implement i18n - Complete internationalization setup
- Optimize SEO - Implement advanced SEO strategies