375 lines
11 KiB
Markdown
375 lines
11 KiB
Markdown
# 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 <repository-url>
|
|
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
|
|
|
|
### 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 (
|
|
<div>
|
|
<h2>{title}</h2>
|
|
<Button onClick={handleClick} disabled={isLoading}>
|
|
Submit
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
### 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 <h1>{t('welcome')}</h1>;
|
|
}
|
|
```
|
|
|
|
## 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
|
|
```
|
|
<type>: <subject>
|
|
|
|
<body>
|
|
```
|
|
|
|
### 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**
|