# Contributing to Portfolio Thank you for your interest in contributing to this project! This guide will help you get started with development. ## Table of Contents - [Getting Started](#getting-started) - [Project Overview](#project-overview) - [Tech Stack](#tech-stack) - [Project Structure](#project-structure) - [Development Workflow](#development-workflow) - [Code Style & Standards](#code-style--standards) - [Testing](#testing) - [Commit Guidelines](#commit-guidelines) ## Getting Started ### Prerequisites - **Node.js** 18.x or higher - **npm** 9.x or higher - **Git** for version control ### Installation 1. **Clone the repository** ```bash git clone cd portfolio ``` 2. **Install dependencies** ```bash npm install ``` 3. **Set up environment variables** Create a `.env.local` file in the root directory with the required environment variables: ```bash # Supabase Configuration NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key # Optional: OpenAI (for image generation scripts) OPENAI_API_KEY=your_openai_api_key ``` 4. **Start the development server** ```bash npm run dev ``` The application will be available at `http://localhost:3000` ### Available Scripts | Command | Description | |---------|-------------| | `npm run dev` | Start development server with hot reload | | `npm run build` | Build production bundle | | `npm start` | Start production server (after build) | | `npm run lint` | Run ESLint with strict mode | | `npm test` | Run unit tests with Vitest | | `npm run test:coverage` | Run tests with coverage report | | `npm run build:images` | Optimize images using Sharp | | `npm run generate:images` | Generate blog images using OpenAI | | `npm run generate:images:dry` | Preview image generation without creating files | ## Project Overview This is a personal portfolio website for Damjan Savić, showcasing work as an AI & Automation Specialist. The site features: - **Multi-language support** - German, English, and Serbian with automatic language detection - **Progressive Web App** - Installable and offline-capable - **SEO optimized** - Structured data (Schema.org), sitemap generation - **Responsive Design** - Mobile-first approach with Tailwind CSS - **Blog System** - MDX-based content with frontmatter support - **Portfolio Gallery** - Dynamic project showcase with filtering - **Contact Form** - Integrated with Supabase backend ## Tech Stack ### Core Framework - **Next.js 15** - React framework with App Router - **React 19** - UI library with latest features - **TypeScript 5.5** - Type-safe development ### Styling & UI - **Tailwind CSS 3.4** - Utility-first CSS framework - **Framer Motion 11** - Animation library - **Lucide React** - Icon library - **Tailwind Merge** - Utility for merging Tailwind classes - **CVA (Class Variance Authority)** - Component variants management ### Content & Internationalization - **MDX** - Markdown + JSX for content pages - `@mdx-js/loader`, `@mdx-js/mdx`, `@mdx-js/react` - `@next/mdx`, `next-mdx-remote` - **next-intl 3.26** - Internationalization (i18n) - **gray-matter** - Frontmatter parsing ### Backend & Services - **Supabase** - Database, authentication, and backend services - `@supabase/supabase-js` - `@supabase/ssr` - **OpenAI 4.77** - AI integration for content generation ### Development Tools - **Vitest** - Unit testing framework - **ESLint 9** - Code linting with Next.js config - **PostCSS** - CSS processing - **Autoprefixer** - CSS vendor prefixes - **Sharp** - Image optimization ### Performance & Analytics - **web-vitals** - Performance metrics - **react-intersection-observer** - Lazy loading and scroll animations ## Project Structure ``` portfolio/ ├── public/ # Static assets (images, fonts, etc.) ├── scripts/ # Build and utility scripts │ ├── optimize-images.js # Image optimization │ └── generate-blog-images.mjs # AI-powered image generation ├── src/ │ ├── app/ # Next.js App Router │ │ ├── [locale]/ # Internationalized routes │ │ │ ├── about/ # About page │ │ │ ├── blog/ # Blog listing & posts │ │ │ ├── contact/ # Contact form │ │ │ ├── dashboard/ # Admin dashboard │ │ │ ├── imprint/ # Legal imprint │ │ │ ├── leistungen/ # Services page │ │ │ ├── login/ # Authentication │ │ │ ├── portfolio/ # Portfolio gallery & projects │ │ │ ├── privacy/ # Privacy policy │ │ │ ├── terms/ # Terms of service │ │ │ ├── layout.tsx # Locale-specific layout │ │ │ └── page.tsx # Homepage │ │ ├── globals.css # Global styles │ │ ├── layout.tsx # Root layout │ │ ├── not-found.tsx # 404 page │ │ ├── robots.ts # Robots.txt generation │ │ └── sitemap.ts # Sitemap generation │ ├── components/ # Reusable React components │ ├── components-vite/ # Legacy Vite components │ ├── data/ # Static data and content │ ├── hooks/ # Custom React hooks │ ├── i18n/ # Internationalization config │ ├── lib/ # Utility libraries and helpers │ ├── messages/ # Translation files (de, en, sr) │ ├── middleware.ts # Next.js middleware (i18n routing) │ ├── pages-vite/ # Legacy Vite pages │ ├── services/ # API and service integrations │ ├── styles/ # Additional styles │ ├── types/ # TypeScript type definitions │ └── utils/ # Helper functions ├── .env.local # Environment variables (not in git) ├── .eslintrc.json # ESLint configuration ├── docker-compose.yml # Docker Compose setup ├── Dockerfile # Docker container config ├── next.config.ts # Next.js configuration ├── package.json # Dependencies and scripts ├── postcss.config.js # PostCSS configuration ├── tailwind.config.js # Tailwind CSS configuration └── tsconfig.json # TypeScript configuration ``` ### Key Directories Explained - **`src/app/`** - Next.js App Router pages and layouts using the new file-based routing system - **`src/app/[locale]/`** - All pages are nested under locale for multi-language support (de, en, sr) - **`src/components/`** - Reusable UI components (buttons, cards, forms, navigation, etc.) - **`src/hooks/`** - Custom React hooks for shared logic - **`src/lib/`** - Utility libraries (Supabase client, helpers, etc.) - **`src/messages/`** - Translation JSON files for each language - **`src/services/`** - API integrations and external service wrappers - **`src/types/`** - TypeScript interfaces and type definitions - **`src/utils/`** - Helper functions and utilities - **`public/`** - Static files served directly (images, fonts, favicons) - **`scripts/`** - Build automation and utility scripts ## Development Workflow ### 1. Create a New Feature Branch ```bash git checkout -b feature/your-feature-name ``` ### 2. Make Your Changes - Follow the existing code patterns and structure - Use TypeScript for type safety - Write clean, readable code with appropriate comments - Test your changes locally ### 3. Test Your Changes ```bash # Run development server npm run dev # Run linter npm run lint # Run tests npm test ``` ### 4. Build for Production ```bash npm run build ``` Ensure the build completes without errors before submitting. ## Code Style & Standards ### ESLint & Code Linting This project uses ESLint to enforce code quality and consistency. The configuration extends Next.js recommended presets: **ESLint Configuration** (`.eslintrc.json`): ```json { "extends": [ "next/core-web-vitals", "next/typescript" ] } ``` **Key ESLint Rules:** - `next/core-web-vitals` - Enforces Next.js best practices and Core Web Vitals optimizations - `next/typescript` - TypeScript-specific rules for Next.js applications **Running the Linter:** ```bash # Run ESLint in strict mode (recommended before committing) npm run lint # The linter will check for: # - Code quality issues # - Next.js best practices violations # - TypeScript type errors # - Unused variables and imports # - Accessibility issues ``` **Important:** - Always run `npm run lint` before committing changes - Fix all linting errors - the project uses `--strict` mode - The linter runs automatically during the build process - ESLint errors will prevent successful production builds ### Code Formatting **General Formatting Guidelines:** - **Indentation:** 2 spaces (no tabs) - **Line Length:** Aim for 80-100 characters, hard limit at 120 - **Semicolons:** Required at the end of statements - **Quotes:** Single quotes for strings (except in JSX/TSX where double quotes are preferred) - **Trailing Commas:** Use trailing commas in multi-line objects and arrays **Example:** ```typescript // ✅ Good const user = { name: 'John Doe', email: 'john@example.com', role: 'admin', }; // ❌ Bad const user = { name: "John Doe", email: "john@example.com", role: "admin" } ``` ### TypeScript - Use TypeScript for all new files - Define proper types and interfaces - Avoid using `any` - use proper typing or `unknown` - Export types from a central `types/` directory when shared ### React Components - Use functional components with hooks - Follow the component structure: 1. Imports 2. Type definitions 3. Component definition 4. Helper functions (if needed) 5. Exports Example: ```typescript import { useState } from 'react'; import { Button } from '@/components/ui/Button'; interface MyComponentProps { title: string; onSubmit: () => void; } export function MyComponent({ title, onSubmit }: MyComponentProps) { const [isLoading, setIsLoading] = useState(false); const handleClick = async () => { setIsLoading(true); await onSubmit(); setIsLoading(false); }; return (

