# Terminal Portfolio An Arch Linux terminal-themed portfolio website with Hyprland-style TUI components, built with SvelteKit, Tailwind CSS, and Three.js. ![Terminal Portfolio](./static/og-image.png) ## Features - 🖥️ **Hyprland-style TUI** - Terminal interface inspired by Textual Python TUI - 🎨 **Theme Support** - Arch Linux and Catppuccin (Mocha/Latte) themes - 🌓 **Dark/Light Mode** - Toggle between dark and light modes - ⌨️ **Keyboard Navigation** - Navigate with arrow keys or vim-style j/k - 🎮 **3D Model Viewer** - Interactive Three.js viewer for .glb models - ⚡ **Configurable Speed** - Per-page typing animation speed - 📱 **Responsive** - Works on desktop and mobile - 🎨 **Rich Text Formatting** - Colors, backgrounds, and text decorations ## Pages - **Home** (`/`) - Neofetch-style intro with navigation - **Portfolio** (`/portfolio`) - Skills, projects, and contact info - **Models** (`/models`) - 3D model gallery with interactive viewer - **Hackathons** (`/hackathons`) - Hackathon projects and achievements ## Configuration Everything in the site is configurable from `src/lib/config.ts`. This file is the single source of truth for UI, layout, TUI behavior, colors, and per-page settings. Edit it to personalize the website to your needs. ### Main Config Sections - `user`: Profile info (name, username, bio, social links) - `skills`, `projects`, `models`, `hackathons`: Content arrays shown in pages - `layout`: Sizes and page margins (navbar height, container width) - `breakpoints`: Responsive breakpoints (mobile/tablet/desktop) - `fonts`: Font stacks and weights - `colorPalette`: Terminal and UI colors (semantic and base colors) - `terminalButtons`: Terminal header buttons colors (close/minimize/maximize) - `terminalSettings`: Typing presets, delays, cursor visibility, prompt style - `tuiStyle`: Styling options for border, spacing, font sizes, buttons, etc. - `tuiText`: Labels, hints, prefixes, and text labels for interactive elements - `animations`: Animation durations and easing for UI interactions - `scrollbar`: Scrollbar appearance settings - `navbar`: Navbar sizes and theme button settings - `modelViewer`: 3D viewer camera, lighting, and text strings - `particles`: 3D background particles (count, opacity, motion) - `loadingScreen`: Loading text and colors - `keyboardShortcuts`: Map keyboard actions to keys - `effects`: Misc effects like selection background and backdrop blur - `pageMeta`: Per-route metadata (title, description, icon, keywords) ### Example: Key config snippets ```typescript // Toggle theme keys and other shortcuts export const keyboardShortcuts = { skip: ['y', 'Y'], // Skip typing animation toggleTheme: ['t', 'T'], // Toggle dark/light mode navigateUp: ['ArrowUp', 'k'], navigateDown: ['ArrowDown', 'j'], select: ['Enter'], }; // Terminal / typing export const terminalSettings = { baseTypeSpeed: 20, minTypeSpeed: 5, maxTypeSpeed: 50, startDelay: 300, lineDelay: 100, showCursor: true, promptStyle: 'full', icon: '🐧', scrollMargin: 80, }; // Color palette (Catppuccin Mocha by default) export const colorPalette = { red: '#f38ba8', green: '#a6e3a1', yellow: '#f9e2af', blue: '#89b4fa', magenta: '#cba6f7', cyan: '#94e2d5', white: '#cdd6f4', gray: '#6c7086', error: '#f38ba8', success: '#a6e3a1', }; // TUI styling example export const tuiStyle = { borderRadius: 8, borderWidth: 2, width: '95%', bodyPadding: '1rem 1.25rem 2rem 1.25rem', buttonPadding: '0.5rem 0.75rem', }; ``` ### How to customize - Change any color in `colorPalette` to affect both inline coloring and semantic tokens like `(&primary)`/`(&error)`. - Update `terminalSettings` to control typing speed, delays, and the TUI icon. - Modify `tuiStyle` to adjust spacing, rounded corners, and button sizes. - Use `keyboardShortcuts` to remap keys (e.g., toggle theme, skip animation). - Per-page speeds are controlled by `pageSpeedSettings` (preset or numeric multiplier). ### Where to look for types & utilities - `src/lib/components/tui/types.ts` — main TerminalLine types - `src/lib/components/tui/utils.ts` — parsing utilities and style helpers - `src/lib/stores/theme.ts` — theme store & `toggleMode()` If you change a value in `config.ts`, the UI should pick it up on next reload. Some values (fonts, CSS variables) may also require adjusting CSS variables or Tailwind config. ## Speed Presets | Preset | Effect | |--------|--------| | `instant` | No animation, appears immediately | | `fast` | 3x faster than normal | | `normal` | Default typing speed | | `slow` | 2x slower than normal | | `typewriter` | 3x slower, classic feel | ## Text Formatting Use inline formatting with the `(&specs)text(&)` syntax: ### Colors ```typescript // Basic colors '(&red)Red text(&)' '(&green)Green text(&)' '(&blue)Blue text(&)' '(&yellow)Yellow text(&)' '(&magenta)Magenta text(&)' '(&cyan)Cyan text(&)' '(&orange)Orange text(&)' '(&pink)Pink text(&)' '(&gray)Gray text(&)' '(&white)White text(&)' // Semantic colors (theme-aware) '(&primary)Primary color(&)' '(&accent)Accent color(&)' '(&muted)Muted text(&)' '(&error)Error text(&)' '(&success)Success text(&)' '(&warning)Warning text(&)' '(&info)Info text(&)' // Custom hex colors '(&#ff6b6b)Custom color(&)' ``` ### Background Colors Add `bg-` prefix to any color: ```typescript '(&bg-red)Red background(&)' '(&bg-blue,white)Blue bg with white text(&)' '(&bg-surface)Surface background(&)' '(&bg-#333333)Custom bg color(&)' ``` ### Text Styles ```typescript '(&bold)Bold text(&)' '(&italic)Italic text(&)' '(&dim)Dimmed text (60% opacity)(&)' '(&underline)Underlined text(&)' '(&strikethrough)Strikethrough text(&)' '(&strike)Strikethrough shorthand(&)' '(&overline)Overlined text(&)' ``` ### Combining Styles Combine multiple styles with commas: ```typescript '(&bold,red)Bold red text(&)' '(&italic,cyan,underline)Italic cyan underlined(&)' '(&bg-blue,white,bold)Bold white on blue(&)' '(&dim,strikethrough,gray)Dim gray strikethrough(&)' ``` ## Line Types ### Basic Lines ```typescript const lines: TerminalLine[] = [ { type: 'command', content: 'ls -la' }, // With prompt prefix { type: 'output', content: 'File listing...' }, // Muted text { type: 'error', content: 'Error message' }, // Red with ✗ prefix { type: 'success', content: 'Success!' }, // Green with ✓ prefix { type: 'info', content: 'Information' }, // Primary with › prefix { type: 'header', content: 'Section Title' }, // Bold with # icon { type: 'blank', content: '' }, // Empty line { type: 'divider', content: 'SECTION' }, // Horizontal divider ]; ``` ### Button (Full-width interactive) ```typescript { type: 'button', content: 'Click me', icon: 'mdi:github', // Iconify icon style: 'primary', // primary | accent | warning | error href: 'https://github.com', // URL to navigate to external: true, // Open in new tab (auto-detected for http/https) // OR action: () => doSomething(), // Custom action } ``` ### Link (Inline clickable text) ```typescript { type: 'link', content: 'Visit GitHub', icon: 'mdi:github', // Optional icon style: 'accent', // Styling href: 'https://github.com', external: true, // Open in new tab (auto-detected for http/https) } ``` ### Image ```typescript { type: 'image', content: 'Caption text', // Optional caption image: '/path/to/image.png', imageAlt: 'Alt text', imageWidth: 300, // Max width in pixels } ``` ### Card ```typescript { type: 'card', content: 'Card body text with (&bold)formatting(&) support', cardTitle: 'Card Title', // Optional header cardFooter: 'Footer text', // Optional footer icon: 'mdi:star', // Optional header icon image: '/path/to/image.png', // Optional card image style: 'primary', // Border accent color } ``` ### Progress Bar ```typescript { type: 'progress', content: 'Loading assets...', // Label above bar progress: 75, // 0-100 percentage progressLabel: '75%', // Custom label (defaults to percentage) style: 'accent', // Bar color } ``` ### Accordion ```typescript { type: 'accordion', content: '', accordionItems: [ { title: 'Section 1', content: 'Content for section 1 with (&cyan)colors(&)' }, { title: 'Section 2', content: 'Content for section 2' }, ], accordionOpen: true, // First item open by default style: 'primary', // Accent color } ``` ### Table ```typescript { type: 'table', content: 'Table Title', // Optional title tableHeaders: ['Name', 'Role', 'Status'], tableRows: [ ['Alice', 'Developer', '(&success)Active(&)'], ['Bob', 'Designer', '(&warning)Away(&)'], ], style: 'accent', // Header color } ``` ### Tooltip ```typescript { type: 'tooltip', content: 'Hover me', // Trigger text tooltipText: 'This is helpful information!', tooltipPosition: 'top', // top | bottom | left | right style: 'info', // Tooltip border color } ``` ## TUI Components ### TerminalTUI Main terminal component: ```svelte console.log('Done!')} /> ``` ### Component Structure ``` src/lib/components/ ├── TerminalTUI.svelte # Main terminal container └── tui/ ├── types.ts # TypeScript types ├── utils.ts # Parsing & styling utilities ├── TuiHeader.svelte # Top status bar ├── TuiBody.svelte # Scrollable content area ├── TuiFooter.svelte # Bottom status bar ├── TuiButton.svelte # Full-width button ├── TuiLink.svelte # Inline clickable link ├── TuiCard.svelte # Card with header/body/footer ├── TuiProgress.svelte # Animated progress bar ├── TuiAccordion.svelte # Collapsible sections ├── TuiTable.svelte # Data table with headers └── TuiTooltip.svelte # Hover tooltip ``` ## 3D Models Place `.glb` files in `/static/models/` and update the models page to display them. ## Tech Stack - **Framework**: SvelteKit 2.x with Svelte 5 runes - **Styling**: Tailwind CSS 4.x - **3D**: Three.js with GLTFLoader - **Icons**: @iconify/svelte - **Font**: JetBrains Mono ## Development ```bash # Install dependencies bun install # Start dev server bun run dev # Build for production bun run build # Preview production build bun run preview ``` ## Keyboard Shortcuts | Key | Action | |-----|--------| | `↑` / `k` | Navigate up | | `↓` / `j` | Navigate down | | `Enter` | Activate button | | `Y` | Skip typing animation | | `T` | Toggle dark/light mode |