Skip to content

matthen/leafstone

Repository files navigation

leafstone

leafstone icon

Test Lint npm version

A CLI tool for easily running single file React components. Allows you to run and build React artifacts output by Claude and ChatGPT.

Installation

Install globally via npm:

npm install -g leafstone

AI-assisted Coding

Leafstone is perfect for testing React components generated by AI tools, such as Claude Artifacts or ChatGPT Canvas code. Here's how to prompt Claude, ChatGPT, or other assistants to create components that work seamlessly with leafstone:

Create a single-file React component in a .jsx file that:

- Uses NO PROPS (component renders in isolation)
- Has a default export
- Includes Tailwind CSS classes for styling
- Can use Lucide React icons (import { IconName } from 'lucide-react')

Optional advanced features:
- Add "// @requires package@version" comments to auto-install npm packages
- Add "// @requires-asset ./path/to/filename" comments to include static assets
- Reference assets via "./assets/filename" in your JSX

Save as ComponentName.jsx and run: `leafstone ComponentName.jsx`

Usage

Basic Usage

# Start dev server for a specific component file
leafstone examples/Counter.jsx

# Start dev server with custom port
leafstone examples/Counter.jsx 3001

# Build component for static deployment
leafstone --build ./dist examples/Counter.jsx
leafstone -b ./output examples/Chart.jsx

Quick Start

  1. Create a JSX component

    // Counter.jsx
    import { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0);
      
      return (
        <div>
          <h1>Count: {count}</h1>
          <button onClick={() => setCount(count + 1)}>
            Increment
          </button>
        </div>
      );
    }
    
    export default Counter;
  2. Start the development server

    leafstone Counter.jsx
  3. Open your browser

    • Server opens automatically at http://localhost:3000
    • Your component renders immediately
    • Changes hot-reload automatically

Features

  • Zero Configuration - Just point at a JSX file
  • Instant Development - Component renders immediately in the browser
  • Hot Module Replacement (HMR) - Changes are reflected instantly
  • Dynamic Dependencies - Auto-install npm packages with JSDoc comments
  • Tailwind CSS Support - Built-in Tailwind with Dracula theme
  • Lucide React Icons - Icon library available for all components
  • React DevTools Compatible - Full React development experience

Component Requirements

Components should:

  • Be in .jsx files
  • Export the component as default export
  • Not require any props (they render in isolation)
  • Use standard React patterns (hooks, state, etc.)

Available Libraries

  • React - Hooks, state, context, etc.
  • Tailwind CSS - Utility-first CSS framework with Dracula theme
  • Lucide React - Beautiful icon library (import { Icon } from 'lucide-react')

Custom Dependencies

Need to use external packages like charts, utilities, or other React libraries? Just add a JSDoc-style comment at the top of your component:

// @requires recharts@^2.8.0
// @requires lodash@^4.17.0
// @requires date-fns@^2.0.0
import { LineChart, Line, XAxis, YAxis } from 'recharts';
import _ from 'lodash';
import { format } from 'date-fns';

function MyChart() {
  const data = _.range(10).map(i => ({ x: i, y: Math.random() * 100 }));
  
  return (
    <div>
      <h2>{format(new Date(), 'PPP')}</h2>
      <LineChart width={400} height={200} data={data}>
        <Line dataKey="y" />
        <XAxis dataKey="x" />
        <YAxis />
      </LineChart>
    </div>
  );
}

How it works:

  • Add // @requires package@version comments at the top of your file
  • Leafstone automatically detects and installs these dependencies
  • Use any npm package in your components without manual installation
  • Supports version constraints (package@^2.0.0) or latest (package)

Examples:

  • // @requires recharts@^2.8.0 - Install specific version
  • // @requires lodash - Install latest version
  • // @requires d3@^7.0.0 - Popular data visualization library
  • // @requires framer-motion@^10.0.0 - Animation library

Assets and Media Files

Need to use images, SVGs, or other static assets in your components? Use the @requires-asset syntax to include them:

// @requires-asset ./logo.svg
// @requires-asset ./chart-data.json
// @requires-asset ../shared/icon.svg shared-icon.svg
import { useState } from 'react';
import { BarChart } from 'lucide-react';
import data from './assets/chart-data.json';