{title}

); } ``` ### Styling - Use Tailwind CSS utility classes - Use `cn()` utility from `tailwind-merge` to merge classes - Follow the mobile-first responsive design approach - Use CSS variables for theme colors (defined in `globals.css`) ### File Naming - Components: PascalCase (e.g., `MyComponent.tsx`) - Utilities: camelCase (e.g., `formatDate.ts`) - Pages: lowercase (e.g., `page.tsx`, `layout.tsx`) - Types: PascalCase with `.types.ts` suffix (e.g., `User.types.ts`) ### Import Organization ```typescript // 1. External dependencies import { useState } from 'react'; import { useTranslations } from 'next-intl'; // 2. Internal components and utilities import { Button } from '@/components/ui/Button'; import { formatDate } from '@/utils/date'; // 3. Types import type { User } from '@/types/User.types'; // 4. Styles (if any) import styles from './Component.module.css'; ``` ### Internationalization - All user-facing text must be internationalized - Use `useTranslations()` hook from `next-intl` - Add translation keys to all language files in `src/messages/` Example: ```typescript import { useTranslations } from 'next-intl'; export function WelcomeMessage() { const t = useTranslations('home'); return

{t('welcome')}

; } ``` ## Testing ### Unit Tests - Write tests for utility functions and complex logic - Use Vitest as the testing framework - Place test files next to the code they test with `.test.ts` or `.test.tsx` extension Example: ```typescript // formatDate.test.ts import { describe, it, expect } from 'vitest'; import { formatDate } from './formatDate'; describe('formatDate', () => { it('formats date correctly', () => { const date = new Date('2024-01-15'); expect(formatDate(date)).toBe('15.01.2024'); }); }); ``` ### Running Tests ```bash # Run tests in watch mode npm test # Run tests once with coverage npm run test:coverage ``` ## Commit Guidelines ### Commit Message Format ``` : ``` ### Types - `feat` - New feature - `fix` - Bug fix - `docs` - Documentation changes - `style` - Code style changes (formatting, etc.) - `refactor` - Code refactoring - `test` - Adding or updating tests - `chore` - Maintenance tasks ### Examples ```bash git commit -m "feat: add contact form validation" git commit -m "fix: resolve mobile navigation menu bug" git commit -m "docs: update README with deployment instructions" ``` ## Questions? If you have any questions or need help, please: - Check existing documentation - Review similar code in the codebase - Open an issue for discussion --- **Built with Next.js + TypeScript + Tailwind CSS**