387 lines
11 KiB
Markdown
387 lines
11 KiB
Markdown
# Terminal Portfolio
|
||
|
||
An Arch Linux terminal-themed portfolio website with Hyprland-style TUI components, built with SvelteKit, Tailwind CSS, and Three.js.
|
||
|
||

|
||
|
||
## 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
|
||
<TerminalTUI
|
||
lines={lines}
|
||
title="~/directory"
|
||
interactive={true}
|
||
speed="normal"
|
||
onComplete={() => 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 |
|
||
|