All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Gemini blog draft generation (EN/TR, UI-managed prompts)
- Admin can generate blog drafts via Google Gemini from a topic/outline. Prompts are stored in
content/config/gemini-prompts.jsonand editable at/admin/blog-prompts. - Config:
lib/gemini-prompts.ts:getGeminiPrompts(),writeGeminiPrompts()(atomic write),getDefaultGeminiPrompts();lib/schemas/gemini-prompts.ts:GeminiPromptsConfig,generateBlogDraftInputSchema. - Actions:
lib/actions/gemini.ts:getDefaultGeminiPromptsAction(),updateGeminiPromptsAction(),generateBlogDraftAction(); all Gemini usage server-only. - Generation:
lib/gemini-generate.ts:generateBlogDraft()with@google/genai(modelgemini-2.0-flash),{{topic}}/{{context}}substitution, Zod-validated JSON output, date set server-side; timeout 30s, Turkish error messages. - Blog draft schema:
blogDraftSchemainlib/schemas/blog.tsfor generation output validation. - Admin Blog prompts page:
/admin/blog-promptswith two text areas (EN/TR prompts), Save, Reset to defaults; nav item "Blog prompts" in admin layout. - New post: "Generate with Gemini" section (create mode only): topic text area, Generate button; fills form for selected locale (EN or TR).
- Edit post: "Generate with Gemini" section: shared topic field, buttons "EN taslak", "TR taslak", "Her iki dil"; fills EN and/or TR panels; optional context from other locale.
- Locale support: EN only, TR only, or both; no requirement for both locales; existing add/remove locale unchanged.
- Env:
GEMINI_API_KEYin.env; documented in.env.examplefor other developers.
- Admin can generate blog drafts via Google Gemini from a topic/outline. Prompts are stored in
- Dependency:
@google/genai@^1.38.0 - Default prompts in
content/config/gemini-prompts.json; in-code defaults inlib/gemini-prompts.tswhen file missing - Topic max 2000 chars; prompt max 10k chars per locale (Zod in
lib/schemas/gemini-prompts.ts)
- Admin error handling (Phase 6)
app/admin/error.tsx: segment-level error boundary mirroring root; English copy; "Back to dashboard" link to/adminlib/api-responses.ts:badRequestFromZod(zodError)for 400 with joined Zod validation messages;serverErrorResponse(message?)for 500 with generic message- API route convention: use
badRequestFromZodon ZodsafeParsefailure; useserverErrorResponsefor unexpected errors (documented in JSDoc)
- Admin blog: single edit per locale pair
- Blog list shows one row per blog (group): EN slug, TR slug, primary title, date, tags; Edit opens a single edit page for both locales
lib/blog-groups.ts:getBlogGroups()(reciprocalalternateSlug= pair, else solo),getBlogGroupByPrimarySlug(primarySlug)lib/actions/blog.ts:updateBlogGroupAction(primarySlug, payload),deleteBlogGroupAction(primarySlug)(deletes both locale files)- Edit page at
/admin/blogs/[slug]/editloads group and rendersBlogGroupFormwith two panels (English, Türkçe); add/remove locale; save keepsalternateSlug/alternateLocalein sync - New post creates one locale and redirects to
/admin/blogs/[slug]/editso the other locale can be added on the same page
- Markdown editor for blog content
react-markdowndependency for previewcomponents/admin/markdown-editor.tsx: split view (textarea + live preview)BlogGroupFormusesMarkdownEditorfor EN and TR content fields
- Admin blogs list: sync
getBlogGroups()fromlib/blog-groups.ts;BlogListacceptsgroups: BlogGroup[] BlogGroupForm: two locale panels; optional "Remove English/TR version"; submit builds{ en?, tr? }and callsupdateBlogGroupAction- Edit route:
getBlogGroupByPrimarySlug(slug);not-foundwhen group missing - Dependencies:
react-markdown@10.1.0
- Admin panel (auth and layout): Protected admin area for content management
- NextAuth v5 (beta) with credentials provider; env:
AUTH_SECRET,ADMIN_EMAIL,ADMIN_PASSWORD - Login page at
/admin/login; unauthenticated users redirected to login - Protected routes under
/admin(route group(protected));/adminredirects to/admin/hero-summary - Admin layout with top nav: Hero & Summary, Resume, Certifications, Blogs; sign-out button
- Placeholder pages:
/admin/hero-summary,/admin/resume,/admin/certifications,/admin/blogs
- NextAuth v5 (beta) with credentials provider; env:
- Added
auth.ts(NextAuth config with Credentials provider),app/api/auth/[...nextauth]/route.ts - Added
app/admin/login/page.tsx,app/admin/(protected)/layout.tsx,app/admin/(protected)/page.tsx, placeholder admin pages - Added
.env.examplewithAUTH_SECRET,ADMIN_EMAIL,ADMIN_PASSWORD - Dependencies:
next-auth@5.0.0-beta.30,zod@^3.23 - Hero & Summary edit: Admin form at
/admin/hero-summaryto edit name, title, tagline, email, location, website, LinkedIn, GitHub, summary; submits via server action - Resume write layer:
writeResumeData()inlib/resume.ts(atomic write);lib/schemas/resume.ts(partial Zod schema);lib/actions/resume.ts(updateResumeActionwith deep-merge) - Resume section edit: Admin page at
/admin/resumewithResumeSectionForm: experience (add/remove entries, description bullets), education (add/remove), coreSkills (per-category bullet list); submits viaupdateResumeAction - Certifications edit: Admin page at
/admin/certificationswithCertificationsForm: list, add, edit, remove certifications; fields: name, version, issuer, issueDate, expirationDate, credentialId, credentialUrl, skills (one per line); submits viaupdateResumeAction
- Source URL Title Fetching: Automatic fetching and display of actual titles for source URLs in blog posts
- Replaces generic labels like "YouTube Video" or "YouTube Videosu" with actual video/page titles
- Supports YouTube videos (all URL formats: youtu.be, youtube.com/watch, youtube.com/embed)
- Supports regular web pages with title extraction
- Build-time processing script for batch updating all blog posts
- Batch processing with rate limiting (5 URLs at a time, 200ms delays)
- Error resilience - continues processing even if some URLs fail
- Cache file persistence for resume capability (
cache/source-url-metadata.json) --dry-runflag for safe testing without modifying files--resumeflag to continue from cached metadata
-
New Utilities:
lib/source-url-metadata.ts: URL validation, type detection, YouTube normalization, metadata fetchinglib/source-url-processor.ts: MDX content parsing and source URL replacementscripts/process-source-urls.ts: Build-time script for processing all blog posts
-
New NPM Scripts:
pnpm process-source-urls- Process all blog posts and update source URLspnpm process-source-urls:dry-run- Test processing without modifying files
-
Features:
- YouTube oEmbed API integration with 10-second timeout
- Web page title scraping with regex (falls back to Open Graph og:title)
- Redirect handling (up to 3 redirects)
- In-memory caching for build-time efficiency
- Generic label detection (case-insensitive)
- Markdown character escaping for safe title replacement
- Preserves frontmatter and formatting during content updates
- Blog List Page: Fixed locale filter dropdown font inconsistency
- Removed conflicting
font-sansclass from locale filter select element - Enhanced global CSS rules to ensure Solitreo font applies to all select and option elements
- Added specific CSS selectors for all select states (focus, hover, active)
- Added specific CSS selectors for all option states (checked, hover, focus)
- Dropdown options ("All Languages", "English", "Turkish") now use Solitreo font consistently
- Font now matches other page elements (headings, search bar placeholder)
- Removed conflicting
- Updated
components/blog/locale-filter.tsx: Removedfont-sansclass from select element - Updated
app/globals.css: Enhanced select and option CSS rules with state-specific selectors - CSS rules use
!importantflag to override browser default styling - Font consistency maintained across all dropdown states and interactions
- Reverted Handwriting Border Design: Reverted handwriting border system to clean, professional borders
- Removed complex CSS mask operations (~400+ lines of handwriting border CSS)
- Replaced handwriting borders with standard Tailwind border utilities
- Improved performance by removing complex mask calculations
- Enhanced maintainability with simpler, standard CSS patterns
- Better browser compatibility (universal support vs. mask-image requirement)
- Cleaner, more professional visual appearance
-
Removed Handwriting Border CSS System:
- Removed CSS custom properties:
--handwriting-border-horizontal,--handwriting-border-vertical,--handwriting-underline - Removed all handwriting border CSS classes (
.handwriting-border-all,.handwriting-border-t/b/l/r/x/y,.handwriting-border,.handwriting-underline, etc.) - Removed handwriting border pseudo-elements from
.notebook-panel::after,.loose-leaf-card::after,.pencil-divider::before - Updated
.notebook-panelto useborder border-notebook-divider - Updated
.loose-leaf-cardto useborder border-notebook-divider - Updated
.pencil-dividerto useborder-t border-notebook-divider
- Removed CSS custom properties:
-
Updated Components (22+ files):
- Layout:
header.tsx,mobile-menu.tsx,navigation.tsx,footer.tsx - Blog:
mdx-components.tsx,blog-list-client.tsx,back-button.tsx,locale-filter.tsx,search-bar.tsx,tag-filter.tsx,tag-list.tsx - Home:
personal-hero.tsx,certifications-section.tsx,latest-blogs-section.tsx,featured-posts.tsx,bottom-navigation.tsx - Resume:
experience-item.tsx,skills-grid.tsx - UI:
theme-toggle.tsx,glassy-button.tsx - All components now use standard Tailwind border classes (
border,border-t,border-b,border-l,border-accent, etc.) - Maintained existing hover/active states and accessibility features
- Layout:
- Reduced CSS file size by ~400 lines
- Improved rendering performance (no complex mask operations)
- Faster page load (less CSS to parse)
- Better compatibility with Next.js build optimizations
- Universal browser support (CSS borders supported since CSS 1.0)
- Consistent rendering across all modern browsers
- No fallback handling needed
- Works perfectly in all browsers (including IE11+)
- Handwriting Border Color Inconsistency: Fixed borders displaying both grey and black colors
- Removed
background-imagedeclarations that rendered SVG patterns with hardcoded black strokes - Implemented two-layer mask system: gradient masks for border shape + SVG pattern masks for handwriting texture
- All borders now display consistent grey color controlled by
--notebook-dividerCSS variable - Borders respect theme colors: light grey (
#E5E0D6) in light mode, medium grey (#6B7280) in dark mode - Handwriting pattern texture preserved while eliminating black color artifacts
- Fixed duplicate
.notebook-panel::beforedefinition (code quality improvement)
- Removed
- Updated
app/globals.csshandwriting border implementations:.notebook-panel::after: Removedbackground-image, combined gradient + SVG pattern masks.loose-leaf-card::after: Removedbackground-image, combined gradient + SVG pattern masks.handwriting-border::before: Removedbackground-image, combined gradient + SVG pattern masks.handwriting-border-all::before/::after: Removedbackground-image, usemask-imageonly- All borders now use
mask-imagewith SVG patterns for shape,background-colorfor color - Two-layer mask system: gradient masks define border area, SVG patterns add handwriting texture
- Combined masks using
mask-composite: addfor proper rendering
- Removed duplicate
.notebook-panel::beforedefinition (paper texture) - Verified all directional border classes (
.handwriting-border-t/b/l/r/x/y) already correct - No component changes required - CSS-only fix
- Blog Links Visibility: Fixed invisible URL links in blog posts
- Updated
.handwriting-underlineCSS class to use explicitaccent-cyancolor instead ofcurrentColor - Added explicit
colorproperty as fallback to ensure text visibility - Links now display correctly in both light and dark modes
- Handwriting underline effect preserved while ensuring text remains visible
- Fixes issue where only underline was visible but link text was invisible
- Updated
- Modified
app/globals.css.handwriting-underlineclass:- Changed
background-color: currentColortobackground-color: rgb(var(--color-accent-cyan)) - Added
color: rgb(var(--color-accent-cyan))as explicit fallback - Maintains all existing mask properties for handwriting underline effect
- Changed
- No component changes required - MDX components already compatible
- Blog Content: Added new Turkish blog post "OpenTelemetry ve Grafana Labs: 2026 Vizyonu ve Yeni Teknolojiler"
- Comprehensive article covering OpenTelemetry's 2026 vision and Grafana Labs' strategic direction
- Topics include CNCF graduation goals, Declarative Configuration, Prometheus compatibility, AIOps integration, and fleet management
- Includes three dashboard images: APM dashboard, OpenTelemetry Collector monitoring dashboard, and Linux monitoring dashboard
- Images stored locally in
public/images/blog/directory for optimal performance - Blog post date: 2026-01-17
- Tags: OpenTelemetry, Grafana, Observability, DevOps, Monitoring, SRE
- Locale: Turkish (tr)
- Created
content/blog/opentelemetry-ve-grafana-labs-2026-vizyonu-ve-yeni-teknolojiler.mdxwith proper MDX frontmatter - Added three dashboard images to
public/images/blog/:otel-demo-apm-dashboard.png- APM dashboard for OpenTelemetry Demootel-demo-collector-monitoring-dashboard.png- Collector monitoring dashboardotel-demo-linux-dashboard.png- Linux system monitoring dashboard
- Images properly referenced using local paths (
/images/blog/...) instead of external URLs - Blog post follows project MDX structure and formatting conventions
- Handwriting Border System: Implemented hand-drawn/sketchy border system for organic, notebook-style aesthetic
- Created SVG patterns for horizontal, vertical, and underline borders with seamless tiling
- Implemented CSS classes using pseudo-elements to support
border-radius(unlikeborder-image) - Added
.handwriting-border-allclass for all borders - Added directional variants:
.handwriting-border-t,.handwriting-border-b,.handwriting-border-l,.handwriting-border-r,.handwriting-border-x,.handwriting-border-y - Added
.handwriting-underlineclass for text decorations - Uses CSS
mask-imagefor proper color inheritance from CSS variables - Follows existing
.paper-texture::beforepattern for consistency - Optimized SVG patterns to < 500 bytes each for performance
- Added CSS custom properties in
:rootfor handwriting border SVG patterns:--handwriting-border-horizontal: Hand-drawn wavy line pattern (50px width) for top/bottom borders--handwriting-border-vertical: Hand-drawn wavy line pattern (50px height) for left/right borders--handwriting-underline: Hand-drawn underline pattern (35px width) for text decorations
- Implemented handwriting border classes in
app/globals.css:- All classes use pseudo-elements (
::before,::after) positioned absolutely - Pseudo-elements respect parent
border-radiusautomatically - Uses
mask-imagewithbackground-colorfor color control - Proper z-index stacking: border (0) < texture (0) < content (1)
- Includes fallback support for older browsers
- All classes use pseudo-elements (
- Foundation ready for Phase 2: Applying handwriting borders to components (cards, panels, dividers, etc.)
- Blog Detail Page: Removed outer border from Related Posts section and restored borders on individual post cards
- Removed
pencil-dividerclass from Related Posts section container to eliminate outer border - Removed
border-0class from Related Posts post cards to restore defaultloose-leaf-cardborders - Related Posts section now has a cleaner appearance without outer border
- Individual post cards now display with borders as originally intended
- Preserves all other styling including rounded corners, shadows, hover effects, paper texture, and spacing
- Removed
- Updated
components/blog/related-posts.tsx: Removedpencil-dividerfrom section element andborder-0from post cards - Post cards now use default
loose-leaf-cardborder behavior (as originally designed) - Section spacing (
mt-16 pt-12) preserved - No changes to global CSS classes - isolated fix to Related Posts component only
- Minimal code change - two class removals for targeted styling adjustments
- Documentation: Updated Next.js 15+ project rules to reflect actual Next.js 15 behavior
- Updated
nextjs-rules.mdcto correctly document Promise-typed params for dynamic routes (Next.js 15+ requirement) - Updated rules to allow
generateMetadatafor dynamic routes (required for per-route SEO) - Clarified distinction between static routes (plain object params) and dynamic routes (Promise-typed params)
- Updated code review command documentation to reflect correct Next.js 15 patterns
- All existing code was already compliant with Next.js 15 best practices
- Updated
- Updated
.cursor/rules/nextjs-rules.mdc: Corrected metadata and params handling documentation - Updated
.cursor/commands/review-changes.md: Aligned review criteria with Next.js 15 actual behavior - No code changes required - existing implementation was already correct
- Rules now accurately reflect Next.js 15.1.0 requirements
- Blog Detail Page: Removed unwanted border from Related Posts section cards
- Added
border-0class to Related Posts cards to override defaultloose-leaf-cardborder - Related Posts cards now display without visible borders while maintaining all other styling
- All other components using
loose-leaf-cardretain their borders as intended - Preserves rounded corners, shadows, hover effects, paper texture, and accessibility features
- Added
- Updated
components/blog/related-posts.tsx: Addedborder-0Tailwind utility class to card className - Border removal uses Tailwind utility override pattern (maintains design system integrity)
- No changes to global CSS classes - isolated fix to Related Posts component only
- All other
loose-leaf-cardinstances across the site remain unaffected - Minimal code change - single class addition for targeted border removal
- Blog Detail Page: Fixed background color mismatch between blog content area and outer page background
- Added
bg-backgroundclass to blog content div to ensure unified background color - Blog content area now matches outer page background in both light and dark themes
- Maintains seamless visual appearance across the entire blog detail page
- Paper texture overlay continues to function correctly above the background
- Added
- Updated
app/blog/[slug]/page.tsx: Addedbg-backgroundclass to blog content div className - Background color uses same CSS variable (
--color-background) as outer page background - No visual regressions - typography, spacing, and paper texture effects preserved
- Minimal code change - single class addition for improved visual consistency
- Typography: Replaced Charm font family with Solitreo font family
- Implemented unified typography using Solitreo-Regular.ttf (400 weight only)
- All text elements (headings, body, code) now use Solitreo font for consistent typographic identity
- Updated
app/layout.tsxto use Solitreo font withnext/font/local - Updated Tailwind configuration to use
--font-solitreoCSS variable for all font families (sans, serif, mono) - Bold text uses synthetic bold (browser-generated) since only Regular weight is available
- Font file is preloaded for optimal performance
- License: SIL Open Font License (OFL) - compliant for commercial use
- Updated
app/layout.tsx: Replaced Charm font with Solitreo font usinglocalFontfromnext/font/local - Updated
tailwind.config.ts: Changed all font families to usevar(--font-solitreo)with Georgia fallback - Font configuration uses single
localFontinstance with Regular weight only (400) - Browser generates synthetic bold for
font-weight: 700(no separate Bold font file available) - All existing Tailwind font utilities (
font-sans,font-serif,font-mono) now use Solitreo font - No hardcoded font-family values found in codebase - all components use Tailwind utilities
- TypeScript type checking passed
- No breaking changes - all existing components work with new font configuration
- Typography: Replaced all Google Fonts (Inter, Playfair Display, JetBrains Mono) with local Charm font family
- Implemented unified typography using Charm-Regular.ttf (400 weight) and Charm-Bold.ttf (700 weight)
- All text elements (headings, body, code) now use Charm font for consistent typographic identity
- Updated
app/layout.tsxto usenext/font/localwith local font files - Updated Tailwind configuration to use
--font-charmCSS variable for all font families (sans, serif, mono) - Removed Google Fonts dependencies - no external font requests
- Font files are preloaded for optimal performance
- License: SIL Open Font License (OFL) - compliant for commercial use
- Updated
app/layout.tsx: Replaced Google Font imports withlocalFontfromnext/font/local - Updated
tailwind.config.ts: Changed all font families to usevar(--font-charm)with Georgia fallback - Font configuration uses single
localFontinstance with array of src objects for multiple weights - Browser automatically selects correct font weight (Regular 400 or Bold 700) based on CSS
font-weightproperty - All existing Tailwind font utilities (
font-sans,font-serif,font-mono) now use Charm font - No hardcoded font-family values found in codebase - all components use Tailwind utilities
- TypeScript type checking passed
- No breaking changes - all existing components work with new font configuration
- UI Refinement: Removed borders from all heading elements (h1-h6) for a cleaner, more minimal appearance
- Removed
pencil-dividerclass and border utilities from ResumeSection h2 headings - Removed
pencil-dividerclass and border utilities from MDX h2 headings in blog posts - Refactored ResumeSection to use
cn()utility for className composition (project pattern consistency) - Removed padding-bottom classes (
pb-3,pb-2) that were only used for border spacing - Preserved all typography, spacing, and responsive styling
- Non-heading elements (dividers, sections, hr) retain
pencil-dividerclass for decorative purposes
- Removed
- Updated
components/resume/resume-section.tsxto remove borders and usecn()utility - Updated
components/blog/mdx-components.tsxto remove borders from h2 component - All changes maintain responsive behavior, typography, and theme compatibility
- Code quality checks passed (TypeScript, ESLint, Prettier)
- Persistent Badge Borders: Added explicit Tailwind utility overrides to completely remove any inherited badge styles from location and date elements
- Added
bg-transparent border-0 rounded-none p-0 m-0utilities to all location/date elements in Experience Item component - Used
cn()utility for proper className composition following project patterns - Ensures no borders, backgrounds, padding, or margins are applied regardless of CSS specificity or inheritance
- Verified no conflicting global CSS rules or Tailwind plugin conflicts
- Added
- Updated
components/resume/experience-item.tsxwith explicit style overrides using Tailwind utilities - Investigated and verified no global CSS rules, Tailwind typography plugin, or parent component styles causing conflicts
- All changes maintain responsive behavior, text styling, and theme compatibility
- Code quality checks passed (TypeScript, ESLint, Prettier)
- UI Refinement: Removed badge frames from title-related elements across the website for a cleaner, more minimal appearance
- Removed location and date badge frames from Professional Experience section (mobile and desktop views)
- Removed summary opening words badge frame from Personal Hero section
- Preserved all text content, styling, animations, and responsive behavior
- Maintained text readability and proper spacing without background frames
- Updated
components/resume/experience-item.tsxto remove badge styling from location and date metadata - Updated
components/home/personal-hero.tsxto remove badge frame from summary opening words - All changes maintain responsive behavior and theme compatibility
- Code quality checks passed (TypeScript, ESLint, Prettier)
- TypeScript version of blog date update script (
scripts/update-blog-dates.ts) update-blog-datesnpm script command for easy blog date management- TypeScript type definitions for blog post file operations
- Converted blog date update script from JavaScript to TypeScript for better type safety
- Added tsx as dev dependency for running TypeScript scripts directly
- Updated all blog post dates to be distributed one per day starting from 2026-01-14 going backwards
- Script now uses proper TypeScript types and interfaces
- Improved type safety for file operations and date handling
- Script automatically sorts posts by creation time (newest first) and assigns dates accordingly
- Enhanced notebook aesthetic with improved paper texture (increased opacity, enhanced grain pattern)
- Enhanced notebook binding (increased width to 7px, added gradient and shadow)
- Journal-like elements: enhanced pencil dividers with gradient overlay, page edge shadows
- Typography utility classes:
.text-heading,.text-body,.text-codefor consistent font usage - Distinct component styles: refined notebook-panel, loose-leaf-card, and button styles with paper texture overlays
- Design System Refinement: Replaced gold/brass accent color with grey metallic (#6B7280) for sophisticated look
- Shadow System: Removed all accent-colored shadows, using only paper shadows for depth
- Typography Standardization: All headings (h1-h6) use serif font (Playfair Display), all body text uses sans-serif (Inter)
- Padding Standardization: Standardized section title padding (mb-6), container padding (px-4 sm:px-6 lg:px-8), and card padding (p-6 md:p-8)
- Component Styles:
- Notebook panels: Flat style with paper texture, no rotation
- Loose-leaf cards: Enhanced with rotation effects (0.5deg default, 1deg on hover) and paper texture
- Buttons: Added paper texture overlay and enhanced press effects (scale 0.98 hover, 0.96 active)
- Paper Texture: Increased opacity (0.03→0.05 for light, 0.02→0.03 for dark) and enhanced grain pattern
- Notebook Binding: Updated to match grey metallic accent color, increased width to 7px with gradient and shadow
- Removed all glassmorphism styling remnants (glass-panel, glass-card classes)
- Fixed asymmetric padding in section titles and cards
- Fixed font inconsistency across components
- Fixed linting errors: escaped apostrophes in JSX, added eslint-disable comment for MDX components
- Updated 20+ components to use standardized typography and padding
- Enhanced CSS with distinct styles for panels, cards, and buttons
- All components now use consistent notebook aesthetic with paper texture overlays
- Verified no glassmorphism styling remains in codebase
- Fixed bullet list text wrapping under dots in blog reading page by changing from
list-insidetolist-outside - Fixed title text alignment: all headings (h1-h4) are now explicitly left-aligned instead of justified
- Improved list indentation: replaced
ml-4withpl-6for proper spacing withlist-outside - Added
prose-headings:text-leftto prose container to ensure headings remain left-aligned
- Updated
ulandolMDX components to uselist-outsidefor better text wrapping behavior - All heading components (h1, h2, h3, h4) now explicitly include
text-leftclass - List items maintain proper indentation without text wrapping under bullet points
- Multi-language support for blog posts with Turkish (tr) and English (en) locales
- Language switcher component for bilingual blog posts with visual emphasis for preferred locale
- Locale detection utility using Next.js 15 headers() API to detect user's preferred language from browser
- Post prioritization system that shows user's preferred locale first in blog listings
- Locale filtering dropdown on blog list page with "All Languages", "English", "Turkish" options
- Locale badges (EN/TR) on blog post cards for quick language identification
- Extended BlogPost type with locale, alternateLocale, and alternateSlug fields
- Helper functions: getPostsByLocale() and prioritizePostsByLocale() for locale-based filtering and sorting
- SEO enhancements: hreflang tags in metadata and JSON-LD translations array for bilingual posts
- Locale-aware date formatting (tr-TR for Turkish, en-US for English)
- Localized reading time text ("min read" / "dakika okuma")
- Blog post frontmatter now supports locale field (defaults to 'en' for backward compatibility)
- Blog list page prioritizes posts in user's preferred locale
- Related posts prioritize user's preferred locale while maintaining tag-based relevance
- Blog post pages include dynamic HTML lang attribute based on post locale
- Date formatting respects post locale (Turkish vs English formats)
- JSON-LD structured data includes inLanguage property and translations array for bilingual posts
- Server-side locale detection using Next.js 15 headers() API
- Smart prioritization algorithm groups bilingual posts and maintains date sorting
- All locale-related functions are async-compatible with Next.js 15 App Router
- Backward compatible: existing posts without locale field default to 'en'
- Updated ProfileImage component to use PNG format for theme-specific images (profile_light.png and profile_dark.png)
- ProfileImage component now properly switches between dark and light theme images using next-themes hook
- Project version display in footer with small font size (10px)
- Version positioned in center of footer using three-column grid layout
- Version automatically updates from VERSION constant in lib/constants.ts
- Footer layout restructured to use grid system (grid-cols-1 md:grid-cols-3) for better alignment
- Version display uses subtle styling (text-[10px] text-foreground/40) for minimal visual impact
- Hide expiration date display for expired certificates in certifications section
- Expiration date now only shows for non-expired certificates with "Expires: [date]" format
- Certifications section component on home page displaying professional certifications and badges
- Company logo support for certifications (Grafana Labs, DevOps Institute, Riverbed Technology)
- Fixed-size logo containers (64x64px) with Next.js Image optimization for PNG/SVG formats
- Extended certification data structure with issue dates, expiration dates, credential IDs, credential URLs, and skills
- Automatic expiration date detection and visual indication for expired certifications
- Individual credential links for certifications with external URLs
- Updated resume.json with 9 certifications from Credly profile
- Extended TypeScript types in lib/resume.ts to support additional certification fields
- Certifications section positioned after blogs section on home page
- Fly.io configuration file (
fly.toml) for cloud deployment .flyignorefile to optimize deployment uploads and reduce build context- Comprehensive Fly.io deployment documentation (
docs/fly-deployment.md) - HTTP service configuration with health checks for Fly.io
- Auto-scaling configuration (auto-start machines, min machines running)
- Resource limits configuration (512MB memory, 1 shared CPU)
- Configured Fly.io deployment with Amsterdam (ams) as primary region
- Set up HTTPS enforcement and health check monitoring for production deployment
- Secure multi-stage Dockerfile optimized for Next.js 15 standalone output
- .dockerignore file to reduce build context size and improve build performance
- Health check API endpoint (
/api/health) for container orchestration and monitoring - Docker Compose example configuration file for easy local development and testing
- Non-root user security configuration in Docker image
- Health check configuration with proper intervals and timeouts
- Docker image runs as non-root user (nextjs:nodejs) for enhanced security
- Alpine Linux base image with security updates applied
- Minimal attack surface with only runtime dependencies in final image
- Proper file ownership and permissions set in Docker container
- Removed resume page (
/resumeroute) - Removed PDF download button functionality and components
- Removed print resume button component
- Removed resume header component (only used on resume page)
- Removed resume API route (
/api/resume) - Removed resume link from navigation menu
- Removed resume link from hero section
- Removed PDF mode CSS styles from globals.css
- Updated metadata to remove resume references
- Updated site description to remove resume mention
- Simplified hero section by removing resume CTA button
- Updated footer GitHub and LinkedIn links to point to user profiles instead of placeholder URLs
- Footer links now correctly open in new tab (target="_blank" was already present, verified)
- Enhanced search bar component with primary color shadow for better visual prominence
- Improved search input contrast with thicker primary-colored border (border-2 border-accent/30)
- Increased placeholder text opacity for better readability
- Enhanced focus state with stronger border and shadow effects
- Changed search icon color to primary accent color with proper z-index and pointer-events handling
- Removed tag filter component from blog list page
- Removed posts count display component from blog list page
- Simplified blog list page to focus on search functionality only
- Back button component for blog detail pages
- Conditional PDF button wrapper to hide download button on blog pages
- Redesigned share button to match metadata style and positioned next to reading time
- Updated footer copyright text format to "All Rights Reserved © {year}"
- Improved experience section mobile layout: date and location now appear side-by-side with badge styling
- Standardized font sizes across resume sections (summary, experience, core skills) to
text-xs sm:text-sm md:text-base - Added text justification for blog content on mobile devices
- Fixed Next.js 15 params Promise requirement - updated blog detail page to await params
- Fixed spacing issues on blog detail pages (buttons overlapping with content)
- Fixed text justification not applying to blog paragraphs on mobile
- Added 6 comprehensive technical blog posts covering AI/ML production systems:
- Why AI Systems Fail in Production (And Why It's Rarely the Model)
- Designing Observability for AI/ML Services: Metrics That Actually Matter
- From PoC to Production: What Breaks When You Ship LLM-Based Systems
- Azure for AI: An SRE's Guide to Provisioning for High Availability
- The AWS AI Stack: Moving Beyond Proof-of-Concept to Five-Nines Reliability
- Observing the Stochastic: Tuning the LGTM Stack for AI Infrastructure
- All blog posts formatted with proper MDX frontmatter, tags, and markdown structure
- Fixed home page summary text to display complete summary instead of truncated first sentence
- Summary text now properly displays all content from resume data
- Split summary text into two paragraphs for improved readability
- Added text justification to both summary paragraphs for cleaner appearance
- Glassmorphism container for profile image with rounded-2xl border radius matching menu styling
- Top spacing in profile image container to position image at bottom
- Updated profile image container to use square glassmorphism frame instead of circular
- Changed contact icon containers (location, LinkedIn, GitHub) from circular to square with rounded-2xl corners
- Increased glassmorphism contrast for better visibility (light theme: bg 0.15→0.75, dark theme: bg 0.3→0.5)
- Icon containers now use explicit square dimensions (h-8 w-8 md:h-9 md:w-9) matching toggle switch pattern
- Profile image now properly aligned to bottom of glass container with spacing on top
- Icon containers now display as squares with rounded corners instead of circles
- Theme-specific profile images support (profile_light.jpg and profile_dark.jpg)
- ProfileImage component with automatic theme-based image switching
- Smooth transitions when switching between theme-specific profile images
- Updated color scheme from green to true turquoise tones (#008080, #20B2AA, #40E0D0)
- Improved bottom navigation: removed empty spacing on right side (desktop view)
- Enhanced profile image component to use theme-aware image selection
- Fixed hardcoded green color in status badge component (now uses accent color)
- Fixed color scheme not applying correctly (updated CSS variables to true turquoise)
- Removed links section component from home page
- Removed links menu item from bottom navigation
- Menu item labels in bottom navigation for desktop view
- Dynamic active indicator positioning for accurate centering
- Enhanced bottom navigation: icon-only on mobile, labels on desktop
- Improved active indicator centering using dynamic position calculation
- Fixed favicon conflict by removing public/favicon.ico (Next.js 15 uses app/favicon.ico)
- Fixed favicon ICO format to use proper RGBA encoding
- Fixed TypeScript error in links-section component (null href type narrowing)
- Fixed favicon.ico format error (PNG not in RGBA format)
- Fixed conflicting public file and page file for favicon.ico path
- Profile photo in hero section with circular design and dramatic lighting effects
- Responsive profile photo display (visible on mobile and desktop)
- Profile photo as favicon.ico with automatic generation
- Favicon generation script (
npm run generate-favicon) - Multiple favicon formats (ICO, PNG) for better browser compatibility
- Menu item labels in bottom navigation for desktop view
- Dynamic active indicator positioning for accurate centering
- Enhanced hero section with larger, more prominent profile photo
- Improved profile photo styling with glassmorphism effects and accent borders
- Updated favicon generation to use secure implementation
- Enhanced bottom navigation: icon-only on mobile, labels on desktop
- Improved active indicator centering using dynamic position calculation
- Fixed favicon conflict by removing public/favicon.ico (Next.js 15 uses app/favicon.ico)
- Fixed favicon ICO format to use proper RGBA encoding
- Fixed TypeScript error in links-section component (null href type narrowing)
- Fixed favicon.ico format error (PNG not in RGBA format)
- Fixed conflicting public file and page file for favicon.ico path
- Fixed 10 npm package vulnerabilities (3 moderate, 2 high, 5 critical)
- Updated to-ico package to secure version 1.0.1
- Improved favicon generation script security
- Blog pagination component with glassmorphism design
- Configurable posts per page (default: 9 posts)
- Page count indicator in blog list results
- Smooth scroll to top when changing pages
- Pagination integration with search and tag filtering
- Improved resume page layout: moved print resume button next to GitHub button with matching style
- Fixed alignment issues on resume page contact section - all links now display on the same line
- Removed "Open to work" status indicator from resume page header
- Removed all Twitter-related content and links from the website (footer, metadata, constants)
- Next.js 15 project setup with TypeScript
- Tailwind CSS configuration with custom theme
- Theme system with dark/light mode support
- Blog system with MDX support
- Resume page with printable styles
- Responsive navigation and layout components
- SEO optimization with Open Graph and structured data