Build Web Apps with
JavaScript & Python
in One File

PureMix is an HTML-first full-stack framework that lets you mix JavaScript, TypeScript, and Python in the same file. Native Python integration, server-side rendering, simple development.

npx puremix create my-app
cd my-app && npm run dev
app/routes/index.puremix
<loader>
  async function loadDashboard(request, actionResult) {
    // Use analysis result from action if available
    if (actionResult && actionResult.success) {
      return {
        data: {
          sales: actionResult.predictions,
          confidence: actionResult.confidence_score,
          timeframe: actionResult.timeframe,
          sampleSize: actionResult.sample_size
        }
      };
    }

    // Default initial load
    return {
      data: {
        timeframe: request.query.timeframe || 'month',
        pendingAnalysis: true
      }
    };
  }
</loader>

<div class="dashboard">
  <h1>Sales Analysis Dashboard</h1>
  
  {loadDashboard.data.pendingAnalysis ?
    <div>
      <p>Click the button below to run Python ML analysis:</p>
      <form onsubmit="analyzeSales">
        <button type="submit" class="btn-primary">
          🐍 Run Python Analysis
        </button>
      </form>
    </div>
  :
    <div>
      <h2>Results for {loadDashboard.data.timeframe}</h2>
      <p><strong>Sales Forecast:</strong> {loadDashboard.data.sales}</p>
      <p><strong>Confidence:</strong> {loadDashboard.data.confidence}%</p>
      <p><small>Based on {loadDashboard.data.sampleSize} months of data</small></p>
      
      <button onclick="analyzeSales" class="btn-secondary">
        🔄 Run Again
      </button>
    </div>
  }
</div>

<script server lang="python">
def analyzeSales(formData, request):
    """Run ML analysis on sales data"""
    import pandas as pd
    import numpy as np
    
    # Sample data for demo
    sample_sales = [
        {'date': '2024-01', 'sales': 1200},
        {'date': '2024-02', 'sales': 1500},
        {'date': '2024-03', 'sales': 1350},
        {'date': '2024-04', 'sales': 1800},
        {'date': '2024-05', 'sales': 2100},
        {'date': '2024-06', 'sales': 1950}
    ]
    
    df = pd.DataFrame(sample_sales)
    predictions = float(df['sales'].mean())
    std_dev = float(df['sales'].std())
    confidence = round(95 - (std_dev / predictions * 100), 2)
    
    return {
        'success': True,
        'predictions': predictions,
        'confidence_score': confidence,
        'timeframe': formData.get('timeframe') or 'month',
        'sample_size': len(sample_sales)
    }
</script>

Why PureMix?

🐍 Python Integration

Mix Python and JavaScript seamlessly. Call NumPy, Pandas, and ML libraries directly from your web app.

Simple Development

Node.js 22+ runs TypeScript natively. No webpack, no bundlers, no complex configuration.

HTML-First

Write familiar HTML with server-side logic. No JSX compilation, no virtual DOM, just pure web development.

🧩 Component System

React-style components with props and selective updates. Smart DOM diffing for zero-flicker UI.

🚀 Server-Side Rendering

Fast initial page loads with complete SSR. Loader/action pattern for data fetching and mutations.

🔥 Hot Reload

Instant feedback during development. File watching with automatic server restart and browser refresh.

Native Python Integration

PureMix is a framework that lets you use Python using familiar ES6 import syntax. Multiple ways to use Python, from inline execution to ES6 imports.

1

Script Tag Functions

Embed Python functions directly in .puremix files

<script server lang="python">
  def calculate_roi(data, js_context=None):
    import numpy as np

    investment = np.array([d['cost'] for d in data])
    revenue = np.array([d['revenue'] for d in data])
    roi = ((revenue - investment) / investment) * 100

    return {
      'success': True,
      'roi': float(roi.mean()),
      'breakdown': roi.tolist()
    }
</script>

<form onsubmit="calculate_roi">
  <button type="submit">Calculate ROI</button>
</form>
2

Inline Execution

Execute Python code dynamically within loaders

