- Update globals.css to use @import "tailwindcss" and @config - Remove incompatible plugins (tailwindcss-animate, @tailwindcss/forms) - Add @tailwindcss/postcss for v4 compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Portfolio - Damjan Savić
Personal portfolio website showcasing my work as an AI & Automation Specialist based in Germany.
Live: damjan-savic.com
Current Role
Process Automation Specialist @ Everlast Consulting GmbH (since Dec 2024)
- Developing AI agents with n8n and Zapier
- Building web scraping solutions
- Migration from Power Automate to n8n
Tech Stack
Frontend
- Next.js 15 - React framework with SSR & SSG
- React 19 - UI Framework with Suspense & Lazy Loading
- TypeScript - Type-safe development
- Tailwind CSS - Utility-first styling with custom design tokens
- Framer Motion - Animations & page transitions
Content & Internationalization
- MDX - Markdown + JSX for blog posts and project pages
- i18next - Multi-language support (German, English, Serbian)
- react-helmet-async - SEO meta tags & structured data
Backend & Services
- Supabase - Database & Authentication
- Google Analytics 4 - Privacy-compliant analytics with cookie consent
PWA & Performance
- Next.js Image Optimization - Automatic image optimization with AVIF/WebP
- Code Splitting - Automatic route-based code splitting
- Caching Strategies - Custom headers for static assets
Testing & Quality
- Vitest - Unit testing
- Testing Library - React component testing
- ESLint - Code linting
Features
- Multi-language support - DE/EN/SR with automatic language detection
- Progressive Web App - Installable, offline-capable
- SEO optimized - Structured data (Schema.org), sitemap generation
- Responsive Design - Mobile-first approach
- Cookie Consent - GDPR-compliant with granular category control
- Blog System - MDX-based with frontmatter support
- Portfolio Gallery - Dynamic project showcase with filtering
- Contact Form - Integrated with backend services
Pages
| Route | Description |
|---|---|
/ |
Homepage with Hero, Experience, Skills, Projects, FAQ |
/about |
Detailed profile, skills matrix, workflow, journey |
/portfolio |
Project gallery with category filters |
/portfolio/:slug |
Individual project detail pages |
/blog |
Blog post listing |
/blog/:slug |
Individual blog posts |
/contact |
Contact form & info |
/privacy |
Privacy policy |
/terms |
Terms of service |
/imprint |
Legal imprint |
Project Structure
src/
├── components/ # Reusable UI components
├── hooks/ # Custom React hooks
├── i18n/ # Translations (de, en, sr)
├── pages/ # Page components
│ ├── home/
│ ├── about/
│ ├── portfolio/
│ │ └── projects/ # MDX project files
│ ├── blog/
│ └── contact/
├── styles/ # Global styles
├── utils/ # Helper functions
├── routes.tsx # Route definitions
└── App.tsx # Root component
Environment Variables
The application requires several environment variables to function correctly. Create a .env file in the root directory based on .env.example:
Required Variables
NEXT_PUBLIC_SUPABASE_URL
- Purpose: Base URL for your Supabase project
- Format:
https://your-project-id.supabase.co - How to get: Navigate to your Supabase project settings → Settings → API → Project URL
- Example:
https://mxadgucxhmstlzsbgmoz.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY
- Purpose: Anonymous/public key for client-side Supabase authentication
- Format: Long alphanumeric string (JWT token)
- How to get: Navigate to your Supabase project settings → Settings → API → Project API keys →
anonpublic - Security: Safe to use in client-side code (public key)
NEXT_PUBLIC_GA_TRACKING_ID
- Purpose: Google Analytics 4 tracking ID for analytics
- Format:
G-XXXXXXXXXX - How to get: Create a GA4 property in Google Analytics → Admin → Data Streams → Web → Measurement ID
- Optional: Can be omitted if you don't want analytics tracking
NEXT_PUBLIC_SITE_URL
- Purpose: The public URL where your site is hosted (used for SEO, canonical URLs, and sitemap generation)
- Format:
https://your-domain.com(no trailing slash) - Examples:
- Production:
https://damjan-savic.com - Development:
http://localhost:3000
- Production:
- Note: Update this when deploying to production
Setup Instructions
-
Copy the example environment file:
cp .env.example .env -
Fill in your actual values in the
.envfile -
Restart your development server after changing environment variables
Important Notes
- All variables prefixed with
NEXT_PUBLIC_are exposed to the browser - Never commit your
.envfile to version control (it's in.gitignore) - For production deployment, set these variables in your hosting platform's environment settings
- The
.env.examplefile shows the required format and should be kept updated
Development
# Install dependencies
pnpm install
# Start dev server
pnpm run dev
# Build for production
pnpm run build
# Run tests
pnpm test
# Preview production build
pnpm run preview
<<<<<<< HEAD
Docker Deployment
The application includes Docker support for containerized deployment.
Prerequisites
- Docker
- Docker Compose
Environment Variables
Create a .env file with the following variables:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
NEXT_PUBLIC_GA_TRACKING_ID=your_ga_tracking_id
NEXT_PUBLIC_SITE_URL=your_site_url
Using Docker Compose (Recommended)
# Build and start the container
docker-compose up -d
# Stop the container
docker-compose down
# View logs
docker-compose logs -f
The application will be available at http://localhost:3003
Using Docker Directly
# Build the image
docker build -t portfolio-website .
# Run the container
docker run -p 3003:3000 \
-e NEXT_PUBLIC_SUPABASE_URL=your_supabase_url \
-e NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key \
-e NEXT_PUBLIC_GA_TRACKING_ID=your_ga_tracking_id \
-e NEXT_PUBLIC_SITE_URL=your_site_url \
portfolio-website
Container Details
- Port Mapping: 3003 (host) → 3000 (container)
- Base Image: Node 20 Alpine
- Package Manager: pnpm
- Health Check: Automated health checks every 30 seconds
- Restart Policy: unless-stopped
=======
Development Scripts
The project includes 11 utility scripts for automating development tasks. See scripts/README.md for full documentation.
Categories:
- Image Optimization - Responsive image generation with WebP support
- SEO & Performance - Sitemap generation, PageSpeed testing
- Internationalization - Translation file conversion (TS → JSON)
- Assets & Resources - Font downloads and self-hosting
- Icon Generation - PWA icon creation with placeholders
- Documentation - GitHub README and OG image templates
Quick Start:
npm run build:images # Optimize project images
node scripts/generate-sitemap.js # Generate sitemap
node scripts/pagespeed-check.js # Run performance tests
origin/master
Key Technologies Used
Languages: TypeScript, Python, MDX
AI & Automation: GPT-4 API, Claude API, Vapi Voice AI, n8n, Zapier
Frontend: React, Next.js, Tailwind CSS, Framer Motion, Lucide Icons
Backend: Supabase (PostgreSQL, Auth), WebSocket
Build Tools: Next.js, PostCSS
Testing: Vitest, Testing Library, JSDOM
DevOps: ESLint, Git, PWA/Service Workers, Vercel, Docker
Contact
- Email: info@damjan-savic.com
- Phone: +49 175 695 0979
- LinkedIn: linkedin.com/in/damjan-savic
Built with Next.js + TypeScript