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