# react-exe **Repository Path**: monksoul/react-exe ## Basic Information - **Project Name**: react-exe - **Description**: A powerful React component executor that renders code with external dependencies and custom styling - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: main - **Homepage**: https://react-exe-demo.vercel.app - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-01 - **Last Updated**: 2025-04-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React-EXE Execute React components on the fly with external dependencies, custom styling, and TypeScript support. Perfect for creating live code previews, documentation, or interactive code playgrounds. Screenshot 2025-02-26 at 00 23 34 Try the live demo [here](https://react-exe-demo.vercel.app/). ## Features - 🚀 Execute React components from string code - 📦 Support for external dependencies - 🎨 Tailwind CSS support - 🔒 Built-in security checks - 💅 Customizable styling - 📝 TypeScript support - ⚡ Live rendering - 🐛 Error boundary protection - 📄 Multi-file support ## Installation ```bash npm install react-exe # or yarn add react-exe # or pnpm add react-exe ``` ## Basic Usage ```tsx import { CodeExecutor } from "react-exe"; const code = ` export default function HelloWorld() { return (

Hello World!

); } `; function App() { return ; } ``` ## Advanced Usage ### With External Dependencies ```tsx import { CodeExecutor } from "react-exe"; import * as echarts from "echarts"; import * as framerMotion from "framer-motion"; const code = ` import { motion } from 'framer-motion'; import { LineChart } from 'echarts'; export default function Dashboard() { return ( ); } `; function App() { return ( ); } ``` ### With absolute imports and wildcard patterns ```tsx import { CodeExecutor } from "react-exe"; import * as echarts from "echarts"; import * as framerMotion from "framer-motion"; import * as uiComponents from "../ShadcnComps"; const code = ` import { motion } from 'framer-motion'; import { LineChart } from 'echarts'; import { Button } from "@/components/ui/button" export default function Dashboard() { return ( ); } `; function App() { return ( ); } ``` ### With Multiple Files React-EXE supports multiple files with cross-imports, allowing you to build more complex components and applications: ```tsx import { CodeExecutor } from "react-exe"; import * as framerMotion from "framer-motion"; // Define multiple files as an array of code files const files = [ { name: "App.tsx", // Main entry file content: ` import React from 'react'; import { motion } from 'framer-motion'; import Header from './Header'; import Counter from './Counter'; const App = () => { return (
); }; export default App; `, isEntry: true, // Mark this as the entry point }, { name: "Header.tsx", content: ` import React from 'react'; interface HeaderProps { title: string; } const Header = ({ title }: HeaderProps) => { return (

{title}

); }; export default Header; `, }, { name: "Counter.tsx", content: ` import React, { useState } from 'react'; import { motion } from 'framer-motion'; import CounterButton from './CounterButton'; const Counter = () => { const [count, setCount] = useState(0); const increment = () => setCount(prev => prev + 1); const decrement = () => setCount(prev => prev - 1); return (

Counter Component

{count}
); }; export default Counter; `, }, { name: "CounterButton.tsx", content: ` import React from 'react'; import { motion } from 'framer-motion'; interface CounterButtonProps { onClick: () => void; label: string; variant?: 'primary' | 'success' | 'danger'; } const CounterButton = ({ onClick, label, variant = 'primary' }: CounterButtonProps) => { const getButtonColor = () => { switch(variant) { case 'success': return 'bg-green-500 hover:bg-green-600'; case 'danger': return 'bg-red-500 hover:bg-red-600'; default: return 'bg-blue-500 hover:bg-blue-600'; } }; return ( {label} ); }; export default CounterButton; `, }, ]; function App() { return ( ); } ``` ### Creating a Project Structure with Multiple Files For more complex applications, you can organize your files in a project-like structure: ```tsx import { CodeExecutor } from "react-exe"; import * as reactRouter from "react-router-dom"; import * as framerMotion from "framer-motion"; const files = [ { name: "App.tsx", content: ` import React from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Layout from './components/Layout'; import Home from './pages/Home'; import About from './pages/About'; import NotFound from './pages/NotFound'; const App = () => { return ( }> } /> } /> } /> ); }; export default App; `, isEntry: true, }, { name: "components/Layout.tsx", content: ` import React from 'react'; import { Outlet } from 'react-router-dom'; import Navbar from './Navbar'; import Footer from './Footer'; const Layout = () => { return (
); }; export default Layout; `, }, { name: "components/Navbar.tsx", content: ` import React from 'react'; import { Link, useLocation } from 'react-router-dom'; const Navbar = () => { const location = useLocation(); const isActive = (path: string) => { return location.pathname === path ? 'text-white bg-indigo-700' : 'text-indigo-200 hover:text-white hover:bg-indigo-600'; }; return ( ); }; export default Navbar; `, }, { name: "components/Footer.tsx", content: ` import React from 'react'; const Footer = () => { return (

© {new Date().getFullYear()} React-EXE Demo

Built with multiple files

); }; export default Footer; `, }, { name: "pages/Home.tsx", content: ` import React from 'react'; import { motion } from 'framer-motion'; const Home = () => { return (

Welcome to the Home Page

This is a multi-file application example using React-EXE.

It demonstrates how you can create complex applications with multiple components, pages, and even routing!

Features Demonstrated:

  • Multiple file structure
  • React Router integration
  • Animation with Framer Motion
  • Component composition
  • Styling with Tailwind CSS
); }; export default Home; `, }, { name: "pages/About.tsx", content: ` import React from 'react'; import { motion } from 'framer-motion'; const About = () => { return (

About Page

React-EXE is a powerful library for executing React components on the fly. It supports multi-file applications like this one!

{[1, 2, 3].map((item) => (

Feature {item}

This is an example of a card that demonstrates Framer Motion animations in a multi-file React component.

))}
); }; export default About; `, }, { name: "pages/NotFound.tsx", content: ` import React from 'react'; import { Link } from 'react-router-dom'; import { motion } from 'framer-motion'; const NotFound = () => { return (

404

Page Not Found

The page you're looking for doesn't exist or has been moved.

Return Home
); }; export default NotFound; `, }, ]; function App() { return ( ); } ``` ### Using Custom Hooks and Utilities in Multi-File Apps You can also create and use custom hooks, utilities, and TypeScript types across multiple files: ```tsx import { CodeExecutor } from "react-exe"; const files = [ { name: "App.tsx", content: ` import React from 'react'; import ThemeProvider from './theme/ThemeProvider'; import ThemeSwitcher from './components/ThemeSwitcher'; import UserProfile from './components/UserProfile'; import { fetchUserData } from './utils/api'; const App = () => { return (
); }; export default App; `, isEntry: true, }, { name: "types/index.ts", content: ` export interface User { id: string; name: string; email: string; avatar: string; } export type Theme = 'light' | 'dark' | 'system'; export interface ThemeContextType { theme: Theme; setTheme: (theme: Theme) => void; } `, }, { name: "theme/ThemeProvider.tsx", content: ` import React, { createContext, useContext, useState, useEffect } from 'react'; import { Theme, ThemeContextType } from '../types'; const ThemeContext = createContext(undefined); const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [theme, setTheme] = useState('system'); useEffect(() => { const applyTheme = (newTheme: Theme) => { const root = window.document.documentElement; // Remove any existing theme classes root.classList.remove('light', 'dark'); // Apply the appropriate theme if (newTheme === 'system') { const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; root.classList.add(systemTheme); } else { root.classList.add(newTheme); } }; applyTheme(theme); // Listen for system theme changes const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = () => { if (theme === 'system') { applyTheme('system'); } }; mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); }, [theme]); return ( {children} ); }; export const useTheme = () => { const context = useContext(ThemeContext); if (context === undefined) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; }; export default ThemeProvider; `, }, { name: "components/ThemeSwitcher.tsx", content: ` import React from 'react'; import { useTheme } from '../theme/ThemeProvider'; import { Theme } from '../types'; const ThemeSwitcher = () => { const { theme, setTheme } = useTheme(); const themes: { value: Theme; label: string }[] = [ { value: 'light', label: '☀️ Light' }, { value: 'dark', label: '🌙 Dark' }, { value: 'system', label: '🖥️ System' } ]; return (
{themes.map(({ value, label }) => ( ))}
); }; export default ThemeSwitcher; `, }, { name: "hooks/useUser.ts", content: ` import { useState, useEffect } from 'react'; import { User } from '../types'; export const useUser = ( userId: string, fetchUserData: (id: string) => Promise ) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let isMounted = true; const loadUser = async () => { try { setLoading(true); const userData = await fetchUserData(userId); if (isMounted) { setUser(userData); setError(null); } } catch (err) { if (isMounted) { setError('Failed to load user'); setUser(null); } } finally { if (isMounted) { setLoading(false); } } }; loadUser(); return () => { isMounted = false; }; }, [userId, fetchUserData]); return { user, loading, error }; }; `, }, { name: "utils/api.ts", content: ` import { User } from '../types'; // Simulate API call with mock data export const fetchUserData = async (userId: string): Promise => { // Simulate network delay await new Promise(resolve => setTimeout(resolve, 1000)); // Mock data const users: Record = { '1': { id: '1', name: 'John Doe', email: 'john@example.com', avatar: 'https://randomuser.me/api/portraits/men/32.jpg' }, '2': { id: '2', name: 'Jane Smith', email: 'jane@example.com', avatar: 'https://randomuser.me/api/portraits/women/44.jpg' } }; const user = users[userId]; if (!user) { throw new Error(\`User with ID \${userId} not found\`); } return user; }; `, }, { name: "components/UserProfile.tsx", content: ` import React from 'react'; import { useUser } from '../hooks/useUser'; import { User } from '../types'; interface UserProfileProps { userId: string; fetchUserData: (id: string) => Promise; } const UserProfile = ({ userId, fetchUserData }: UserProfileProps) => { const { user, loading, error } = useUser(userId, fetchUserData); if (loading) { return (
); } if (error) { return (

{error}

); } if (!user) { return
No user found
; } return (
{user.name}

{user.name}

{user.email}

User ID: {user.id}

); }; export default UserProfile; `, }, ]; function App() { return ( ); } ``` ### With Custom Error Handling ```tsx import { CodeExecutor } from "react-exe"; function App() { return ( { console.error("Component error:", error); // Send to error tracking service trackError(error); }, // Custom security patterns securityPatterns: [ /localStorage/i, /sessionStorage/i, /window\.location/i, ], }} /> ); } ``` ## Configuration Options The `config` prop accepts the following options: ```typescript interface CodeExecutorConfig { // External dependencies available to the rendered component dependencies?: Record; // Enable Tailwind CSS support enableTailwind?: boolean; // Custom className for the container containerClassName?: string; // Custom inline styles for the container containerStyle?: React.CSSProperties; // Custom className for error messages errorClassName?: string; // Custom inline styles for error messages errorStyle?: React.CSSProperties; // Custom security patterns to block potentially malicious code securityPatterns?: RegExp[]; // Error callback function onError?: (error: Error) => void; } ``` ## Code Input Types React-EXE accepts code in two formats: 1. **Single File**: Pass a string containing the React component code ```typescript // Single file as a string const code = ` export default function App() { return
Hello World
; } `; ``` 2. **Multiple Files**: Pass an array of CodeFile objects: ```typescript // Multiple files const code = [ { name: "App.tsx", content: "import React from 'react';\nimport Button from './Button';\n...", isEntry: true, // Mark this as the entry point }, { name: "Button.tsx", content: "export default function Button() { return ; }", }, ]; ``` The `CodeFile` interface: ```typescript interface CodeFile { name: string; // File name with extension (used for imports) content: string; // File content isEntry?: boolean; // Whether this is the entry point (defaults to first file if not specified) } ``` ## Security React-EXE includes built-in security measures: - Default security patterns to block potentially harmful code - Custom security pattern support - Error boundary protection Default blocked patterns include: ```typescript const defaultSecurityPatterns = [ /document\.cookie/i, /window\.document\.cookie/i, /eval\(/i, /Function\(/i, /document\.write/i, /document\.location/i, ]; ``` ## TypeScript Support React-EXE is written in TypeScript and includes type definitions. For the best development experience, use TypeScript in your project: ```tsx import { CodeExecutor, CodeExecutorConfig, CodeFile } from "react-exe"; const config: CodeExecutorConfig = { enableTailwind: true, dependencies: { "my-component": MyComponent, }, }; const files: CodeFile[] = [ { name: "App.tsx", content: `export default function App() { return
Hello
; }`, isEntry: true, }, ]; function App() { return ; } ``` ## Used By [TuneChat](https://chat.tune.app/) to render Artifacts Screenshot 2025-02-26 at 16 58 34 ## License MIT © [Vikrant](https://www.linkedin.com/in/vikrant-guleria/) --- Made with ❤️ by [Vikrant](https://www.linkedin.com/in/vikrant-guleria/)