Skip to content

jmartinn/portfolio

Repository files navigation

Personal Website

This is the source code for my personal website jmartinn.com. The site serves as a platform to showcase my work, share my thoughts through blog posts, and provide information about my professional journey.

Overview

This portfolio is built with modern web technologies and features a minimalist design focused on content and user experience. While the source code is available for reference, please note that the design, content, and assets are not licensed for reuse.

Built With

  • Next.js - React framework for production
  • TypeScript - Type-safe JavaScript
  • Tailwind CSS - Utility-first CSS framework
  • MDX - Markdown for the component era
  • Vercel - For deployment and analytics

Features

  • Responsive minimalist design
  • Blog with MDX support
  • Dynamic OG image generation
  • RSS feed
  • Sitemap generation
  • View counter for blog posts
  • Performance monitoring with Vercel Analytics and Speed Insights

Project Structure

portfolio/
β”œβ”€β”€ app/                # Next.js 13+ app directory
β”‚   β”œβ”€β”€ (api)/          # API routes (analytics, RSS, resume)
β”‚   β”œβ”€β”€ blog/           # Blog pages and post layouts
β”‚   β”œβ”€β”€ about/          # About page
β”‚   β”œβ”€β”€ uses/           # Uses page
β”‚   └── work/           # Work showcase page
β”œβ”€β”€ components/         # Reusable React components
β”‚   β”œβ”€β”€ blog/           # Blog-specific components
β”‚   β”œβ”€β”€ layout/         # Layout components (footer, sidebar)
β”‚   β”œβ”€β”€ mdx/            # MDX components
β”‚   └── ui/             # UI components (badge, toast, icons)
β”œβ”€β”€ content/            # MDX files for blog posts
β”œβ”€β”€ lib/                # Utility functions and database actions
β”‚   β”œβ”€β”€ config/         # Application configuration
β”‚   β”œβ”€β”€ db/             # Database operations
β”‚   β”œβ”€β”€ constants.ts    # Application constants
β”‚   β”œβ”€β”€ utils.ts        # Utility functions
β”‚   └── validation.ts   # Input validation
└── public/             # Static assets (fonts, images)

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js 18.x or higher
  • pnpm 8.x or higher (recommended package manager)
  • Git for version control

Getting Started

1. Clone the Repository

git clone https://github.com/jmartinn/portfolio.git
cd portfolio

2. Install Dependencies

pnpm install

3. Environment Setup

Copy the example environment file and configure it:

cp .env.example .env.local

Edit .env.local and fill in the required values. See Environment Variables section for details.

4. Run Development Server

pnpm dev

Open http://localhost:3000 to view your site.

5. Build for Production

pnpm build
pnpm start

Environment Variables

Required Services

Supabase (Resume Storage)

  1. Create account at supabase.com
  2. Create new project
  3. Create storage bucket named "resume"
  4. Upload your resume PDF as "main.pdf"
  5. Add to .env.local:
    NEXT_PUBLIC_SUPABASE_URL=your_project_url
    SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
    

Spotify API (Music Widget)

  1. Create app at Spotify Developer Dashboard
  2. Set redirect URI to http://localhost:3000/callback
  3. Follow OAuth2 Code Flow to get refresh token
  4. Generate auth token: echo -n "CLIENT_ID:CLIENT_SECRET" | base64
  5. Add to .env.local:
    SPOTIFY_CLIENT_ID=your_client_id
    SPOTIFY_REFRESH_TOKEN=your_refresh_token
    SPOTIFY_AUTH_TOKEN=your_base64_token
    

Vercel Postgres (View Tracking)

  1. Deploy to Vercel
  2. Add Postgres storage in project dashboard
  3. Run migration:
    CREATE TABLE views (
      slug TEXT PRIMARY KEY,
      count INTEGER NOT NULL DEFAULT 0
    );
  4. Environment variables added automatically by Vercel

Vercel KV (Token Cache)

  1. Deploy to Vercel
  2. Add KV storage in project dashboard
  3. Environment variables added automatically by Vercel

Adding Blog Posts

  1. Create a new .mdx file in the content/ directory:
touch content/my-new-post.mdx
  1. Add frontmatter and content:
---
title: "My New Post"
publishedAt: "2025-10-24"
summary: "A brief description of the post"
keywords: ["nextjs", "react", "typescript"]
---

Your content here with **markdown** and React components!
  1. The post will automatically appear in the blog listing

Available Scripts

pnpm dev       # Start development server
pnpm build     # Build for production
pnpm start     # Start production server
pnpm lint      # Run ESLint
pnpm format    # Format code with Prettier

Deployment

Deploy to Vercel (Recommended)

  1. Push code to GitHub
  2. Import project in Vercel
  3. Add environment variables in project settings
  4. Deploy!

Vercel will automatically:

  • Install dependencies
  • Run build
  • Deploy to CDN
  • Provide Postgres and KV storage

Tech Stack Details

  • Framework: Next.js 15 (App Router)
  • Language: TypeScript 5
  • Styling: Tailwind CSS 3
  • Content: MDX with custom components
  • Database: Vercel Postgres
  • Cache: Vercel KV (Redis)
  • Storage: Supabase
  • Deployment: Vercel
  • Analytics: Vercel Analytics + Speed Insights

Project Architecture

ISR (Incremental Static Regeneration)

Blog posts use ISR with 1-hour revalidation:

  • Posts are statically generated at build time
  • Regenerated at most once per hour
  • Provides optimal performance with fresh content

Caching Strategy

  • React Cache: Request deduplication for blog posts
  • Vercel KV: 59-minute TTL for Spotify tokens
  • ISR: 1-hour revalidation for blog content

API Routes

  • /api/track - Get currently playing Spotify track
  • /api/spotify/token - Refresh Spotify access token
  • /resume - Download resume PDF
  • /rss - RSS feed for blog
  • /og - Dynamic OpenGraph image generation

Contributing

This is a personal portfolio, but feel free to:

  • Report bugs via GitHub Issues
  • Suggest improvements
  • Use as reference for your own portfolio

License

The code is open source, but content and design are not licensed for reuse.

Contributors