Deploy Crypto Data Aggregator to production.
Vercel is the recommended platform for Next.js applications.
- Install Vercel CLI
npm install -g vercel- Login to Vercel
vercel login- Deploy
# From project root
vercel
# For production
vercel --prod- Configure Environment Variables
# Set optional API key for higher rate limits
vercel env add COINGECKO_API_KEYCreate vercel.json for custom settings:
{
"framework": "nextjs",
"regions": ["iad1"],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" },
{ "key": "Cache-Control", "value": "public, s-maxage=60" }
]
}
]
}API routes automatically deploy to Edge Runtime for low latency:
// src/app/api/market/coins/route.ts
export const runtime = 'edge';Railway provides simple deployments with automatic scaling.
-
Create Railway Account
Go to railway.app and sign up.
-
Deploy from GitHub
- Click "New Project"
- Select "Deploy from GitHub repo"
- Choose
crypto-data-aggregator - Railway auto-detects Next.js
-
Configure Build
Railway auto-detects settings. Override if needed:
Build Command: npm run build Start Command: npm start -
Add Environment Variables
In Railway dashboard:
- Go to Variables tab
- Add
COINGECKO_API_KEY(optional)
Create railway.json:
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "NIXPACKS"
},
"deploy": {
"numReplicas": 1,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 3
}
}- Go to Settings → Domains
- Add custom domain
- Configure DNS:
CNAME your-app.railway.app
Deploy with Docker for maximum portability.
Create Dockerfile in project root:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci
# Copy source
COPY . .
# Build application
RUN npm run build
# Production stage
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Copy built application
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]Create docker-compose.yml:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- COINGECKO_API_KEY=${COINGECKO_API_KEY:-}
restart: unless-stopped
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/trending']
interval: 30s
timeout: 10s
retries: 3# Build image
docker build -t crypto-data-aggregator .
# Run container
docker run -p 3000:3000 crypto-data-aggregator
# With environment variables
docker run -p 3000:3000 \
-e COINGECKO_API_KEY=your_key \
crypto-data-aggregator# Start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose downEnable standalone output in next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};
module.exports = nextConfig;Deploy to your own server.
- Node.js 18+
- npm or yarn
- Process manager (PM2 recommended)
- Reverse proxy (nginx recommended)
- Clone Repository
git clone https://github.com/nirholas/crypto-data-aggregator.git
cd crypto-data-aggregator- Install Dependencies
npm ci --production=false- Build Application
npm run build- Install PM2
npm install -g pm2- Create PM2 Config
Create ecosystem.config.js:
module.exports = {
apps: [
{
name: 'crypto-data-aggregator',
script: 'npm',
args: 'start',
cwd: '/path/to/crypto-data-aggregator',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
env_production: {
NODE_ENV: 'production',
COINGECKO_API_KEY: 'your_key',
},
},
],
};- Start Application
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startupserver {
listen 80;
server_name crypto.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Cache static assets
location /_next/static {
proxy_pass http://localhost:3000;
proxy_cache_valid 200 365d;
add_header Cache-Control "public, max-age=31536000, immutable";
}
}# Install certbot
sudo apt install certbot python3-certbot-nginx
# Get certificate
sudo certbot --nginx -d crypto.yourdomain.com
# Auto-renewal
sudo certbot renew --dry-runNone. The application works with free tier APIs.
| Variable | Description | Default |
|---|---|---|
COINGECKO_API_KEY |
CoinGecko Pro API key | - |
COINGECKO_BASE_URL |
CoinGecko API URL | https://api.coingecko.com/api/v3 |
DEFILLAMA_BASE_URL |
DeFiLlama API URL | https://api.llama.fi |
vercel env add COINGECKO_API_KEYOr via dashboard: Settings → Environment Variables
Dashboard: Variables tab → Add variable
docker run -e COINGECKO_API_KEY=xxx ...Or in docker-compose.yml:
environment:
- COINGECKO_API_KEY=xxxCreate .env.local:
COINGECKO_API_KEY=your_api_key
COINGECKO_BASE_URL=https://pro-api.coingecko.com/api/v3# Check health
curl https://your-domain.com/api/trending
# Check specific endpoint
curl https://your-domain.com/api/market/coins?limit=5Enable in next.config.js:
const nextConfig = {
experimental: {
webVitals: true,
},
};Add response timing in API routes:
import { withTiming } from '@/lib/api-utils';
export async function GET() {
const startTime = Date.now();
const data = await fetchData();
return Response.json(withTiming(data, startTime));
}# Clear cache and rebuild
rm -rf .next node_modules
npm install
npm run build- Add
COINGECKO_API_KEYfor higher limits - Check rate limit state in logs
- Increase cache TTLs if needed
For self-hosted:
# Increase Node.js memory
NODE_OPTIONS="--max-old-space-size=4096" npm startFor Docker:
deploy:
resources:
limits:
memory: 1GAutomatic. Edge functions scale globally.
Increase replicas in settings or railway.json:
{
"deploy": {
"numReplicas": 3
}
}Use PM2 cluster mode:
// ecosystem.config.js
{
instances: 'max', // Use all CPU cores
exec_mode: 'cluster',
}For high traffic:
- Enable Redis for shared cache
- Use CDN for static assets
- Increase stale-while-revalidate windows
Create .github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:run
- run: npm run build
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'Vercel automatically creates preview deployments for PRs.
For Railway:
{
"build": {
"builder": "NIXPACKS"
}
}Railway creates preview environments from PRs when connected to GitHub.