Skip to content

Building Your First App

Complete step-by-step tutorial for creating a PACE-powered product storefront.


What We're Building

A conversational storefront for MCP (Model Context Protocol) servers with:

  • ✅ Product catalog with search and categories
  • ✅ AI-powered chat guide
  • ✅ About page with origin story
  • ✅ Executive summary tracking
  • ✅ Purple gradient theme
  • ✅ Fully functional routing

Time: 30-45 minutes


Prerequisites

  • Node.js 18+
  • NPM or Yarn
  • Code editor (VS Code recommended)
  • Basic JavaScript/HTML knowledge

Part 1: Project Setup

1. Create Project Directory

bash
mkdir mcp-storefront
cd mcp-storefront
npm init -y

2. Install PACE.js

bash
npm install @semanticintent/pace-pattern

3. Create Project Structure

bash
mkdir public
touch public/index.html
touch public/app.js
touch public/products.json
touch public/about.json

Your structure:

mcp-storefront/
├── package.json
├── public/
│   ├── index.html
│   ├── app.js
│   ├── products.json
│   └── about.json

Part 2: Create Product Data

public/products.json

Create realistic MCP server products:

json
{
  "products": [
    {
      "id": "sql-mcp",
      "name": "SQL MCP",
      "tagline": "Query databases with natural language",
      "category": "Database Tools",
      "description": "## SQL MCP\n\nConnect Claude to your databases and query them using natural language.\n\n### Features\n- PostgreSQL, MySQL, SQLite support\n- Natural language → SQL translation\n- Query result formatting\n- Safe read-only mode\n\n### Installation\n```bash\nnpm install -g sql-mcp\n```\n\n### Usage\nAdd to your Claude Desktop config:\n```json\n{\n  \"mcpServers\": {\n    \"sql\": {\n      \"command\": \"sql-mcp\",\n      \"args\": [\"--db\", \"postgresql://localhost/mydb\"]\n    }\n  }\n}\n```",
      "action_label": "Install",
      "action_url": "https://github.com/example/sql-mcp"
    },
    {
      "id": "github-mcp",
      "name": "GitHub MCP",
      "tagline": "Interact with GitHub repositories",
      "category": "Developer Tools",
      "description": "## GitHub MCP\n\nManage GitHub repositories, issues, and PRs through Claude.\n\n### Features\n- Repository browsing\n- Issue management\n- PR creation and review\n- Code search\n\n### Installation\n```bash\nnpm install -g github-mcp\n```\n\n### Authentication\nRequires GitHub personal access token.",
      "action_label": "Get Started",
      "action_url": "https://github.com/example/github-mcp"
    },
    {
      "id": "filesystem-mcp",
      "name": "Filesystem MCP",
      "tagline": "Safe file operations through Claude",
      "category": "System Tools",
      "description": "## Filesystem MCP\n\nLet Claude read and write files securely.\n\n### Features\n- Read/write files\n- Directory listing\n- File search\n- Safe mode (read-only)\n\n### Security\n- Configurable allowed paths\n- Deny dangerous operations\n- Audit logging",
      "action_label": "Learn More",
      "action_url": "https://github.com/example/filesystem-mcp"
    },
    {
      "id": "api-mcp",
      "name": "API MCP",
      "tagline": "Connect to REST APIs",
      "category": "Integration",
      "description": "## API MCP\n\nCall external APIs through Claude.\n\n### Features\n- REST API calls\n- OAuth support\n- Response parsing\n- Rate limiting\n\n### Use Cases\n- Weather data\n- Stock prices\n- News feeds\n- Custom APIs",
      "action_label": "Explore",
      "action_url": "https://github.com/example/api-mcp"
    },
    {
      "id": "analytics-mcp",
      "name": "Analytics MCP",
      "tagline": "Query analytics platforms",
      "category": "Data & Analytics",
      "description": "## Analytics MCP\n\nConnect to Google Analytics, Mixpanel, etc.\n\n### Supported Platforms\n- Google Analytics 4\n- Mixpanel\n- Amplitude\n- Custom sources\n\n### Example Queries\n- \"Show me last week's traffic\"\n- \"What's our conversion rate?\"\n- \"Top pages by views\"",
      "action_label": "Connect",
      "action_url": "https://github.com/example/analytics-mcp"
    }
  ]
}

