Skip to content

iamovi/tfish

Repository files navigation

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.

Preview

https://iamovi.github.io/tfish/

Screenshots

i ii
iii iv

Installation

Prerequisites

  • Node.js 18+ or Bun
  • npm, yarn, or bun

Quick Start

# 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 build

The app will be available at http://localhost:5173

🎨 Customization Guide

1. Personal Information

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>
  ),
},

2. Skills

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                                         β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
`,
},

3. Projects

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                      β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
`,
},

4. Contact Information

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                              β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
`,
},

5. Username

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>',

6. Login Screen

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>

7. Start Menu

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>

8. Default Wallpaper

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');

9. Desktop Icons

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
];

10. Add Custom Commands

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!

🎭 Theme Customization

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' },
];

Deployment

Vercel

npm run build
# Deploy the 'dist' folder to Vercel

Netlify

npm run build
# Deploy the 'dist' folder to Netlify

GitHub Pages

npm run build
# Push the 'dist' folder to gh-pages branch

Contributing

Contributions are welcome! Feel free to:

  • Report bugs
  • Suggest new features
  • Submit pull requests
  • Improve documentation

License

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!