tfish is a stunning, fully interactive terminal-based portfolio website that simulates a complete operating system experience. Built with React, TypeScript, and Vite, this template transforms your portfolio into an immersive desktop environment with a BIOS boot sequence, login screen, draggable icons, and a functional terminal.
https://iamovi.github.io/tfish/
![]() |
![]() |
![]() |
![]() |
- Node.js 18+ or Bun
- npm, yarn, or bun
# Clone the repository
git clone https://github.com/iamovi/tfish.git
cd tfish
# Install dependencies
npm install
# or
bun install
# Start development server
npm run dev
# or
bun dev
# Build for production
npm run build
# or
bun run buildThe app will be available at http://localhost:5173
Edit src/components/Terminal.tsx to update your details:
// Update the welcome message
const WELCOME_MESSAGE = `Hello, World! I'm [Your Name]
I'm a [Your Title/Role].
Type 'help' to see available commands.`;
// Update the about command
about: {
description: 'Learn about me',
action: () => (
<div className="my-4 space-y-4">
<div className="border border-border rounded-lg overflow-hidden w-64 bg-secondary/50 shadow-lg">
<img
src="YOUR_IMAGE_URL_HERE"
alt="Your Name"
className="w-full h-auto object-cover"
/>
</div>
<div className="font-mono leading-relaxed bg-secondary/30 p-4 border border-border rounded-lg">
<div className="text-terminal-cyan font-bold mb-2">β ABOUT ME β</div>
<p className="mb-4 text-foreground/90">
Your bio here...
</p>
</div>
</div>
),
},Update your technical skills in the skills command:
skills: {
description: 'View my technical skills',
action: () => `
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TECHNICAL SKILLS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Languages β
β βββββββββββββββββββββββββββββββββββββββββββββ β
β β’ Your Language 1 β
β β’ Your Language 2 β
β β
β Frameworks & Libraries β
β βββββββββββββββββββββββββββββββββββββββββ β
β β’ Your Framework 1 β
β β’ Your Framework 2 β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`,
},Update the projects command with your work:
projects: {
description: 'Browse my projects',
action: () => `
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FEATURED PROJECTS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 01. Your Project Name β
β ββββββββββββββββββββββββββββββββββ β
β Project description here β
β β github.com/yourusername/project β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`,
},Update your contact details:
contact: {
description: 'Get my contact information',
action: () => `
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CONTACT β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β π§ Email your.email@example.com β
β π GitHub github.com/yourusername β
β π¦ Twitter twitter.com/yourusername β
β π Website yourwebsite.com β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`,
},Change the terminal username in src/components/Terminal.tsx:
// Find these lines and replace 'ren' with your username
prompt: 'yourusername@ubuntu:~$',
prompt: 'C:\\Users\\yourusername>',
prompt: 'PS C:\\Users\\yourusername>',Update the login screen in src/components/LoginScreen.tsx:
<h1 className="text-3xl font-semibold text-white mb-2 drop-shadow-lg">
Your Name
</h1>Update the start menu profile in src/components/SocialLinks.tsx:
<div className="text-sm font-semibold text-white">Your Name</div>
<div className="text-[11px] text-white/50">Your Title</div>Replace public/frieren.jpg with your own image, or update the default in src/pages/Index.tsx:
const [wallpaper, setWallpaper] = useState<string | null>('/your-image.jpg');Customize icons in src/components/DesktopIcons.tsx:
const icons = [
{ icon: User, label: 'About Me', command: 'about', pos: { x: 20, y: 20 } },
{ icon: Folder, label: 'Projects', command: 'projects', pos: { x: 20, y: 120 } },
// Add or remove icons as needed
];Add new commands in src/components/Terminal.tsx:
const COMMANDS: Record<string, { description: string; action: () => string | React.ReactNode }> = {
// ... existing commands
yourcmd: {
description: 'Your command description',
action: () => 'Your command output',
},
};Don't forget to add it to the help menu!
Themes are defined in src/components/Terminal.tsx. Add your own:
case 'yourtheme':
return {
bg: '#000000', // Background color
text: '#ffffff', // Text color
prompt: 'user@host:~$', // Command prompt
header: 'Your Theme', // Window title
welcome: WELCOME_MESSAGE,
caret: '#ffffff' // Cursor color
};Then add it to the theme selector in src/components/SocialLinks.tsx:
const themes = [
// ... existing themes
{ name: 'Your Theme', color: '#000000', id: 'yourtheme' },
];npm run build
# Deploy the 'dist' folder to Vercelnpm run build
# Deploy the 'dist' folder to Netlifynpm run build
# Push the 'dist' folder to gh-pages branchContributions are welcome! Feel free to:
- Report bugs
- Suggest new features
- Submit pull requests
- Improve documentation
This project is open source and available under the MIT License.
Made with β€οΈ by Ovi ren, for developers
Star β this repo if you found it helpful!
Thanks for reading!




