Seymour Papert’s constructionism meets Linear.app aesthetics. Rows over cards, progressive disclosure.
$ npx snappy-skills install seymour-papert
A design philosophy — not a component library — for building dashboard interfaces that teach through interaction. Combines Seymour Papert's constructionism (learn by exploring, not by being told) with Linear.app's visual language (one surface, minimal chrome, rows over cards).
The core principle: Information should arrive in the order cognition requests it, at the depth cognition is ready for. A page is a mirror of how a person thinks — each section answers the next question the mind is already forming. The visual rules (rows, dots, inline stats) are symptoms of this principle. They work because they match how cognition flows: overview → scan → select → reveal.
Seymour Papert's constructionism says: people learn by building and exploring, not by being presented with pre-digested views. Applied to dashboards:
Linear.app's aesthetic is radical simplicity:
282 files · 3,167 lines · COBOL not three separate StatCards.border-t sections, not Card wrappers.Before touching any page, ask these:
| # | Question | If yes... |
|---|---|---|
| 1 | Are there StatCard grids (3-4 cards showing single numbers)? | → Convert to inline stat line |
| 2 | Are there Card-wrapped sections that aren't interactive forms? | → Unwrap to border-t sections |
| 3 | Is there a view mode toggle (list/grid/gallery)? | → Merge into one expandable view |
| 4 | Does clicking a list item navigate away from the list? | → Make it expand in place instead |
| 5 | Are there multi-column card grids for displaying info? | → Convert to single-column rows |
If you answered yes to 0: the page may already be clean.
If you answered yes to 1-2: quick cleanup.
If you answered yes to 3+: full redesign needed.
tsx<p className="text-sm text-muted-foreground">
<span className="text-foreground font-medium">Healthy</span>
{" · "}<span className="text-foreground font-medium">12</span> routes
{" · "}<span className="text-foreground font-medium">8</span> functions
{" · "}142MB memory
</p>
Rules:
text-foreground font-medium{" · "} (middle dot with spaces)text-success or text-destructivetsx<div className="border border-border/50 rounded-lg divide-y divide-border/30">
{groups.map((group) => (
<button
key={group.name}
onClick={() => toggle(group.name)}
className="w-full group flex items-center gap-3 px-3 py-2.5
text-left hover:bg-muted/30 transition-colors"
>
<span className="w-1.5 h-1.5 rounded-full shrink-0"
style={{ backgroundColor: group.color }} />
<span className="text-sm font-medium truncate">{group.name}</span>
<span className="text-xs text-muted-foreground font-mono">
{group.count}
</span>
{/* summary info visible when collapsed */}
<div className="ml-auto flex items-center gap-1.5">
{expanded ? <ChevronDown /> : <ChevronRight />}
</div>
</button>
{expanded && <ChildRows />}
))}
</div>
tsx{/* Before: */}
<Card><CardHeader><CardTitle>Recent Requests</CardTitle></CardHeader>
<CardContent><Table>...</Table></CardContent></Card>
{/* After: */}
<div className="border-t border-border/40 pt-4">
<p className="text-sm font-medium mb-2">Recent Requests</p>
<Table>...</Table>
</div>
tsx{/* Before: */}
<div className="h-10 w-10 rounded-lg bg-blue-500/10 flex items-center
justify-center"><Server className="h-5 w-5 text-blue-500" /></div>
{/* After: */}
<span className="w-1.5 h-1.5 rounded-full bg-blue-500 shrink-0" />
tsx<div className="border border-border/20 bg-card/30 rounded-lg p-3">
{/* AI summary, generated content, etc. */}
</div>
| Need to... | Read this |
|---|---|
| Understand the philosophy deeply | philosophy.md |
| See before/after transformation examples | transformations.md |
| Apply to a specific page type | page-recipes.md |
| Know what NOT to change | exceptions.md |
border-t dividersborder rounded-lg divide-y containersThis is where most people stop too early. Visual changes aren't enough.
See exceptions.md for the full list.
| Don't | Instead |
|---|---|
| 3-4 StatCards showing single numbers | One inline stat line |
| Card wrapping a read-only section | border-t border-border/40 pt-4 |
| View mode toggle (list/grid/gallery) | One expandable view |
| Click group → navigate to filtered page | Click group → expand in place |
| Icon in colored rounded box | 1.5px color dot |
| Multi-column card grid for info display | Single column rows |
bg-gradient-to-r on info cards |
Plain background |
| Separate "summary" and "detail" views | Progressive disclosure on one surface |
This skill is designed to evolve. After applying it to a page:
Update this skill after each major page redesign.
Skill Status: COMPLETE
Line Count: < 500
Progressive Disclosure: 4 resource files
---
name: papert-linear
description: "Design philosophy combining Seymour Papert's constructionism with Linear.app aesthetics. Progressive disclosure, direct manipulation, inline stats, clean rows, no card grids, no view mode toggles. Use when redesigning UI pages, auditing dashboard layouts, converting card-based interfaces to row-based ones, or applying constructionist interaction models to admin dashboards."
---
# Papert-Linear Design System
## Purpose
A design philosophy — not a component library — for building dashboard interfaces that teach through interaction. Combines Seymour Papert's constructionism (learn by exploring, not by being told) with Linear.app's visual language (one surface, minimal chrome, rows over cards).
**The core principle**: Information should arrive in the order cognition requests it, at the depth cognition is ready for. A page is a mirror of how a person thinks — each section answers the next question the mind is already forming. The visual rules (rows, dots, inline stats) are symptoms of this principle. They work because they match how cognition flows: overview → scan → select → reveal.
## When to Use This Skill
- Redesigning or auditing dashboard pages
- Converting card-grid layouts to clean row layouts
- Replacing StatCard grids with inline stats
- Removing unnecessary view mode toggles
- Building new admin/dashboard pages from scratch
- Any UI work where "it looks busy" or "there are too many cards"
---
## The Two Pillars
### Papert: The Interaction Model
Seymour Papert's constructionism says: people learn by building and exploring, not by being presented with pre-digested views. Applied to dashboards:
1. **One surface** — no view mode toggles. The user explores ONE map.
2. **Progressive disclosure** — click to expand, click to collapse. Zoom in, zoom out.
3. **Direct manipulation** — the thing you see IS the thing you interact with.
4. **No mode switching** — clicking a group shouldn't navigate you away. It opens right there.
5. **Context preservation** — expanding one section doesn't hide the others.
### Linear: The Visual Language
Linear.app's aesthetic is radical simplicity:
1. **Rows, not cards** — information in horizontal lines, not boxed grids.
2. **Inline stats** — `282 files · 3,167 lines · COBOL` not three separate StatCards.
3. **Minimal chrome** — no icon-in-rounded-box, no gradient cards, no glassmorphic effects.
4. **Single column** — content flows vertically in one column.
5. **Subtle dividers** — `border-t` sections, not Card wrappers.
---
## The Audit: 5 Questions
Before touching any page, ask these:
| # | Question | If yes... |
|---|----------|-----------|
| 1 | Are there StatCard grids (3-4 cards showing single numbers)? | → Convert to inline stat line |
| 2 | Are there Card-wrapped sections that aren't interactive forms? | → Unwrap to `border-t` sections |
| 3 | Is there a view mode toggle (list/grid/gallery)? | → Merge into one expandable view |
| 4 | Does clicking a list item navigate away from the list? | → Make it expand in place instead |
| 5 | Are there multi-column card grids for displaying info? | → Convert to single-column rows |
If you answered yes to 0: the page may already be clean.
If you answered yes to 1-2: quick cleanup.
If you answered yes to 3+: full redesign needed.
---
## Quick Reference: Patterns
### Inline Stat Line (replaces StatCard grids)
```tsx
<p className="text-sm text-muted-foreground">
<span className="text-foreground font-medium">Healthy</span>
{" · "}<span className="text-foreground font-medium">12</span> routes
{" · "}<span className="text-foreground font-medium">8</span> functions
{" · "}142MB memory
</p>
```
**Rules:**
- Values needing emphasis: `text-foreground font-medium`
- Separator: `{" · "}` (middle dot with spaces)
- Status values: `text-success` or `text-destructive`
- Keep it one line. If it needs two lines, it's two stat lines.
### Expandable Row (replaces card grids + view toggles)
```tsx
<div className="border border-border/50 rounded-lg divide-y divide-border/30">
{groups.map((group) => (
<button
key={group.name}
onClick={() => toggle(group.name)}
className="w-full group flex items-center gap-3 px-3 py-2.5
text-left hover:bg-muted/30 transition-colors"
>
<span className="w-1.5 h-1.5 rounded-full shrink-0"
style={{ backgroundColor: group.color }} />
<span className="text-sm font-medium truncate">{group.name}</span>
<span className="text-xs text-muted-foreground font-mono">
{group.count}
</span>
{/* summary info visible when collapsed */}
<div className="ml-auto flex items-center gap-1.5">
{expanded ? <ChevronDown /> : <ChevronRight />}
</div>
</button>
{expanded && <ChildRows />}
))}
</div>
```
### Section Divider (replaces Card wrapper)
```tsx
{/* Before: */}
<Card><CardHeader><CardTitle>Recent Requests</CardTitle></CardHeader>
<CardContent><Table>...</Table></CardContent></Card>
{/* After: */}
<div className="border-t border-border/40 pt-4">
<p className="text-sm font-medium mb-2">Recent Requests</p>
<Table>...</Table>
</div>
```
### Color Dot (replaces icon-in-rounded-box)
```tsx
{/* Before: */}
<div className="h-10 w-10 rounded-lg bg-blue-500/10 flex items-center
justify-center"><Server className="h-5 w-5 text-blue-500" /></div>
{/* After: */}
<span className="w-1.5 h-1.5 rounded-full bg-blue-500 shrink-0" />
```
### Subtle Container (for AI/generated content)
```tsx
<div className="border border-border/20 bg-card/30 rounded-lg p-3">
{/* AI summary, generated content, etc. */}
</div>
```
---
## Navigation Guide
| Need to... | Read this |
|------------|-----------|
| Understand the philosophy deeply | [philosophy.md](philosophy.md) |
| See before/after transformation examples | [transformations.md](transformations.md) |
| Apply to a specific page type | [page-recipes.md](page-recipes.md) |
| Know what NOT to change | [exceptions.md](exceptions.md) |
---
## The Process
### Phase 1: Audit (read-only)
1. Read the page file completely
2. Run the 5 Questions audit above
3. Count: StatCards, Card wrappers, view toggles, card grids
4. Identify the interaction model — does clicking navigate away or expand in place?
### Phase 2: Transform (visual)
1. Replace StatCard grids with inline stat lines
2. Unwrap Card containers from info sections → `border-t` dividers
3. Convert card grids to row-based lists in `border rounded-lg divide-y` containers
4. Replace icon-in-box patterns with color dots
5. Remove gradient/glassmorphic card styling
### Phase 3: Transform (interaction model)
This is where most people stop too early. **Visual changes aren't enough.**
1. If there's a view mode toggle → merge views into one expandable surface
2. If clicking navigates away from a list → make it expand in place
3. If sections are hidden behind tabs → make them collapsible sections on one page
4. Remove state variables for view modes, active groups, etc.
5. The URL should only change when entering a truly different context (e.g., route detail)
### Phase 4: Verify
1. Build — must compile clean
2. Deploy
3. **Browse the page yourself** (agent-browser or manual)
4. Ask: "Can I understand the full picture from this one surface?"
5. Ask: "Does clicking explore deeper, or does it take me somewhere else?"
6. If confused → the interaction model still needs work
---
## What NOT to Change
- **Navigation cards** — clickable entry points to other pages (service grid, etc.)
- **Interactive forms** — route testers, SQL editors, config forms → keep Card wrappers
- **Dialogs** — keep Dialog components as-is
- **Charts** — keep chart libraries, just remove Card wrappers around them
- **Tables** — keep Table component, just remove Card/CardHeader wrappers
See [exceptions.md](exceptions.md) for the full list.
---
## Anti-Patterns
| Don't | Instead |
|-------|---------|
| 3-4 StatCards showing single numbers | One inline stat line |
| Card wrapping a read-only section | `border-t border-border/40 pt-4` |
| View mode toggle (list/grid/gallery) | One expandable view |
| Click group → navigate to filtered page | Click group → expand in place |
| Icon in colored rounded box | 1.5px color dot |
| Multi-column card grid for info display | Single column rows |
| `bg-gradient-to-r` on info cards | Plain background |
| Separate "summary" and "detail" views | Progressive disclosure on one surface |
---
## Iterating the Skill
This skill is designed to evolve. After applying it to a page:
1. Did the 5 Questions catch everything? If not, add a question.
2. Did a new pattern emerge? Add it to Quick Reference.
3. Did you find something that should NOT be changed? Add it to exceptions.
4. Did the user push back on something? That's signal — update the philosophy.
Update this skill after each major page redesign.
---
**Skill Status**: COMPLETE
**Line Count**: < 500
**Progressive Disclosure**: 4 resource files