First Steps Tutorial

Learn the fundamentals by exploring the codebase and making your first changes

Overview

Learn the fundamentals by exploring the codebase and making your first changes

Now that you have Portfolio OS running, let's take a tour and make some changes to get comfortable with the codebase.

Note:

Time to Complete: 20-30 minutes

Understanding the Monorepo Structure

Portfolio OS uses a monorepo architecture with Turborepo and PNPM workspaces:

Tutorial 1: Explore the Site App

Let's start by understanding the main portfolio site.

1

Open the Site in Your Browser

Navigate to http://localhost:3000

You should see the portfolio homepage. Take a moment to explore:

  • Homepage with hero section
  • Projects page
  • Blog posts
  • Navigation menu
2

Locate the Homepage Code

Open apps/site/app/page.tsx in your editor.

This is the main homepage using Next.js App Router. Notice:

  • Server Component by default (no "use client" directive)
  • Async component that can fetch data
  • Imports from shared packages (@mindware-blog/ui, @mindware-blog/lib)
3

Make Your First Change

Let's customize the homepage. Find the hero section and update the text:

export default async function HomePage() {
  return (
    <div className="flex flex-col gap-8">
      <h1 className="text-4xl font-bold">
        Welcome to My Portfolio // [!code --]
        Hello! I'm Building Something Awesome // [!code ++]
      </h1>
      {/* Rest of the component */}
    </div>
  )
}

Save the file and watch the browser auto-refresh with your changes!

Note:

🎉 Nice work! You just made your first change. The browser updated automatically thanks to Next.js Fast Refresh.

Tutorial 2: Working with Shared Packages

One of the key benefits of the monorepo is code sharing. Let's see how packages work.

1

Explore the UI Package

Open packages/ui/src/button.tsx

This is a shared Button component used across all apps. It uses:

  • Tailwind CSS for styling
  • Radix UI primitives for accessibility
  • TypeScript for type safety
2

Use the Component in Site

The Button is already imported and used throughout the site. Check apps/site/app/page.tsx:

import { Button } from "@mindware-blog/ui"

export default function HomePage() {
  return (
    <div>
      <Button>Click Me</Button>
    </div>
  )
}

Notice the import path: @mindware-blog/ui maps to packages/ui

3

Modify a Shared Component

Let's add a new variant to the Button. Open packages/ui/src/button.tsx:

const buttonVariants = cva(
  "inline-flex items-center justify-center...",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground",
        destructive: "bg-destructive text-destructive-foreground",
        outline: "border border-input bg-background",
        // Add your custom variant // [!code ++]
        custom: "bg-purple-600 text-white hover:bg-purple-700", // [!code ++]
      },
    },
  }
)

Now use it in the site:

<Button variant="custom">Custom Style</Button>

Note:

Monorepo Magic: Changes to packages/ui are immediately available in all apps without publishing to npm!

Tutorial 3: Understanding Data Flow

Let's explore how Portfolio OS fetches and displays blog posts from Hashnode.

1

Examine the Blog Page

Open apps/site/app/blog/page.tsx

This server component:

  1. Fetches posts from Hashnode using GraphQL
  2. Optionally caches results in Redis
  3. Renders the post list
2

Explore the Hashnode Client

Open packages/hashnode/src/client.ts

This package encapsulates all Hashnode API interactions:

export async function getAllPosts() {
  const response = await fetch(HASHNODE_API_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: GET_ALL_POSTS_QUERY }),
  })
  return response.json()
}
3

Check the Caching Layer

Open apps/site/lib/cache.ts (if it exists)

Portfolio OS uses Redis to cache blog posts for better performance:

  • Cache key: blog:posts:all
  • TTL: 3600 seconds (1 hour)
  • Automatic invalidation on new posts

Tutorial 4: Working with the Dashboard

The dashboard app provides admin functionality for content management.

1

Open the Dashboard

Navigate to http://localhost:3001

Explore the dashboard features:

  • Content management
  • Analytics
  • Media library
2

Understand the Database

Open apps/dashboard/prisma/schema.prisma

This defines the database schema using Prisma:

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String
  published Boolean  @default(false)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}
3

Query the Database

Open apps/dashboard/lib/db.ts to see how data is queried:

import { prisma } from "@mindware-blog/db"

export async function getPosts() {
  return await prisma.post.findMany({
    where: { published: true },
    orderBy: { createdAt: "desc" },
  })
}

Common Development Tasks

Now that you understand the basics, here are common tasks you'll perform:

Running Commands

# Run all apps
pnpm dev

# Run specific app
pnpm dev --filter=@mindware-blog/site
pnpm dev --filter=@mindware-blog/dashboard

# Run multiple specific apps
pnpm dev --filter=@mindware-blog/site --filter=@mindware-blog/dashboard

Adding a New Package

# Create new package directory
mkdir packages/my-new-package
cd packages/my-new-package

# Initialize package
pnpm init

# Add to workspace (automatically detected)
# Add dependencies
pnpm add some-dependency

# Use in app
# In apps/site/package.json, add:
# "@mindware-blog/my-new-package": "workspace:*"

Database Migrations

# Create a migration
cd apps/dashboard
pnpm prisma migrate dev --name add_new_field

# Apply migrations
pnpm prisma migrate deploy

# Open Prisma Studio to browse data
pnpm prisma studio

Understanding Turborepo

Portfolio OS uses Turborepo for build orchestration:

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Key Concepts:

  • ^build: Build dependencies first
  • outputs: Cache these directories
  • persistent: Keep dev servers running

Next Steps

You're now familiar with the basics! Here's what to explore next:

Tips for Success

Note:

Best Practices:

  1. Use TypeScript strictly - The codebase is fully typed
  2. Follow the monorepo conventions - Keep packages focused and composable
  3. Leverage shared packages - Don't duplicate code between apps
  4. Write tests - Especially for shared packages used across apps
  5. Use Turbo caching - Builds and tests are cached for speed

Getting Help

Need assistance?

  • Documentation: You're in the right place! Explore the sidebar.
  • Troubleshooting: Check Common Issues
  • GitHub Issues: Open an issue for bugs or feature requests
  • Developer Guide: See Architecture for deeper concepts

Note:

Ready for advanced features? Check out the Multi-Agent System for parallel development workflows.