const result = await request.python.call('analyze', data, `
  import pandas as pd

  def analyze(data, js_context=None):
    df = pd.DataFrame(data)
    stats = df.describe()
    return {
      'success': True,
      'statistics': stats.to_dict()
    }
`);
3

ES6 Import Syntax 🎉

Native

Import Python functions like JavaScript modules!

// Import Python functions using standard ES6 syntax!
import { validate_data, analyze_portfolio } from '../lib/data_processor'
import { calculate_loan } from '../services/financial_analyzer'

async function loadPage(request) {
  // Call Python functions using familiar ES6 import syntax!
  const validation = await validate_data({ userId: 123 });
  const analysis = await analyze_portfolio(portfolioData);
  const loan = await calculate_loan({ principal: 300000 });

  return { data: { validation, analysis, loan } };
}
4

Global Functions (Auto-Discovery)

Zero imports needed - Python functions available everywhere

// No imports required! All Python modules auto-discovered
async function loadPage(request) {
  // Call any Python function globally
  const result = await validate_data({ userId: 123 });
  const processed = await process_data(result);
  const formatted = await format_text({ text: 'hello' });

  return { data: { result, processed, formatted } };
}

Why Python Integration Matters

📊

Data Science

Use Pandas, NumPy, Matplotlib directly in your web apps

🤖

Machine Learning

Integrate Scikit-learn, TensorFlow, PyTorch models

🔬

Scientific Computing

Leverage SciPy, SymPy for complex calculations

📈

Financial Analysis

Build trading platforms, risk models, portfolio analyzers

Loader/Action Flow

Understanding PureMix's data fetching and mutation pattern (inspired by Remix)

⚠️ Important: Action results are passed to the loader. When a form submits and calls an action (<script server>), the action's return value becomes available as actionResult in the loader function. The loader then runs again with this data.
1

HTTP Request

User visits /products/123 or submits a form

GET /products/123
POST /products/123
2

Route Resolution

File-based routing matches URL to .puremix file

app/routes/products/[id].puremix
3

Action Execution (POST only)

Server function processes form data or API mutations

<script server>
  async function updateProduct(formData, request) {
    const product = await saveProduct({
      id: request.params.id,
      name: formData.get('name'),
      price: formData.get('price')
    });

    return {
      success: true,
      product,
      message: 'Product updated!'
    };
  }
</script>
4

Loader Execution

Fetch data for rendering (receives action result if POST)

<loader>
  async function loadProduct(request, actionResult) {
    const productId = request.params.id;
    const product = await getProduct(productId);

    return {
      data: {
        product,
        // Include action result for feedback
        updateSuccess: actionResult?.success,
        message: actionResult?.message
      }
    };
  }
</loader>
5

Template Rendering

Server-side rendering with loader data

<div>
  {loadProduct.data.updateSuccess ?
    <div class="success">{loadProduct.data.message}</div> :
    null
  }

  <h1>{loadProduct.data.product.name}</h1>
  <p>Price: ${loadProduct.data.product.price}</p>

  <form onsubmit="updateProduct">
    <input name="name" value="{loadProduct.data.product.name}">
    <input name="price" value="{loadProduct.data.product.price}">
    <button type="submit">Update</button>
  </form>
</div>
6

HTML Response

Complete rendered page sent to browser

HTTP/1.1 200 OK
Content-Type: text/html

<!DOCTYPE html>
<html>...</html>

Key Benefits of This Pattern

Progressive Enhancement

Works without JavaScript, enhanced with JavaScript

Type-Safe

TypeScript support for request, formData, and responses

SEO-Friendly

Complete HTML rendered server-side

Fast Initial Load

No client-side data fetching waterfall

Get Started in 3 Minutes

Step 1

Install PureMix

npx puremix create my-app

Requires Node.js 22+ for native TypeScript support

Step 2

Create Your App

puremix create my-app

# Choose template:
# - basic: Tailwind CSS with animations
# - minimal: Zero dependencies
# - advanced: MongoDB + authentication
Step 3

Start Development

cd my-app
npm run dev

# Server starts at http://localhost:3000
# Hot reload enabled - changes reflect instantly!