Skip to content

Repository files navigation

damirkotoric.com

Design Engineer. I build with React, Next.js, TypeScript. See my work at https://damirkotoric.com

Tech Stack

  • Next.js 16 (App Router)
  • TypeScript
  • Tailwind CSS 4 (inline @theme config in globals.css, no tailwind.config file)
  • shadcn/ui
  • Motion (Framer Motion)
  • pnpm (pinned to 10.18.1 via corepack — npm and yarn won't work)

Development

pnpm dev

predev and prebuild hooks auto-regenerate image dimensions before every dev and build.

Images

All portfolio images live in public/images/portfolio/ as AVIF.

Converting new images

ffmpeg -i input.png -c:v libaom-av1 -crf 18 -still-picture 1 output.avif

CRF 18 (visually lossless) is the compression standard for this project. Lower CRF = higher quality/larger file, higher CRF = more compression/smaller file.

Image dimensions

src/lib/image-dimensions.ts is auto-generated by scripts/generate-image-dimensions.ts. Don't edit it manually. It runs automatically on dev and build, or manually via pnpm gen:images.

Without correct dimensions, grid images fall back to 600px width and render blurry.

Next.js Image quality

Portfolio images use quality={100} on the Next.js <Image> component since CRF 18 already handles compression. Apply this to any new portfolio image usage.

Blur placeholders

src/lib/blur-placeholders.ts contains base64 blur data for portfolio showcase images. These are manually maintained (no generation script).

AVIF metadata workaround

PixelatedCanvas (src/components/ui/pixelated-canvas.tsx) can't reliably read AVIF naturalWidth/naturalHeight from the browser. Pass explicit naturalWidth and naturalHeight props when using AVIF sources with this component.

Portfolio System

Portfolio projects are defined in src/lib/portfolio-data.tsx.

Image Block Layouts

  • full - Full-width image
  • grid-2 - Two-column grid
  • grid-3 - Three-column grid

Interactive Covers

Animated cover backgrounds are mapped in src/components/portfolio-cover.tsx:

  1. Create component (e.g., src/components/project-bg.tsx)
  2. Import and add to interactiveCovers map

Path Aliases

@/* maps to ./src/* (configured in tsconfig.json). Use @/components, @/lib, etc. for all imports.

About

Personal portfolio — built with Next.js, TypeScript, Tailwind, and shadcn/ui

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages