Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deployment and Documentation

From Development to Production

You’ve built it, tested it, refactored it. Now comes the final phase: making it real. This chapter covers the journey from working code to deployed application with comprehensive documentation.

Creating the Documentation Corpus

Transitioning from DevDocs to User Docs

DevDocs served development. Now create user-facing documentation:

Ask AI to create a docs folder and generate documentation for each module.
Documentation should include edge cases and interface specifications.
This step indicates that our codebase is stabilizing and maturing.

Structure your docs:

docs/
├── getting-started/
│   ├── installation.md
│   ├── quick-start.md
│   └── first-expense.md
├── user-guide/
│   ├── expense-management.md
│   ├── categories.md
│   ├── multi-currency.md
│   └── data-export.md
├── api-reference/
│   ├── storage-api.md
│   ├── currency-api.md
│   └── export-api.md
├── troubleshooting/
│   ├── common-issues.md
│   ├── data-recovery.md
│   └── performance.md
└── contributing/
    ├── development-setup.md
    ├── architecture.md
    └── testing.md

Documentation Generation

Let AI help create comprehensive docs:

Please generate user documentation for the Storage module:

1. Read the module's interface.md and implementation
2. Create docs/api-reference/storage-api.md with:
   - Overview of what the module does
   - API reference with all public methods
   - Code examples for common use cases
   - Error handling information
   - Performance considerations
   
Make it readable for developers who'll use this module.

Example output:

# Storage API Reference

## Overview

The Storage module provides local-first data persistence for the expense tracker. All data is stored on the user's device using browser localStorage with automatic serialization and versioning support.

## Basic Usage

```javascript
import { StorageService } from '@modules/storage'

const storage = new StorageService()

// Save an expense
await storage.save('expenses', expenseData)

// Load all expenses
const expenses = await storage.load('expenses', [])

// Delete specific item
await storage.delete('expenses', expenseId)

API Reference

Constructor

new StorageService(options?: StorageOptions)

Creates a new storage instance.

Options:

  • namespace (string): Prefix for all keys (default: ‘app’)
  • version (number): Storage version for migrations (default: 1)

Methods

save(key: string, data: any): Promise

Saves data to storage.

Parameters:

  • key: Storage key identifier
  • data: Data to store (will be JSON serialized)

Example:

await storage.save('user-preferences', {
  currency: 'USD',
  theme: 'dark'
})

Errors:

  • StorageQuotaError: When storage limit exceeded
  • SerializationError: When data cannot be serialized

[… continues with all methods …]


## Creating the Production Test Suite

### Converting Smoke Tests to Production Tests

Transform verbose smoke tests into CI-ready tests:

Please analyze all smoke test files across all modules and create a comprehensive test suite in the root directory.

Requirements:

  1. Convert smoke tests into properly structured test files using Jest
  2. Organize tests logically for CI/CD pipeline execution
  3. Include appropriate test utilities and helpers
  4. Generate test documentation that explains the testing strategy

This will serve as our production-ready test suite for continuous integration.


### Test Suite Organization

Create a professional test structure:

```javascript
// tests/setup.js
// Global test configuration

beforeEach(() => {
  // Clear all mocks
  jest.clearAllMocks()
  
  // Reset localStorage
  localStorage.clear()
  
  // Reset test data
  global.testData = createTestData()
})

// Suppress console during tests unless debugging
if (!process.env.DEBUG) {
  global.console = {
    ...console,
    log: jest.fn(),
    error: jest.fn(),
    warn: jest.fn()
  }
}
// tests/unit/modules/storage.test.js
// Production-ready unit tests

import { StorageService } from '@/modules/storage'
import { StorageQuotaError } from '@/modules/storage/errors'

describe('StorageService', () => {
  let storage
  
  beforeEach(() => {
    storage = new StorageService()
  })
  
  describe('save', () => {
    it('should persist data to localStorage', async () => {
      const data = { id: 1, amount: 100 }
      
      await storage.save('test-key', data)
      
      const stored = localStorage.getItem('app:test-key')
      expect(JSON.parse(stored)).toEqual(data)
    })
    
    it('should handle storage quota exceeded', async () => {
      // Fill storage to near capacity
      const largeData = 'x'.repeat(5 * 1024 * 1024) // 5MB
      
      await expect(
        storage.save('large', largeData)
      ).rejects.toThrow(StorageQuotaError)
    })
  })
  
  // ... more focused tests
})

Test Documentation

Create comprehensive test documentation:

# Testing Strategy

## Overview

Our test suite ensures reliability across three levels:
1. Unit tests - Individual modules in isolation
2. Integration tests - Modules working together
3. E2E tests - Complete user workflows

## Running Tests