Part 3: Create About Content

public/about.json

json
{
  "title": "About MCP Hub",
  "sections": [
    {
      "title": "What is MCP Hub?",
      "content": "## What is MCP Hub?\n\nMCP Hub is a conversational storefront for discovering Model Context Protocol (MCP) servers.\n\n### What are MCP Servers?\n\nMCP servers are plugins that extend Claude's capabilities by connecting it to external tools, databases, APIs, and services.\n\n### Why This Exists\n\nFinding the right MCP server shouldn't require browsing dozens of repositories. Let our guide help you discover what you need through conversation."
    },
    {
      "title": "The PACE Pattern",
      "content": "## Built with PACE\n\nThis site implements the **PACE Pattern** — Pattern for Agentic Conversational Experience.\n\n### Four Principles:\n\n- **Proactive** — Guide initiates conversation\n- **Adaptive** — Matches your expertise level\n- **Contextual** — Remembers what you've discussed\n- **Efficient** — Concise, actionable responses\n\n[Learn more about PACE →](https://pace.cormorantforaging.dev)"
    },
    {
      "title": "Open Source",
      "content": "## Open Source\n\nMCP Hub is built with PACE.js, an open-source framework.\n\n- **Framework:** [PACE.js](https://github.com/semanticintent/pace.js)\n- **Pattern:** [PACE Pattern](https://zenodo.org/records/18049371)\n- **License:** MIT\n\nContributions welcome!"
    }
  ],
  "links": [
    {
      "label": "PACE.js on GitHub",
      "url": "https://github.com/semanticintent/pace.js"
    },
    {
      "label": "MCP Protocol Docs",
      "url": "https://modelcontextprotocol.io"
    }
  ]
}

Part 4: Create HTML

public/index.html

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>MCP Hub - Find Your Perfect MCP Server</title>

  <!-- PACE.js CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@semanticintent/pace-pattern/dist/pace.min.css">

  <!-- Custom overrides -->
  <style>
    body {
      margin: 0;
      font-family: Inter, system-ui, sans-serif;
    }

    /* Optional: Override PACE colors */
    :root {
      --pace-primary: #667eea;
      --pace-accent: #764ba2;
    }
  </style>
</head>
<body>
  <div id="app"></div>

  <script type="module" src="app.js"></script>
</body>
</html>

Part 5: Initialize PACE.js

public/app.js (Basic Version)

Start without AI:

javascript
import { PACE } from '@semanticintent/pace-pattern'

// Initialize PACE
const pace = new PACE({
  container: '#app',
  products: './products.json',
  greeting: 'Welcome to MCP Hub! What kind of MCP server are you looking for?',
  defaultView: 'product'
})

// Mount to DOM
pace.mount()

// Listen to events
pace.on('ready', () => {
  console.log('MCP Hub is ready!')
})

pace.on('product:select', ({ product }) => {
  console.log('User selected:', product.name)
})

pace.on('product:search', ({ query, results }) => {
  console.log(`Search for "${query}" found ${results.length} results`)
})

Part 6: Test Basic Functionality

Start Development Server

bash
npx serve public

Open http://localhost:3000

Test These Features

✅ Product catalog displays all 5 MCP servers ✅ Search works (try "database" or "github") ✅ Products grouped by category ✅ Sidebar navigation works ✅ URLs update with hash routing ✅ About page shows custom content


Part 7: Add AI (Claude)

Update app.js with Claude

javascript
import { PACE, ClaudeAdapter } from '@semanticintent/pace-pattern'

// Create Claude adapter
const claudeAdapter = new ClaudeAdapter({
  apiKey: process.env.CLAUDE_API_KEY, // Use environment variable
  model: 'claude-3-sonnet-20240229'
})

// Initialize PACE with AI
const pace = new PACE({
  container: '#app',
  products: './products.json',
  aiAdapter: claudeAdapter,
  greeting: 'Welcome to MCP Hub! What are you fishing for?',

  // Pass product context to AI
  context: {
    storeName: 'MCP Hub',
    storeDescription: 'A curated collection of MCP servers for Claude',
    totalProducts: 5
  }
})

