---
name: opentui-projects
description: Expert assistance for OpenTUI project scaffolding, templates, examples, and learning paths. Use for quick start, project templates, component library, and best practices.
---
# OpenTUI Projects
Expert assistance for scaffolding OpenTUI projects and exploring examples.
## Quick Start (create-tui)
The fastest way to create an OpenTUI project:
```bash
# Using create-tui (recommended)
bun create tui my-app
# Or with npm
npm create tui my-app
```
### Template Selection
```bash
# Choose from available templates:
# - minimal: Minimal setup
# - basic-cli: Basic CLI tool
# - dashboard: Dashboard layout
# - form-app: Form-based application
# - editor: Text editor template
# - game: Simple game template
bun create tui my-app --template dashboard
```
## Manual Project Setup
### Core Project Structure
```
my-opentui-app/
├── package.json
├── tsconfig.json
├── src/
│ ├── main.tsx
│ ├── components/
│ └── utils/
└── README.md
```
### package.json
```json
{
"name": "my-opentui-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "bun run src/main.tsx",
"build": "tsc",
"start": "bun run dist/main.js"
},
"dependencies": {
"@opentui/core": "latest",
"@opentui/react": "latest",
"react": "^18.3.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.3.0"
}
}
```
### tsconfig.json
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
```
### Basic Entry Point
```tsx
// src/main.tsx
import { createCliRenderer } from "@opentui/core"
import { createRoot } from "@opentui/react"
function App() {
return Hello, OpenTUI!
}
async function main() {
const renderer = await createCliRenderer()
createRoot(renderer).render()
}
main()
```
## Project Templates
### Minimal Template
**Use case:** Simple hello world, learning basics
```tsx
import { createCliRenderer } from "@opentui/core"
import { TextRenderable } from "@opentui/core"
async function main() {
const renderer = await createCliRenderer()
const text = new TextRenderable("Hello, World!")
renderer.getRoot().add(text)
renderer.start()
}
main()
```
### CLI Tool Template
**Use case:** Command-line tools with menus
```tsx
import { createCliRenderer } from "@opentui/core"
import { BoxRenderable, TextRenderable } from "@opentui/core"
async function main() {
const renderer = await createCliRenderer()
const container = new BoxRenderable()
container.setStyle({
borderStyle: "double",
padding: 1,
})
const title = new TextRenderable("My CLI Tool")
title.setStyle({ textDecoration: "bold" })
container.add(title)
renderer.getRoot().add(container)
renderer.start()
}
main()
```
### Dashboard Template
**Use case:** Multi-panel dashboard applications
```tsx
import { createCliRenderer } from "@opentui/core"
import { GroupRenderable, BoxRenderable, TextRenderable } from "@opentui/core"
async function main() {
const renderer = await createCliRenderer()
const root = renderer.getRoot()
const app = new GroupRenderable()
app.setStyle({
flexDirection: "row",
width: 80,
height: 30,
})
// Sidebar
const sidebar = new BoxRenderable()
sidebar.setStyle({
width: 20,
borderStyle: "single",
})
sidebar.add(new TextRenderable("Sidebar"))
// Main content
const main = new BoxRenderable()
main.setStyle({
flexGrow: 1,
borderStyle: "single",
})
main.add(new TextRenderable("Main Content"))
app.add(sidebar)
app.add(main)
root.add(app)
renderer.start()
}
main()
```
### Form App Template
**Use case:** Data entry applications
```tsx
import { createCliRenderer } from "@opentui/core"
import {
GroupRenderable,
BoxRenderable,
TextRenderable,
InputRenderable,
} from "@opentui/core"
async function main() {
const renderer = await createCliRenderer()
const root = renderer.getRoot()
const form = new GroupRenderable()
form.setStyle({
flexDirection: "column",
gap: 1,
width: 60,
})
const title = new TextRenderable("User Registration")
title.setStyle({ textDecoration: "bold" })
const nameInput = new InputRenderable()
nameInput.setPlaceholder("Name")
const emailInput = new InputRenderable()
emailInput.setPlaceholder("Email")
const submitButton = new BoxRenderable()
submitButton.setStyle({ borderStyle: "single" })
submitButton.add(new TextRenderable("Submit"))
form.add(title)
form.add(nameInput)
form.add(emailInput)
form.add(submitButton)
root.add(form)
renderer.start()
}
main()
```
## Component Library
### Button Component
```tsx
// components/Button.ts
import { BoxRenderable, TextRenderable } from "@opentui/core"
export interface ButtonOptions {
label: string
onClick?: () => void
variant?: "primary" | "secondary" | "danger"
}
export class Button {
private box: BoxRenderable
constructor(options: ButtonOptions) {
this.box = new BoxRenderable()
this.setupStyles(options.variant)
this.setupContent(options.label)
this.setupEvents(options.onClick)
}
private setupStyles(variant: string = "primary") {
const styles = {
primary: {
borderStyle: "single" as const,
backgroundColor: new Color(100, 149, 237),
foregroundColor: new Color(255, 255, 255),
},
secondary: {
borderStyle: "single" as const,
backgroundColor: new Color(50, 50, 50),
foregroundColor: new Color(255, 255, 255),
},
danger: {
borderStyle: "single" as const,
backgroundColor: new Color(231, 76, 60),
foregroundColor: new Color(255, 255, 255),
},
}
const style = styles[variant as keyof typeof styles] || styles.primary
this.box.setStyle(style)
}
private setupContent(label: string) {
const text = new TextRenderable(label)
this.box.add(text)
}
private setupEvents(onClick?: () => void) {
if (onClick) {
this.box.on("click", onClick)
}
}
getRenderable() {
return this.box
}
}
```
### Modal Component
```tsx
// components/Modal.ts
import { BoxRenderable, TextRenderable, GroupRenderable } from "@opentui/core"
export class Modal {
private overlay: BoxRenderable
private content: BoxRenderable
constructor() {
this.overlay = new BoxRenderable()
this.overlay.setStyle({
position: "absolute",
top: 0,
left: 0,
width: 80,
height: 30,
backgroundColor: new Color(0, 0, 0, 0.5),
})
this.content = new BoxRenderable()
this.content.setStyle({
borderStyle: "double",
backgroundColor: new Color(30, 30, 30),
padding: 2,
})
this.overlay.add(this.content)
}
setContent(component: any) {
this.content.clear()
this.content.add(component)
}
show() {
this.overlay.setStyle({ display: "flex" })
}
hide() {
this.overlay.setStyle({ display: "none" })
}
getRenderable() {
return this.overlay
}
}
```
## Learning Paths
### Beginner Path (1-2 weeks)
**Week 1: Basics**
1. Set up minimal project
2. Learn basic components (Text, Box)
3. Understand Yoga layout
4. Handle keyboard input
5. Style with colors
**Week 2: Interactive**
1. Use Input and Select components
2. Manage focus
3. Create simple forms
4. Handle events
5. Debug with console overlay
**Projects:**
- Hello World app
- Simple menu
- Basic form
- Counter app
### Intermediate Path (2-4 weeks)
**Week 3-4: Advanced**
1. ScrollBox for lists
2. Animations with Timeline
2. Component composition
3. State management
4. Testing basics
**Projects:**
- Todo list
- File explorer
- Simple game (tic-tac-toe)
- Dashboard with multiple panels
### Advanced Path (4-8 weeks)
**Week 5-8: Production**
1. Performance optimization
2. Advanced patterns
3. Error handling
4. Production deployment
5. Advanced testing
**Projects:**
- Text editor
- Terminal emulator
- Database viewer
- Complex dashboard
## Examples Explorer
### Available Examples
See `.search-data/research/opentui/resources.md` for a complete list of examples.
**Key Examples:**
1. **OpenCode** - AI coding agent (https://opencode.ai)
2. **cftop** - CloudFlare dashboard
3. **critique** - Git review tool
4. **opentui-examples** - Community examples
### Running Examples
```bash
# Clone OpenTUI repo
git clone https://github.com/sst/opentui.git
cd opentui
# Install dependencies
bun install
# Run core examples
cd packages/core
bun run src/examples/index.ts
# Run React examples
cd packages/react
bun run dev
```
## Best Practices
### Project Organization
```
src/
├── main.tsx # Entry point
├── app/ # App components
│ ├── App.tsx
│ └── layout/
├── components/ # Reusable components
│ ├── ui/
│ └── features/
├── hooks/ # Custom hooks (React/SolidJS)
├── stores/ # State management
├── utils/ # Helper functions
└── types/ # TypeScript types
```
### Component Design
1. **Single Responsibility:** Each component does one thing
2. **Composition:** Build complex UIs from simple components
3. **Props Interface:** Define clear props with TypeScript
4. **Styling Consistency:** Use themes and style utilities
5. **Error Handling:** Add error boundaries
### Performance
1. **Memoize expensive computations**
2. **Use efficient list rendering**
3. **Optimize re-renders**
4. **Profile performance**
5. **Test with realistic data**
## When to Use This Skill
Use `/opentui-projects` for:
- Creating new OpenTUI projects
- Choosing project templates
- Exploring examples
- Learning OpenTUI patterns
- Finding component libraries
- Best practices guidance
For core development help, use `/opentui`
For React-specific help, use `/opentui-react`
For SolidJS-specific help, use `/opentui-solid`
## Resources
- [Templates](references/TEMPLATES.md) - Complete template catalog
- [Examples](references/EXAMPLES.md) - Curated example collection
- [Learning Paths](references/LEARNING.md) - Structured learning guides
- [Best Practices](references/PRACTICES.md) - Production guidelines
## Key Knowledge Sources
- create-tui: https://github.com/msmps/create-tui
- Awesome OpenTUI: https://github.com/msmps/awesome-opentui
- OpenTUI Examples: https://github.com/sst/opentui/tree/main/packages/core/src/examples
- Research: `.search-data/research/opentui/`