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.
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
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)
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.
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
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
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.
Examine the Blog Page
Open apps/site/app/blog/page.tsx
This server component:
- Fetches posts from Hashnode using GraphQL
- Optionally caches results in Redis
- Renders the post list
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()
}
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.
Open the Dashboard
Navigate to http://localhost:3001
Explore the dashboard features:
- Content management
- Analytics
- Media library
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
}
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 firstoutputs: Cache these directoriespersistent: Keep dev servers running
Next Steps
You're now familiar with the basics! Here's what to explore next:
Architecture Deep Dive
Understand the system architecture and design patterns
Development Workflow
Learn the recommended development process
Automation Scripts
Discover powerful automation tools
Tips for Success
Note:
Best Practices:
- Use TypeScript strictly - The codebase is fully typed
- Follow the monorepo conventions - Keep packages focused and composable
- Leverage shared packages - Don't duplicate code between apps
- Write tests - Especially for shared packages used across apps
- 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.