pace.mount()

// Track chat interactions
pace.on('chat:message', ({ message }) => {
  console.log('User:', message)
})

pace.on('chat:response', ({ message, metadata }) => {
  console.log('Guide:', message)
  console.log('Detected expertise:', metadata.expertise)
})

Set Environment Variable

bash
export CLAUDE_API_KEY='your-api-key-here'

Test AI Features

✅ Chat with the guide ✅ Ask "What's the best database tool?" ✅ Ask "I'm new to MCP, where should I start?" ✅ Notice adaptive responses (beginner vs advanced) ✅ Executive summary tracks conversation


Part 8: Customize Theme

Add Custom Styling

Create public/custom.css:

css
/* Override PACE.js theme */
:root {
  --pace-primary: #2563eb;  /* Blue instead of purple */
  --pace-accent: #3b82f6;
  --pace-font: 'Roboto', system-ui, sans-serif;
}

/* Custom product cards */
.pace-product-card {
  border-left: 4px solid var(--pace-primary);
  transition: transform 0.2s;
}

.pace-product-card:hover {
  transform: scale(1.02);
  box-shadow: 0 8px 24px rgba(37, 99, 235, 0.15);
}

/* Custom chat messages */
.pace-chat-message.assistant {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
}

/* Custom navigation */
.pace-nav-item.active {
  border-left: 4px solid var(--pace-primary);
}

Link in HTML:

html
<link rel="stylesheet" href="custom.css">

Part 9: Add Analytics

Track User Behavior

javascript
// Analytics plugin
const analyticsPlugin = {
  name: 'analytics',

  install(pace) {
    // Track product views
    pace.on('product:select', ({ product }) => {
      gtag('event', 'product_view', {
        product_id: product.id,
        product_name: product.name,
        product_category: product.category
      })
    })

    // Track searches
    pace.on('product:search', ({ query, results }) => {
      gtag('event', 'search', {
        search_term: query,
        results_count: results.length
      })
    })

    // Track chat engagement
    pace.on('chat:message', ({ message }) => {
      gtag('event', 'chat_message', {
        message_length: message.length
      })
    })
  }
}

// Use plugin
pace.use(analyticsPlugin).mount()

Part 10: Deploy

Build for Production

  1. Bundle with Vite
bash
npm install -D vite

Update package.json:

json
{
  "scripts": {
    "dev": "vite public",
    "build": "vite build public",
    "preview": "vite preview"
  }
}
  1. Build
bash
npm run build
  1. Deploy to Netlify
bash
netlify deploy --prod

Or GitHub Pages, Vercel, Cloudflare Pages — all work great with PACE.js!


Complete Code

Final app.js

javascript
import { PACE, ClaudeAdapter } from '@semanticintent/pace-pattern'

const pace = new PACE({
  container: '#app',
  products: './products.json',

  aiAdapter: new ClaudeAdapter({
    apiKey: process.env.CLAUDE_API_KEY,
    model: 'claude-3-sonnet-20240229'
  }),

  greeting: 'Welcome to MCP Hub! What are you fishing for?',
  defaultView: 'product',

  theme: {
    primary: '#667eea',
    accent: '#764ba2'
  },

  context: {
    storeName: 'MCP Hub',
    productCount: 5
  }
})

// Analytics plugin
pace.use({
  name: 'analytics',
  install(p) {
    p.on('product:select', ({ product }) => {
      console.log('Product viewed:', product.name)
    })
  }
})

pace.mount()

// Debug events
if (import.meta.env.DEV) {
  pace.on('*', (event, payload) => {
    console.log('[PACE]', event, payload)
  })
}

What You Built

🎉 Congratulations! You've built a fully functional PACE-powered storefront with:

  • ✅ 5 MCP server products with rich descriptions
  • ✅ AI-powered conversational guide
  • ✅ Search and category filtering
  • ✅ Custom About page
  • ✅ Executive summary tracking
  • ✅ Analytics integration
  • ✅ Custom theming
  • ✅ Production-ready deployment

Next Steps

Continue Learning


You've built your first PACE app! 🚀