"use client" import { useState, useEffect } from "react" import TerminalVisualizer from "@/components/terminal-visualizer" // Types for the layout tree type PaneNode = { type: "pane" id: number } type SplitNode = { type: "split-h" | "split-v" ratio: number children: [LayoutNode, LayoutNode] } export type LayoutNode = PaneNode | SplitNode const ASCII_ART = ` _________________________________________ / \\ | root@mytmux:~ $ tmux new -s dev | | [0] nvim ---------------- [1] server -- | | | | | | | | import { life } | npm run | | | | from 'tmux'; | dev | | | | | | | | | // TODO: Sleep | | | | |________________________|____________| | | [2] logs ------------------------------ | | | > ready in 200ms | | | | > watching files... | | | |_____________________________________| | \\_________________________________________/ ` export default function Home() { const [layout, setLayout] = useState({ type: "pane", id: 0 }) const [nextId, setNextId] = useState(1) const [activePaneId, setActivePaneId] = useState(0) const [generatedConfig, setGeneratedConfig] = useState("") // Helper to find and split the active node function findAndSplitNode( node: LayoutNode, activeId: number, direction: "h" | "v", nextIdVal: number, ): { found: boolean; nextId: number; newNode?: LayoutNode } { if (node.type === "pane") { if (node.id === activeId) { const oldId = node.id const newId = nextIdVal // Create new split node const newNode: SplitNode = { type: direction === "h" ? "split-h" : "split-v", ratio: 0.5, children: [ { type: "pane", id: oldId }, { type: "pane", id: newId }, ], } return { found: true, nextId: nextIdVal + 1, newNode } } return { found: false, nextId: nextIdVal } } else { // Recursively check children // We need to clone the node to avoid mutating state directly if we were modifying in place, // but here we are rebuilding the tree structure where needed. // Check left/top child const leftResult = findAndSplitNode(node.children[0], activeId, direction, nextIdVal) if (leftResult.found) { return { found: true, nextId: leftResult.nextId, newNode: { ...node, children: [leftResult.newNode as LayoutNode, node.children[1]], }, } } // Check right/bottom child const rightResult = findAndSplitNode(node.children[1], activeId, direction, nextIdVal) if (rightResult.found) { return { found: true, nextId: rightResult.nextId, newNode: { ...node, children: [node.children[0], rightResult.newNode as LayoutNode], }, } } return { found: false, nextId: nextIdVal } } } function splitPane(direction: "h" | "v") { const result = findAndSplitNode(layout, activePaneId, direction, nextId) if (result.found && result.newNode) { setNextId(result.nextId) setLayout(result.newNode) } } function resetLayout() { setLayout({ type: "pane", id: 0 }) setNextId(1) setActivePaneId(0) } // Generate config whenever layout changes useEffect(() => { let config = `# ~/.tmux.conf setup\n` config += `# Configured by Shawn Anderson (Long Tail Financial)\n` config += `# Generated by mytmux.life\n\n` config += `new-session -s development -n editor\n` function traverse(node: LayoutNode) { if (node.type === "split-h") { config += `split-window -h\n` traverse(node.children[1]) // Right child config += `select-pane -L\n` // Go back left traverse(node.children[0]) // Left child } else if (node.type === "split-v") { config += `split-window -v\n` traverse(node.children[1]) // Bottom child config += `select-pane -U\n` // Go back up traverse(node.children[0]) // Top child } } traverse(layout) config += `\n# Select the initially active pane\n` config += `select-pane -t ${activePaneId}\n` setGeneratedConfig(config) }, [layout, activePaneId]) return (
{/* Hero Section */}
SYSTEM ONLINE

Master Your
<Terminal />

Stop wasting time switching windows. mytmux.life helps you architect the perfect terminal development environment.

{/* ASCII Art / Decorative Element */}
{ASCII_ART}
{/* Configurator Section */}

ENVIRONMENT_CONFIGURATOR

Visually design your session layout. Click actions to split the active pane.

{/* Controls & Output */}

> ACTIONS

ACTIVE_PANE_ID: {activePaneId}

> GENERATED_CONFIG

{generatedConfig}
{/* Visualizer Canvas */}
CANVAS_RENDER_TARGET
{/* Documentation / Info Section */}

THE_TMUX_IFESTO

The philosophy of persistent, multiplexed terminal environments.

01. PERSISTENCE

Your work should not die when your connection drops. Detach your session, go home, and reattach exactly where you left off. The session lives on the server, independent of your client.

02. MULTIPLEXING

One terminal is never enough. Split your workspace into windows (tabs) and panes (tiled splits). Monitor logs, edit code, and run git commands simultaneously in a single SSH connection.

03. CONFIGURATION

The terminal is your canvas. Script your layouts, bind custom keys, and automate your startup. A well-configured tmux environment is a force multiplier for any developer.

{/* Mobile Setup Section */}

MOBILE_DEPLOYMENT_PROTOCOLS

{/* Android Protocol */}

ANDROID TERMUX_PROTOCOL

01.

Acquire F-Droid

Download the F-Droid APK from f-droid.org to access the open-source repository.

02.

Install Termux

Search for "Termux" within F-Droid. Do not use the Play Store version (deprecated).

03.

Initialize Environment

$ pkg update && pkg upgrade

$ pkg install tmux vim git

{/* iOS Protocol */}

APPLE ISH_SHELL_PROTOCOL

01.

Acquire iSH Shell

Install "iSH Shell" from the App Store. This provides a localized Alpine Linux environment.

02.

Package Management

iSH uses Alpine's 'apk' package manager.

03.

Deploy Tmux

$ apk update

$ apk add tmux vim openssh

{/* Cheat Sheet */}

COMMAND_REFERENCE_MATRIX

{[ { cmd: "tmux new -s ", desc: "Start new named session" }, { cmd: "tmux a -t ", desc: "Attach to existing session" }, { cmd: "tmux ls", desc: "List all active sessions" }, { cmd: "Ctrl+b d", desc: "Detach from current session" }, { cmd: "Ctrl+b %", desc: "Split pane vertically" }, { cmd: 'Ctrl+b "', desc: "Split pane horizontally" }, { cmd: "Ctrl+b ", desc: "Navigate between panes" }, { cmd: "Ctrl+b z", desc: "Toggle pane zoom (maximize)" }, { cmd: "Ctrl+b c", desc: "Create new window" }, { cmd: "Ctrl+b n", desc: "Move to next window" }, { cmd: "Ctrl+b ,", desc: "Rename current window" }, { cmd: "Ctrl+b [", desc: "Enter copy/scroll mode" }, ].map((item, i) => (
{item.desc} {item.cmd}
))}
) }