Data App Creator

SkillFiles & storage

Create self-contained HTML apps from user data (CSV, JSON, bank statements, APIs) with interactive tables and charts.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Data App Creator skill

What this skill tells your AI

The instructions your AI receives, as published by spamsch/son-of-simon in skills/data_app_creator/SKILL.md and read by ahel’s review.

Behavior Notes

When to Use This Skill

Use this skill when the user wants a persistent, visual app they can open and interact with in a browser. Examples: dashboards, data explorers, chart viewers, interactive tables.

Do NOT use this skill when the user just wants quick analysis or a one-off answer ("what's my average spending?"). For that, use Python or shell commands directly and report the result.

Rule of thumb: If the user says "create", "build", "make", "dashboard", or "app" — use this skill. If they say "analyze", "tell me", "what is" — just answer the question.

The App Creation Workflow

  1. Understand what the user wants to see — ask for clarification if the request is vague
  2. Locate data — use spotlight_search to find files, read_file to load them, or web_fetch/fetch_url for API data
  3. Analyze structure — peek at the first 5–10 rows, detect column names, types, and value ranges
  4. Choose app type — dashboard, table viewer, chart, or API-driven (see Common App Types below)
  5. Generate HTML — a single self-contained HTML file following the structure template below
  6. Save to the apps well-known directory under a descriptive subfolder: <apps-dir>/<descriptive-name>/index.html
  7. Open in Safari with open -a Safari <path>

Always use get_preferences to resolve the apps directory path — never hardcode ~/Documents/Apps.

App Directory Convention

Each app lives in its own subfolder under the apps well-known directory:

~/Documents/Apps/
  bank-statement-2024/
    index.html
  weather-dashboard/
    index.html
    data.json        (only for large datasets)
  • Kebab-case folder names — descriptive, no generic names like "dashboard"
  • Always index.html as the entry point
  • One app per folder — keeps things tidy for the user

Data Processing Patterns

CSV files — embed as a JS string constant, parse client-side with PapaParse:

<script src="https://cdn.jsdelivr.net/npm/papaparse@5/papaparse.min.js"></script>
<script>
const csvData = `...embedded CSV...`;
const parsed = Papa.parse(csvData, { header: true, dynamicTyping: true });
</script>

JSON files — embed directly as a JS object literal:

<script>
const data = [ ...embedded JSON... ];
</script>

API data — use client-side fetch() with loading states and error handling:

<script>
async function loadData() {
  showLoading();
  try {
    const res = await fetch('https://api.example.com/data');
    const data = await res.json();
    renderDashboard(data);
  } catch (err) {
    showError('Failed to load data. Check your connection and try again.');
  }
}
</script>

Large data (>500KB) — save as a separate data.json in the same folder, fetch it via a relative path:

<script>
fetch('data.json').then(r => r.json()).then(renderDashboard);
</script>

HTML Structure Template

Every generated app should follow this base skeleton:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>App Title</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
      background: #f5f5f7;
      color: #1d1d1f;
      padding: 24px;
      line-height: 1.5;
    }
    @media (prefers-color-scheme: dark) {
      body { background: #1d1d1f; color: #f5f5f7; }
      .card { background: #2c2c2e; }
    }
    h1 { font-size: 28px; font-weight: 700; margin-bottom: 24px; }
    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
      gap: 16px;
      margin-bottom: 24px;
    }
    .card {
      background: #fff;
      border-radius: 12px;
      padding: 20px;
      box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    }
    .card h2 { font-size: 14px; color: #86868b; font-weight: 500; margin-bottom: 4px; }
    .card .value { font-size: 32px; font-weight: 700; }
    table { width: 100%; border-collapse: collapse; }
    th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid #e5e5ea; }
    th { font-weight: 600; font-size: 13px; color: #86868b; text-transform: uppercase; letter-spacing: 0.5px; }
    @media (prefers-color-scheme: dark) {
      th, td { border-color: #3a3a3c; }
    }
  </style>
</head>
<body>
  <h1>App Title</h1>
  <div class="grid">
    <!-- Summary cards -->
  </div>
  <!-- Charts -->
  <!-- Detail table -->
  <script>
    // Data and rendering logic
  </script>
</body>
</html>

Layout pattern: Summary cards at top → charts in the middle → detail table at the bottom.

Recommended Libraries

Load from CDN — keeps apps self-contained with no build step:

  • Chart.js — default choice for line, bar, pie, and doughnut charts. Simple API, looks good out of the box.
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
    
  • PapaParse — CSV parsing. Always use header: true and dynamicTyping: true.
    <script src="https://cdn.jsdelivr.net/npm/papaparse@5/papaparse.min.js"></script>
    
  • Plotly.js — use only when the user needs advanced interactivity (3D charts, hover details, range sliders). Heavier than Chart.js.
    <script src="https://cdn.jsdelivr.net/npm/plotly.js@2/dist/plotly.min.js"></script>
    
  • Vanilla JS tables — for simple data with <100 rows, skip libraries entirely. Add sort/filter with plain JS event handlers.

Common App Types

Financial dashboard (bank statements, expense exports):

  • Auto-detect date, amount, and description/category columns
  • Summary cards: total income, total expenses, net, transaction count
  • Chart: spending over time (grouped by month or week)
  • Chart: spending by category (pie or bar)
  • Table: all transactions, sortable by date/amount
  • Format amounts with currency symbols and 2 decimal places

Generic CSV explorer (any tabular data):

  • Sortable, filterable table with all columns
  • Column statistics at top: count, min, max, mean for numeric columns
  • Search/filter input above the table
  • Handle missing values gracefully — show "—" not "null"

API dashboard (weather, stocks, public APIs):

  • Loading spinner while fetching
  • Auto-refresh with configurable interval (default: 5 minutes)
  • Error state with retry button
  • Last-updated timestamp in the header
  • Use fetch() with timeout handling

Health data viewer (Apple Health exports, fitness data):

  • Time-series line charts with date range controls
  • Summary stats per period (daily, weekly, monthly)
  • Multiple metrics on the same chart where it makes sense

Styling Defaults

  • Font: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif
  • Spacing: multiples of 8px (8, 16, 24, 32)
  • Colors: light background #f5f5f7, white cards #fff, dark text #1d1d1f, muted labels #86868b
  • Dark mode: always include @media (prefers-color-scheme: dark) with inverted backgrounds and lighter text
  • Responsive: use grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)) for card layouts
  • Border radius: 12px for cards, 8px for inputs/buttons
  • Shadows: subtle box-shadow: 0 1px 3px rgba(0,0,0,0.08) on cards

Smart Data Detection

Use these heuristics to pick the right visualization automatically:

  • Date column + number column → line chart (time series)
  • Category column + number column → bar chart or pie chart
  • Financial keywords in filename or headers (amount, balance, debit, credit, transaction) → financial dashboard layout
  • All text columns → searchable/sortable table, no charts
  • Lat/lng columns → mention map possibility but stick to table (maps need Leaflet, which adds complexity)
  • Multiple numeric columns → summary stats cards + comparison bar chart

Security & Privacy

  • Confirm before embedding account numbers, SSNs, or other PII in the HTML file
  • Redact sensitive fields to last-4 digits when displaying (e.g., ****1234)
  • Warn the user that HTML files store data in plain text — anyone with file access can read them
  • Never embed API keys in client-side code — use public/free-tier APIs or prompt the user to enter keys at runtime
  • Sanitize data before injecting into HTML to prevent XSS (escape <, >, &, ", ' in user data strings)

Signals

GitHub stars
28
Forks
1
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
data-app-creator
Source
github.com/spamsch/son-of-simon