Superfile Sidebar Architecture and Pinned Directories Management
Superfile implements a hybrid navigation system that combines a static, TypeScript-defined sidebar tree with dynamic user-pinned directories stored in JSON configuration, enabling immutable documentation structure alongside customizable user workflows.
The yorukot/superfile repository structures its interface navigation through a declarative static model while persisting user-specific shortcuts via runtime configuration. This architectural pattern strictly separates immutable navigation elements from mutable user preferences, creating a predictable yet flexible browsing experience.
Static Navigation Tree Structure
The foundation of Superfile’s sidebar resides in website/src/lib/navigation.ts, which exports a strictly typed navigation hierarchy. This file defines the immutable structure of the documentation and interface navigation through distinct interfaces that differentiate between single links and collapsible groups.
Core Navigation Interfaces
The type system distinguishes between leaf nodes and container nodes using two primary interfaces:
export interface NavLeaf {
label: string;
slug: string;
zhLabel?: string;
}
export interface NavGroup {
label: string;
zhLabel?: string;
items: NavLeaf[];
}
export type NavNode = NavLeaf | NavGroup;
Each NavLeaf represents a terminal navigation destination with a display label, URL slug, and optional Chinese translation label. The NavGroup interface creates collapsible sections containing multiple leaf items, enabling organized categorization of documentation sections like "Start Here", "Configure", and "Contribute".
Navigation Utilities
To facilitate traversal and sequential navigation, the module exports two critical helper functions:
flattenNav(): Recursively walks the navigation tree and produces a flat, ordered array ofNavLeafobjects while preserving the hierarchical declaration order.getPrevNext(slug): Accepts a URL slug parameter, locates it within the flattened navigation array, and returns references to the immediately preceding and succeeding entries.
These utilities power breadcrumb generation, documentation "previous/next" pagination controls, and ordered traversal of the navigation structure without requiring repeated tree-walking operations.
Pinned Directories Runtime Management
Unlike the static navigation tree, pinned directories represent mutable user state that persists across sessions. Superfile maintains these preferences in a user-specific configuration file rather than in the source code.
Configuration Storage
Pinned directories reside in ~/.superfile/config.json as an array of absolute paths within a pinned property. This location is user-specific and runtime-dependent, allowing each installation to maintain independent shortcut lists without modifying the application source or rebuilding the navigation structure.
Display and Interaction
During application startup, Superfile performs the following sequence:
- Loading: Reads and parses the JSON configuration file, extracting the
pinnedarray. - Rendering: Injects a dedicated "Pinned" section at the top of the sidebar, treating each directory path as a dynamic
NavLeaf-equivalent entry. - Persistence: Writes modifications back to
~/.superfile/config.jsonimmediately when users add or remove pins, ensuring state consistency without application restart.
This approach treats pinned directories as first-class navigation citizens while maintaining complete separation from the static documentation structure defined in navigation.ts.
Implementation Examples
Rendering the Complete Sidebar
The following React/TypeScript pattern demonstrates how Superfile composes the static navigation tree with dynamic pinned content:
import { navigation, flattenNav } from '@/lib/navigation';
function Sidebar() {
const staticItems = navigation.map(node =>
isGroup(node) ? (
<Collapsible key={node.label} label={node.label}>
{node.items.map(item => <Link key={item.slug} to={item.slug}>{item.label}</Link>)}
</Collapsible>
) : (
<Link key={node.slug} to={node.slug}>{node.label}</Link>
)
);
const pinned = usePinnedDirectories(); // reads ~/.superfile/config.json
const pinnedItems = pinned.map(dir => (
<Link key={dir} to={`pinned/${encodeURIComponent(dir)}`}>{path.basename(dir)}</Link>
));
return (
<nav>
<Section title="Pinned">{pinnedItems}</Section>
<Section title="Docs">{staticItems}</Section>
</nav>
);
}
Managing Pinned Directories
The following utility functions demonstrate the file system operations for modifying the pinned list:
import fs from 'fs';
import os from 'os';
import path from 'path';
const CONFIG_PATH = path.join(os.homedir(), '.superfile', 'config.json');
export function addPin(dir: string) {
const cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
cfg.pinned = Array.from(new Set([...(cfg.pinned || []), dir])); // avoid duplicates
fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
}
Sequential Navigation Implementation
To implement documentation pagination using the navigation utilities:
import { getPrevNext } from '@/lib/navigation';
function DocNav({ slug }: { slug: string }) {
const { prev, next } = getPrevNext(slug);
return (
<div className="doc-nav">
{prev && <Link to={prev.slug}>← {prev.label}</Link>}
{next && <Link to={next.slug}>{next.label} →</Link>}
</div>
);
}
Summary
- Static Architecture: The sidebar structure is defined declaratively in
website/src/lib/navigation.tsusing theNavLeafandNavGroupinterfaces, providing type-safe, immutable navigation hierarchies. - Dynamic Pinned Directories: User-specific shortcuts are stored in
~/.superfile/config.jsonand rendered as a distinct "Pinned" section, allowing runtime customization without source modification. - Navigation Utilities: Helper functions
flattenNav()andgetPrevNext()enable efficient tree traversal and sequential navigation generation for documentation workflows. - Separation of Concerns: The architecture cleanly separates immutable application structure from mutable user preferences, enabling independent updates to either component.
Frequently Asked Questions
How does Superfile differentiate between static documentation links and user-pinned directories?
Superfile maintains static documentation links in the TypeScript source file website/src/lib/navigation.ts, while user-pinned directories reside in the runtime configuration file ~/.superfile/config.json. The rendering layer combines both sources during component initialization, displaying pinned items in a dedicated section above the static navigation tree.
What file contains the sidebar navigation structure in Superfile?
The immutable sidebar structure is defined in website/src/lib/navigation.ts, which exports the navigation constant and related TypeScript interfaces (NavLeaf, NavGroup). This file serves as the single source of truth for static navigation elements across the application.
How does the getPrevNext function determine documentation pagination?
The getPrevNext(slug) function first calls flattenNav() to generate a one-dimensional array of navigation leaves in declaration order, then performs an index lookup on the provided slug. It returns objects containing the label and slug properties for the entries immediately preceding and following the current page, or null values when at the boundaries of the navigation sequence.
Can pinned directories be modified without restarting Superfile?
Yes, the pinned directory configuration is read from ~/.superfile/config.json at startup and written back immediately upon modification. Changes take effect in the sidebar without requiring application restart, as the UI layer references the current state of the configuration file when rendering the navigation components.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →