# Sir Blob's Desktop A portfolio website that recreates my Arch Linux desktop (Hyprland, Quickshell bar, kitty terminals) in the browser. Built with SvelteKit 3, Svelte 5 runes and Tailwind CSS 4. ## Running `start` builds the site and serves it with Bun on `PORT` (default 3000), reading `.env` for the Discord variables. ```bash bun install bun run dev bun run build bun run start bun run check ``` ## How the desktop works - The top bar mirrors the blob-shell Quickshell bar: chai menu (app launcher), workspaces 1-9, clock, Discord status and theme picker. - Every page (`/about`, `/projects/hackathons`, ...) opens as a tiled window, so old resume links still work. - Terminals open next to it and tile with the Hyprland dwindle layout. - Desktop icons open a page, a terminal running a command, or an external link. - On small screens the focused window goes fullscreen and open windows are listed as tabs. ### Keybinds | Keys | Action | | --- | --- | | Alt + Enter | Open a kitty terminal | | Alt + Space | App launcher | | Alt + Q | Close focused window | | Alt + F | Fullscreen the page window | | Alt + J / K | Focus next / previous window | | Alt + 1-9 | Switch workspace | | Alt + T | Next theme | Alt stands in for Super, which browsers do not receive. ## Editing content Everything you would normally change lives in `content/`. No code changes needed. | File | Contents | | --- | --- | | `content/profile.json` | name (shown only on the portfolio page), bio, avatar, education, socials (also used by the links page), skills, interests | | `content/experience.json` | experience with highlights, tech, awards and links | | `content/leadership.json` | leadership roles | | `content/about.json` | hobbies, games, shows, movies | | `content/projects/opensource.json` | open source projects | | `content/projects/packages.json` | published packages | | `content/projects/hackathons.json` | hackathon projects, events and awards | | `content/projects/research.json` | research roles and projects | | `content/models.json` | 3D models (files go in `static/models/`) | | `content/desktop.json` | default theme, workspaces, desktop icons, startup command | | `content/blog.json` | blog name, tagline, posts per page | | `content/blog/*.md` | blog posts | ### Projects Every project in every category uses the same shape. Only `name`, `description`, `tags` and `links` are required. ```json { "name": "HushMap", "description": "What it does.", "image": "/hacks/hushmap.png", "tags": ["Svelte", "FastAPI"], "featured": true, "event": { "name": "Bitcamp 2026", "university": "University of Maryland", "location": "College Park, MD", "year": "2026" }, "awards": [{ "track": "Best UI/UX Hack", "place": "Winner" }], "demoMayBeOffline": false, "version": "2.2.0", "links": { "demo": "https://...", "code": "https://...", "devpost": "https://...", "package": "https://...", "article": "https://..." } } ``` Featured projects are listed first. ### Desktop icons Each icon in `content/desktop.json` has a `label`, an Iconify `icon` and one `open` action: ```json { "label": "about", "icon": "mdi:account", "open": { "page": "/about" } } { "label": "skills.sh", "icon": "mdi:script-text", "open": { "terminal": "skills" } } { "label": "github", "icon": "mdi:github", "open": { "url": "https://github.com/SirBlobby" } } ``` `{ "terminal": "" }` opens an empty terminal. ### Blog posts Add a markdown file to `content/blog/`. The file name is the URL slug. ```markdown --- title: My Post Title author: Sir Blob date: 2026-01-01 tags: meta, notes excerpt: One line summary for the list and the RSS feed. --- Post content in markdown. ``` The RSS feed is at `/blog/rss.xml`. ## Themes Themes live in `src/lib/theme/themes.ts` and use the same keys as a blomarchy `colors.toml`, so a theme can be copied over from the dotfiles. Each theme can set a `wallpaper` (from `static/wallpapers/`) and an `activeBorder` gradient. The default theme is set in `content/desktop.json`. Shipped themes: Flats (default), Retro 82, Tokyo Night, Catppuccin, Arch Linux, Gruvbox, Nord, Kanagawa, Wintry, Rose, Cerberus, Catppuccin Latte, Rose Pine Dawn. ## Terminal commands `help`, `whoami`, `fastfetch`, `skills`, `contact`, `email`, `experience`, `projects [category]`, `ls`, `cd `, `theme [name]`, `echo`, `cowsay`, `date`, `clear`, `exit`. Page names (`about`, `hackathons`, ...) and social names (`github`, `linkedin`, ...) also work as commands. Tab completes commands, pages after `cd`, themes after `theme` and categories after `projects`; when several match it lists them like bash. Up/Down walk history, Ctrl+L clears. Commands live in `src/lib/terminal/commands/`. ## Code layout | Path | Contents | | --- | --- | | `src/lib/content/` | typed loader for `content/` | | `src/lib/blog/` | markdown renderer, frontmatter, highlighting, dates | | `src/lib/theme/` | theme palettes, stylesheet generation, current theme state | | `src/lib/desktop/` | window manager, dwindle tiling, keybinds, desktop actions | | `src/lib/terminal/` | terminal output model and commands | | `src/lib/site/pages.ts` | page list used by the terminal and launcher | | `src/lib/components/shell/` | bar, workspaces, clock, theme menu, Discord status | | `src/lib/server/discord.ts` | Discord bot and presence lookup | | `src/lib/components/desktop/` | desktop, windows, icons, launcher | | `src/lib/components/terminal/` | kitty terminal | | `src/lib/components/ui/` | shared page pieces | | `src/routes/` | pages | ## Discord status The bar shows live Discord presence (status, avatar, guild tag, activities). A discord.js bot starts with the server (`src/hooks.server.ts`) and the bar polls `/api/discord` every 30 seconds. Copy `.env.example` to `.env` and fill in: | Variable | Value | | --- | --- | | `DISCORD_TOKEN` | bot token, with the Server Members and Presence intents enabled | | `DISCORD_USER_ID` | your user id | | `DISCORD_GUILD_ID` | a server both you and the bot are in | Variables are declared in `src/env.ts`. Without them the widget shows your profile name as offline. ## Analytics Umami is loaded in `src/app.html`.