```bash
# All tests
npm test

# Unit tests only
npm run test:unit

# Integration tests
npm run test:integration

# E2E tests
npm run test:e2e

# With coverage
npm run test:coverage

Test Structure

Unit Tests

  • Located in tests/unit/
  • One file per module
  • Mock external dependencies
  • Fast execution (< 10s total)

Integration Tests

  • Located in tests/integration/
  • Test module interactions
  • Use real implementations
  • Moderate execution (< 30s total)

E2E Tests

  • Located in tests/e2e/
  • Test complete workflows
  • Simulate user actions
  • Slower execution (< 2min total)

Coverage Requirements

  • Overall: 80% minimum
  • Critical paths: 95% minimum
  • New code: 90% minimum

Writing Tests

Follow these patterns:

  1. Arrange-Act-Assert
it('should calculate total correctly', () => {
  // Arrange
  const expenses = [{ amount: 10 }, { amount: 20 }]
  
  // Act
  const total = calculateTotal(expenses)
  
  // Assert
  expect(total).toBe(30)
})
  1. Descriptive Names
// Bad
it('test1', () => {})

// Good
it('should return zero for empty expense list', () => {})
  1. Test One Thing Each test should verify a single behavior.

## Deployment Preparation

### Environment Configuration

Create deployment configurations:

```javascript
// config/environments.js

const environments = {
  development: {
    API_URL: 'http://localhost:3000',
    DEBUG: true,
    STORAGE_TYPE: 'localStorage'
  },
  
  production: {
    API_URL: 'https://api.expenses.app',
    DEBUG: false,
    STORAGE_TYPE: 'indexedDB',
    SENTRY_DSN: process.env.SENTRY_DSN
  },
  
  test: {
    API_URL: 'http://mock.api',
    DEBUG: false,
    STORAGE_TYPE: 'memory'
  }
}

export default environments[process.env.NODE_ENV || 'development']

Build Configuration

Set up production builds:

// webpack.prod.js

module.exports = {
  mode: 'production',
  
  optimization: {
    minimize: true,
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10
        }
      }
    }
  },
  
  performance: {
    maxAssetSize: 250000, // 250KB
    maxEntrypointSize: 250000,
    hints: 'error'
  }
}

Deployment Checklist

Create a deployment checklist:

# Deployment Checklist

## Pre-Deployment

- [ ] All tests passing
- [ ] No console.log statements in production code
- [ ] Environment variables configured
- [ ] Security audit completed
- [ ] Performance benchmarks met
- [ ] Documentation updated
- [ ] Version number bumped

## Build

- [ ] Production build created
- [ ] Bundle size within limits
- [ ] Source maps generated
- [ ] Assets optimized
- [ ] Service worker updated

## Deployment

- [ ] Database migrations run
- [ ] Static assets deployed to CDN
- [ ] Application deployed
- [ ] Health checks passing
- [ ] Rollback plan ready

## Post-Deployment

- [ ] Smoke tests in production
- [ ] Monitor error rates
- [ ] Check performance metrics
- [ ] Verify analytics tracking
- [ ] Update status page

Creating the Comprehensive README

The Final Documentation

The README is your project’s front door:

Please create a comprehensive README.md file for the project root by:

1. Reading and synthesizing all documentation in the docs folder
2. Reviewing all .md files throughout the project
3. Creating a professional README that includes:
   - Project overview and purpose
   - Installation and setup instructions
   - Architecture overview with key components
   - Usage examples and API documentation
   - Testing instructions
   - Contributing guidelines

Ensure the README reflects the current state of the codebase and 
serves as the primary entry point for new developers.

README Structure

A complete README:

# Expense Tracker

A privacy-focused, offline-first expense tracking application that respects your data.

