Skip to main content
Kayston’s Forge is built as a fully static Next.js application with output: 'export'. This makes it compatible with any static hosting platform and ensures complete client-side privacy.

Static Export Architecture

The application uses Next.js static export mode configured in next.config.mjs:
const nextConfig = {
  output: 'export',              // Generate static HTML/CSS/JS
  images: {
    unoptimized: true,           // Required for static export
  },
  experimental: {
    optimizePackageImports: ['@heroicons/react'],
  },
};

What This Means

  • No server required: All pages are pre-rendered as HTML
  • No API routes: All processing happens client-side
  • No dynamic routes: Tool pages are generated via generateStaticParams()
  • PWA-ready: Service worker and manifest for offline support

Building for Production

1

Run the build command

npm run build
This command:
  • Compiles TypeScript to JavaScript
  • Bundles React components
  • Generates static HTML for all tool pages
  • Optimizes CSS with Tailwind
  • Creates the out/ directory
2

Verify the output

ls out/
You should see:
out/
├── _next/           # Optimized JS/CSS bundles
├── tools/           # Static tool pages
│   ├── json-format-validate.html
│   ├── base64-string.html
│   └── ... (51 tools)
├── index.html       # Root redirect
├── manifest.json    # PWA manifest
├── sw.js            # Service worker
└── favicon.svg
3

Test locally (optional)

Serve the static files locally to verify:
npx serve out
Or use any static file server:
python3 -m http.server 3000 --directory out

Deploying to Vercel

Vercel provides the simplest deployment experience for Next.js applications.

Automatic Deployment

1

Connect to GitHub

  1. Push your code to GitHub
  2. Visit vercel.com
  3. Click “New Project”
  4. Import your repository
2

Configure project

Vercel auto-detects Next.js. No configuration needed:
  • Framework Preset: Next.js
  • Build Command: npm run build
  • Output Directory: out (auto-detected)
3

Deploy

Click “Deploy” and wait for the build to complete.Vercel will:
  • Install dependencies
  • Run npm run build
  • Deploy the out/ directory to CDN
  • Provide a production URL
4

Configure custom domain (optional)

In Vercel dashboard:
  1. Go to Project Settings → Domains
  2. Add your custom domain
  3. Update DNS records as instructed

Manual Deployment

Deploy from the command line:
# Install Vercel CLI
npm install -g vercel

# Build the project
npm run build

# Deploy
vercel --prod

Vercel Configuration

The project includes vercel.json with security headers:
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Content-Security-Policy",
          "value": "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
        },
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        },
        {
          "key": "Permissions-Policy",
          "value": "camera=(), microphone=(), geolocation=()"
        },
        {
          "key": "Strict-Transport-Security",
          "value": "max-age=31536000; includeSubDomains"
        }
      ]
    }
  ]
}

Deploying to Other Platforms

The static export works with any static hosting provider:
# Build
npm run build

# Deploy
netlify deploy --prod --dir=out

Build Configuration

Environment Variables

For build-time configuration, use .env.local:
# .env.local
NEXT_PUBLIC_APP_VERSION=1.0.0
NEXT_PUBLIC_ANALYTICS_ID=UA-XXXXX
Access in code:
const version = process.env.NEXT_PUBLIC_APP_VERSION;
Only variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Never put secrets in environment variables for static sites.

Build Optimization

The current bundle size is ~513 kB. Optimization strategies:

1. Dynamic Imports

Replace static imports with dynamic imports for large dependencies:
// Before (loads on every page)
import { marked } from 'marked';

// After (loads only when needed)
case 'markdown-preview': {
  const { marked } = await import('marked');
  // Use marked...
}

2. Code Splitting

Split tool logic into separate chunks:
// next.config.mjs
const nextConfig = {
  output: 'export',
  experimental: {
    optimizePackageImports: [
      '@heroicons/react',
      'crypto-js',
      'terser',
    ],
  },
};

3. Remove Unused Dependencies

Regularly audit dependencies:
npx depcheck

Build Troubleshooting

Build Fails with “Error: Dynamic Code Evaluation”

Some libraries use eval() which doesn’t work in static export:
// Solution: Use minify_sync instead of minify
const { minify_sync } = await import('terser');
const result = minify_sync(code);

Build Fails with “Error: Image Optimization”

Next.js Image Optimization requires a server. Use unoptimized: true:
// next.config.mjs
images: {
  unoptimized: true,
}

Build Succeeds but Pages 404

Ensure generateStaticParams() returns all tool IDs:
// app/tools/[toolId]/page.tsx
export function generateStaticParams() {
  return tools.map((tool) => ({
    toolId: tool.id,
  }));
}

Large Bundle Size Warning

Next.js warns if bundles exceed 244 kB. For this app, it’s expected:
Warning: First Load JS shared by all: 513 kB
To reduce:
  • Use dynamic imports for heavy dependencies
  • Split tools into separate route groups
  • Remove unused dependencies

Deployment Checklist

1

Pre-deployment checks

  • All tests pass (npm run test)
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • Security audit passes (npm run audit)
  • Static export works locally (npx serve out)
2

Security verification

  • vercel.json has security headers
  • No secrets in environment variables
  • Content Security Policy configured
  • HTTPS enforced in production
3

Performance verification

  • Bundle size is acceptable
  • Service worker caches assets
  • PWA manifest is valid
  • Images are optimized
4

Functionality verification

  • All tools work in production
  • Command palette search works
  • Keyboard shortcuts work
  • History saves/restores correctly
  • Offline mode works (PWA)

Continuous Deployment

Set up automatic deployments on push:

GitHub Actions + Vercel

# .github/workflows/deploy.yml
name: Deploy to Vercel

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm install
      - run: npm run test
      - 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'

Monitoring

After deployment, monitor:

1. Analytics

Add privacy-respecting analytics:
// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <Script
          src="https://analytics.example.com/script.js"
          strategy="afterInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

2. Error Tracking

Monitor client-side errors:
// app/layout.tsx
if (typeof window !== 'undefined') {
  window.addEventListener('error', (event) => {
    console.error('Global error:', event.error);
    // Send to error tracking service
  });
}

3. Performance Monitoring

Track Core Web Vitals:
// app/layout.tsx
import { sendToAnalytics } from './analytics';

export function reportWebVitals(metric) {
  sendToAnalytics(metric);
}

Rollback Strategy

If a deployment breaks:
1

Vercel: Instant Rollback

In Vercel dashboard:
  1. Go to Deployments
  2. Find previous working deployment
  3. Click “Promote to Production”
2

Other platforms: Redeploy

git revert HEAD
git push
# Redeploy previous commit
3

Fix and redeploy

  1. Identify the issue
  2. Fix in a new branch
  3. Test thoroughly
  4. Deploy via PR/merge

Security Considerations

  • CSP Headers: Configured in vercel.json to prevent XSS
  • HTTPS Only: Enforced by hosting platform
  • No Secrets: All processing is client-side
  • Subresource Integrity: Consider adding SRI hashes for CDN resources
  • Dependency Scanning: GitHub Dependabot monitors for vulnerabilities
Never deploy with failing tests or security audit warnings. Run npm run test and npm run audit before every deployment.

Next Steps

Build docs developers (and LLMs) love