function MyComponent() {
  const [selectedItem, setSelectedItem] = useState(data[0]);
  
  return (
    <div>
      <img src="./assets/logo.svg" alt="Logo" />
      <div className="p-4">
        <BarChart className="text-blue-500" />
        <h3>{selectedItem.title}</h3>
        <p>Value: {selectedItem.value}</p>
        <img src="./assets/shared-icon.svg" alt="Icon" />
      </div>
    </div>
  );
}

export default MyComponent;

How it works:

  • Add // @requires-asset ./path/to/file [destination] comments at the top of your file
  • Leafstone automatically copies these assets to the ./assets/ directory
  • Optional destination filename prevents conflicts when multiple assets have the same name
  • Reference assets in your JSX using ./assets/filename.ext URLs
  • Supports images (PNG, JPG, SVG), fonts, and any static files
  • Assets are available both in development and static builds
  • Automatic conflict detection - exits with error if multiple assets would have the same destination filename

Examples:

  • // @requires-asset ./logo.svg - SVG logo file (uses original filename)
  • // @requires-asset ../images/hero.png - PNG image from parent directory
  • // @requires-asset ./fonts/custom.woff2 - Custom font file
  • // @requires-asset ./data/config.json app-config.json - JSON data with custom name
  • // @requires-asset ./shared/config.json shared-config.json - Avoid filename conflicts

Static Builds

Ready to share your component? Build it into static files that can be deployed anywhere:

# Build to a directory
leafstone --build ./dist examples/Chart.jsx

This generates optimized static files in your output directory:

dist/
├── index.html                    # Production-ready HTML
└── assets/
    ├── index-[hash].js          # React runtime (188KB → 59KB gzipped)
    ├── index-[hash].css         # Compiled Tailwind CSS
    └── [ComponentName]-[hash].js # Your component + dependencies

Features:

  • Production optimized - Minified and tree-shaken bundles
  • All dependencies included - Works with any @requires packages
  • Ready to deploy - Upload to Netlify, Vercel, GitHub Pages, etc.
  • Fast builds - Leverages Vite's optimized bundling

Development

Prerequisites

  • Node.js (v14 or higher)
  • npm

Local Development

  1. Clone and install

    git clone <repository>
    cd leafstone
    npm install
  2. Run tests

    # Run all tests once
    npm test
    
    # Run tests in watch mode (re-runs on file changes)
    npm run test:watch
    
    # Run tests with coverage report
    npm run test:coverage
  3. Lint and format code

    # Check code quality, style, and formatting
    npm run lint
    
    # Auto-fix issues and format code
    npm run lint:fix
  4. Link for local testing

    npm link
    leafstone examples/Counter.jsx

    What is npm link? This creates a global symlink to your local development version of the package. It's like temporarily installing your in-development package globally so you can test the leafstone command before publishing to npm. Think of it as "install this local package globally for testing".

  5. Test the CLI locally

    # Test with the included example component
    leafstone examples/Counter.jsx
    
    # Test with your own component file
    # ... create a JSX file
    leafstone MyComponent.jsx

How It Works

  1. CLI Command - bin/leafstone.js processes the JSX file argument and starts server
  2. Temporary Setup - Creates .leafstone-temp-{unique}/ directory with Vite project files
  3. Component Aliasing - Sets up Vite alias to import your specific component
  4. Direct Rendering - React app imports and renders your component immediately
  5. Hot Reloading - Vite watches your component file for changes

Publishing

To publish to npm:

npm version patch  # or minor/major
npm publish

Troubleshooting

Component not showing up?

  • Make sure your JSX file has a default export
  • Check the browser console for import errors
  • Verify the file path is correct

Dependency installation failing?

  • Check your internet connection
  • Verify the package name and version exist on npm
  • Look at the console output for specific npm error messages

Hot reloading not working?

  • The server automatically watches your component file
  • Try refreshing if changes aren't reflected immediately

Port already in use?

  • Specify a different port: leafstone MyComponent.jsx 3001
  • Check what's running on port 3000: lsof -i :3000

About

Easily run single file React components

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors