The Multi-tab framework of Bubbletea programs!
65
stars
90
commits
Go
primary language
Jul 3, 2026
updated
Skeleton is a Go library built on top of the Bubble Tea framework designed to simplify the development of multi-tab terminal user interface (TUI) applications.

Skeleton leverages Bubble Tea's architecture to provide a framework for multi-tab TUI applications. This tutorial assumes you have a working knowledge of Go and Bubble Tea.
For a complete example code, you can refer to the source code on GitHub.
First, you'll need to install Skeleton. Use the following command to get it:
go get github.com/termkit/skeleton
Let's walk through an example of how to use Skeleton to create a basic multi-tab application.
We'll start by defining a simple model for our tabs. Each tab will be represented by a tinyModel struct:
package main
import (
"fmt"
"strings"
"github.com/termkit/skeleton"
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
)
// -----------------------------------------------------------------------------
// Tiny Model
// The Tiny Model is a sub-model for the tabs. It's a simple model that just shows the title of the tab.
// tinyModel is a sub-model for the tabs
type tinyModel struct {
skeleton *skeleton.Skeleton
title string
}
// newTinyModel returns a new tinyModel
func newTinyModel(skeleton *skeleton.Skeleton, title string) *tinyModel {
return &tinyModel{
skeleton: skeleton,
title: title,
}
}
func (m tinyModel) Init() tea.Cmd {
return nil
}
func (m tinyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}
func (m tinyModel) View() string {
verticalCenter := m.skeleton.GetTerminalHeight()/2 - 3
requiredNewLines := strings.Repeat("\n", verticalCenter)
return fmt.Sprintf("%s%s | %d x %d", requiredNewLines, m.title, m.skeleton.GetTerminalWidth(), m.skeleton.GetTerminalHeight())
}
Initialize Skeleton, add pages, and configure widgets:
// -----------------------------------------------------------------------------
// Main Program
func main() {
s := skeleton.NewSkeleton()
// Add tabs (pages)
s.AddPage("first", "First Tab", newTinyModel(s, "First"))
s.AddPage("second", "Second Tab", newTinyModel(s, "Second"))
s.AddPage("third", "Third Tab", newTinyModel(s, "Third"))
// Set up key bindings ( Optional | Defaults: ctrl+left, ctrl+right )
//To switch next page
s.KeyMap.SwitchTabRight = key.NewBinding(
key.WithKeys("shift+right"))
// To switch previous page
s.KeyMap.SwitchTabLeft = key.NewBinding(
key.WithKeys("shift+left"))
// Add a widget to entire screen
s.AddWidget("battery", "Battery %92")
s.AddWidget("time", time.Now().Format("15:04:05"))
// Update the time widget every second
go func() {
time.Sleep(time.Second)
for {
s.UpdateWidgetValue("time", time.Now().Format("15:04:05"))
time.Sleep(time.Second)
}
}()
p := tea.NewProgram(s)
if err := p.Start(); err != nil {
panic(err)
}
}
Model Definition: tinyModel represents the content of each tab. It uses the Skeleton instance to query terminal dimensions and display information.
Application Setup: The main function initializes Skeleton, adds pages, and sets up widgets. The time widget updates every second to reflect the current time.
The examples directory contains several demonstration applications. See examples for more details.
Some programs that use Skeleton in production:
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
Distributed under the GNU GENERAL PUBLIC LICENSE Version 3 or later. See LICENSE for more information.
Go
100.0%
The Multi-tab framework of Bubbletea programs!
65
stars
90
commits
Go
primary language
Jul 3, 2026
updated
Skeleton is a Go library built on top of the Bubble Tea framework designed to simplify the development of multi-tab terminal user interface (TUI) applications.

Skeleton leverages Bubble Tea's architecture to provide a framework for multi-tab TUI applications. This tutorial assumes you have a working knowledge of Go and Bubble Tea.
For a complete example code, you can refer to the source code on GitHub.
First, you'll need to install Skeleton. Use the following command to get it:
go get github.com/termkit/skeleton
Let's walk through an example of how to use Skeleton to create a basic multi-tab application.
We'll start by defining a simple model for our tabs. Each tab will be represented by a tinyModel struct:
package main
import (
"fmt"
"strings"
"github.com/termkit/skeleton"
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
)
// -----------------------------------------------------------------------------
// Tiny Model
// The Tiny Model is a sub-model for the tabs. It's a simple model that just shows the title of the tab.
// tinyModel is a sub-model for the tabs
type tinyModel struct {
skeleton *skeleton.Skeleton
title string
}
// newTinyModel returns a new tinyModel
func newTinyModel(skeleton *skeleton.Skeleton, title string) *tinyModel {
return &tinyModel{
skeleton: skeleton,
title: title,
}
}
func (m tinyModel) Init() tea.Cmd {
return nil
}
func (m tinyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}
func (m tinyModel) View() string {
verticalCenter := m.skeleton.GetTerminalHeight()/2 - 3
requiredNewLines := strings.Repeat("\n", verticalCenter)
return fmt.Sprintf("%s%s | %d x %d", requiredNewLines, m.title, m.skeleton.GetTerminalWidth(), m.skeleton.GetTerminalHeight())
}
Initialize Skeleton, add pages, and configure widgets:
// -----------------------------------------------------------------------------
// Main Program
func main() {
s := skeleton.NewSkeleton()
// Add tabs (pages)
s.AddPage("first", "First Tab", newTinyModel(s, "First"))
s.AddPage("second", "Second Tab", newTinyModel(s, "Second"))
s.AddPage("third", "Third Tab", newTinyModel(s, "Third"))
// Set up key bindings ( Optional | Defaults: ctrl+left, ctrl+right )
//To switch next page
s.KeyMap.SwitchTabRight = key.NewBinding(
key.WithKeys("shift+right"))
// To switch previous page
s.KeyMap.SwitchTabLeft = key.NewBinding(
key.WithKeys("shift+left"))
// Add a widget to entire screen
s.AddWidget("battery", "Battery %92")
s.AddWidget("time", time.Now().Format("15:04:05"))
// Update the time widget every second
go func() {
time.Sleep(time.Second)
for {
s.UpdateWidgetValue("time", time.Now().Format("15:04:05"))
time.Sleep(time.Second)
}
}()
p := tea.NewProgram(s)
if err := p.Start(); err != nil {
panic(err)
}
}
Model Definition: tinyModel represents the content of each tab. It uses the Skeleton instance to query terminal dimensions and display information.
Application Setup: The main function initializes Skeleton, adds pages, and sets up widgets. The time widget updates every second to reflect the current time.
The examples directory contains several demonstration applications. See examples for more details.
Some programs that use Skeleton in production:
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
Distributed under the GNU GENERAL PUBLIC LICENSE Version 3 or later. See LICENSE for more information.
Go
100.0%