A modern template for creative coding experiments and interactive demos. Built with React, TypeScript, Vite, and Tailwind CSS, featuring Tweakpane for live parameter controls.
- React 19 - Modern hooks and concurrent features
- TypeScript - Full type safety
- Vite - Fast development and optimized builds
- Tailwind CSS v4 - Utility-first styling
- Tweakpane - Interactive parameter controls
- ESLint - Code linting and formatting
- Modular architecture - Clear separation between starter code and demo
- Node.js 18+
- pnpm (recommended), npm, or yarn
# Clone or use this template
git clone <your-repo-url>
cd lab-starter
# Install dependencies
pnpm install
# Start development server
pnpm devThe app will be running at http://localhost:5173
pnpm buildpnpm previewThis template includes two main parts:
Reusable components and utilities:
src/components/- Reusable React componentsBackground.tsx- Dot grid background with theme supportTweakpanePanel.tsx- Generic wrapper for Tweakpane controls
src/lib/- Utility functionscn()- Tailwind class merging with conflict resolutionwithViewTransition()- View Transitions API wrapper
- Configuration files - Prettier, ESLint, EditorConfig
A reference implementation demonstrating the starter capabilities:
src/demo/- Complete demo applicationDemoApp.tsx- Main demo componentuseDemoControls.ts- Tweakpane configurationconstants.ts- Demo constantsutils.ts- Demo utilities
-
Delete the demo folder:
rm -rf src/demo
-
Update
src/App.tsx:export const App = () => { return <div>{/* Your application */}</div>; };
Alternatively, keep the demo folder during initial development and remove it later.
- Creative coding experiments
- Interactive demos and prototypes
- Data visualizations
- Animation showcases
- Educational projects
Use the reusable TweakpanePanel component to add controls:
import { TweakpanePanel } from "@/components/TweakpanePanel";
import { useState } from "react";
export const MyLab = () => {
const [value, setValue] = useState(100);
const setupControls = (pane) => {
const params = { myValue: value };
pane
.addBinding(params, "myValue", { min: 0, max: 200 })
.on("change", (ev) => setValue(ev.value));
};
return (
<>
<TweakpanePanel title="My Controls" onInit={setupControls} />
<div>Value: {value}</div>
</>
);
};import { Background } from "@/components/Background";
<Background theme="dark">
<YourContent />
</Background>;import { cn, withViewTransition } from "@/lib/utils";
// Merge Tailwind classes
const className = cn("px-4 py-2", isDark && "bg-gray-900", "px-6");
// Smooth transitions
withViewTransition(() => {
setState(newValue);
});- React 19.2 - UI library
- TypeScript 5.9 - Type system
- Vite 7.3 - Build tool
- Tailwind CSS 4.1 - Styling
- Tweakpane 4.0 - Control panel
- ESLint 9 - Linting
- All modern browsers (Chrome, Firefox, Safari, Edge)
- Best experience on latest versions
lab-starter/
├── src/
│ ├── components/ # Reusable components (STARTER)
│ │ ├── Background.tsx
│ │ └── TweakpanePanel.tsx
│ ├── lib/ # Utility functions (STARTER)
│ │ └── utils.ts
│ ├── demo/ # Demo application (removable)
│ │ ├── DemoApp.tsx
│ │ ├── useDemoControls.ts
│ │ ├── constants.ts
│ │ └── utils.ts
│ ├── App.tsx # Main entry point
│ ├── main.tsx # React entry point
│ ├── global.css # Global styles
│ └── vite-env.d.ts # TypeScript declarations
├── .github/ # GitHub templates
│ ├── ISSUE_TEMPLATE/
│ └── PULL_REQUEST_TEMPLATE.md
├── public/ # Static assets
├── .editorconfig # Editor configuration
├── .nvmrc # Node.js version
├── .prettierrc.json # Prettier configuration
├── CHANGELOG.md # Version history
├── CONTRIBUTING.md # Contribution guidelines
├── eslint.config.js # ESLint configuration
├── index.html # HTML entry point
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── vite.config.ts # Vite configuration
└── README.md # Documentation
Contributions are welcome. Please read CONTRIBUTING.md for guidelines.
See LICENSE file for details.