![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
![Coverage](https://img.shields.io/badge/coverage-85%25-yellow)
![License](https://img.shields.io/badge/license-MIT-blue)

## Features

- 📱 Works completely offline
- 🌍 Multi-currency support with live rates
- 📊 Visual spending insights
- 🔒 Your data never leaves your device
- 📤 Export to CSV for taxes
- ⚡ Lightning fast performance

## Quick Start

```bash
# Clone the repository
git clone https://github.com/username/expense-tracker.git

# Install dependencies
npm install

# Start development server
npm run dev

# Open http://localhost:3000

Installation

Requirements

  • Node.js 16+
  • npm 7+
  • Modern browser (Chrome 90+, Firefox 88+, Safari 14+)

Development Setup

  1. Clone the repository
  2. Install dependencies: npm install
  3. Copy environment file: cp .env.example .env
  4. Start development server: npm run dev

Production Build

# Create optimized build
npm run build

# Serve production build
npm run serve

Architecture

The application follows a modular architecture:

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   UI Layer  │────▶│   Services   │────▶│    Storage  │
└─────────────┘     └──────────────┘     └─────────────┘
                            │
                    ┌───────▼────────┐
                    │    Currency    │
                    │    Converter   │
                    └────────────────┘

Key Modules

  • Storage: Local-first data persistence
  • Currency: Multi-currency conversion
  • Export: Data export functionality
  • Analytics: Spending insights

Usage

Basic Expense Tracking

// Add an expense
await expenseTracker.add({
  amount: 25.50,
  category: 'food',
  description: 'Lunch',
  currency: 'USD'
})

// View monthly summary
const summary = await expenseTracker.getMonthlySummary()
console.log(summary)
// { total: 425.50, byCategory: { food: 225.50, transport: 200 } }

Multi-Currency Support

// Add expense in different currency
await expenseTracker.add({
  amount: 1000,
  category: 'food', 
  currency: 'JPY' // Japanese Yen
})

// View in preferred currency
const totalUSD = await expenseTracker.getTotal('USD')

Testing

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Run specific suite
npm run test:unit
npm run test:integration
npm run test:e2e

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Workflow

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/amazing-feature
  3. Commit changes: git commit -m 'Add amazing feature'
  4. Push to branch: git push origin feature/amazing-feature
  5. Open Pull Request

Code Style

  • ESLint configuration: .eslintrc.js
  • Prettier configuration: .prettierrc
  • Run npm run lint before committing

Deployment

Vercel

Deploy with Vercel

Netlify

Deploy to Netlify

Self-Hosting

  1. Build the application: npm run build
  2. Serve the dist folder with any static file server
  3. No backend required!

License

MIT License - see LICENSE for details

Acknowledgments

  • Built with ❤️ using Vibe Coding methodology
  • Icons by Heroicons
  • Charts by Chart.js

Support


## Deployment Strategies

### Static Hosting

For offline-first apps:

```yaml
# netlify.toml
[build]
  command = "npm run build"
  publish = "dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    X-Content-Type-Options = "nosniff"

Progressive Web App

Add PWA capabilities:

// sw.js - Service Worker
const CACHE_NAME = 'expense-tracker-v1'

const urlsToCache = [
  '/',
  '/styles/main.css',
  '/scripts/main.js',
  '/offline.html'
]

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  )
})

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  )
})

Container Deployment

For server-based apps:

# Dockerfile
FROM node:16-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Post-Deployment

Monitoring Setup

// monitoring.js
import * as Sentry from '@sentry/browser'

if (process.env.NODE_ENV === 'production') {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    integrations: [
      new Sentry.BrowserTracing(),
    ],
    tracesSampleRate: 0.1,
    environment: process.env.NODE_ENV
  })
}

// Track custom metrics
export function trackMetric(name, value) {
  if (window.analytics) {
    window.analytics.track(name, { value })
  }
}

User Analytics

Respect privacy while gathering insights:

// Privacy-focused analytics
const analytics = {
  pageView: (page) => {
    // No personal data, just page views
    fetch('/api/analytics', {
      method: 'POST',
      body: JSON.stringify({
        event: 'pageview',
        page,
        timestamp: Date.now()
      })
    })
  },
  
  event: (action, category) => {
    // Anonymous events only
    fetch('/api/analytics', {
      method: 'POST', 
      body: JSON.stringify({
        event: 'action',
        action,
        category,
        timestamp: Date.now()
      })
    })
  }
}

Maintenance Documentation

Runbook

Create operational documentation:

# Expense Tracker Runbook

## Common Issues

### Issue: Storage Quota Exceeded
**Symptoms**: App shows "Storage full" error
**Solution**: 
1. Export existing data
2. Clear old data
3. Consider IndexedDB migration

### Issue: Currency Rates Outdated
**Symptoms**: Conversions seem wrong
**Solution**:
1. Check rates.js last update
2. Update rates from reliable source
3. Deploy new version

## Deployment Process

1. Run tests: `npm test`
2. Build: `npm run build`
3. Deploy: `npm run deploy`
4. Verify: Check health endpoint
5. Monitor: Watch error rates for 30min

## Rollback Process

1. Identify issue in monitoring
2. Revert to previous version: `npm run rollback`
3. Verify functionality restored
4. Investigate issue in staging

Final Checklist

Before calling it done:

  • All tests passing
  • Documentation complete
  • README is welcoming
  • Deployment automated
  • Monitoring active
  • Backup plan ready
  • Users can get help
  • You’re proud of it

Conclusion

Deployment and documentation complete the vibe coding journey. You’ve taken an idea, built it systematically with AI assistance, and made it real. The comprehensive documentation ensures others (including future you) can understand, use, and improve what you’ve built.

Remember: Shipping is just the beginning. Real applications evolve with user needs.

🎉 Congratulations! You’ve completed the Vibe Coding Method! 🎉

Next: Part V - Advanced Techniques →