0-dan Azərbaycan dilli Next.js Blog: Tam Praktiki Bələdçi
Next.js 14 ilə çoxdilli blog qurmağı öyrən — i18n routing, MDX content və Azərbaycan dili dəstəyi ilə. Real kod nümunələri ilə addım-addım.
0-dan Azərbaycan Dili Dəstəyi Olan Next.js Blog Qurmaq
Salam, developer dostum! 👋
Bilirəm, LinkedIn-də "personal brand" mövzusu artıq hamını yorub. Amma reallıq budur: Azərbaycanda texnologiya bazarı böyüyür, yerli şirkətlər — Kapital Bank, ABB, Pasha Holding, SOCAR-ın digital komandaları — portfolio və bloqu olan developerlərə fərqli baxır. Bakıda Junior Frontend Developer maaşı 800-1200 AZN arasında dəyişirsə, güclü portfoliosu olan Middle developer 2000-3500 AZN rahatlıqla ala bilir. Fərqi yaradan şeylərdən biri də budur: sən nə bildiyini göstərə bilirsənmi?
Bu gün sıfırdan Next.js 14 (App Router) ilə Azərbaycan dili dəstəyi olan, MDX-powered blog qururuq. Hazırsan? Terminalı aç, başlayırıq.
Niyə Next.js və Niyə Çoxdilli?
Vercel-in 2025 State of Frontend sorğusuna görə, Next.js React ekosistemində 68% pay ilə liderdir. App Router isə artıq stable-dır və next-intl ilə i18n (internationalization) dəstəyi əla işləyir.
Azərbaycan dili dəstəyi əlavə etməyin bir neçə səbəbi var:
- SEO üstünlüyü: Google azərbaycanca axtarışlarda azərbaycanca content-i prioritetləşdirir
- Yerli auditoriya: Hər kəs ingilis dilində rahat oxumur
- Fərqlənmək: Azərbaycanca texniki blog yazan developer çox azdır — bu sənin şansındır
- Portfolio effekti: Müsahibədə i18n təcrübən olduğunu göstərirsən
Addım 1: Layihəni Yaratmaq
Terminalda bu əmri icra et:
bashnpx create-next-app@latest my-az-blog --typescript --tailwind --app --src-dir cd my-az-blog npm install next-intl next-mdx-remote gray-matter
Layihənin struktur belə olacaq:
src/
├── app/
│ └── [locale]/
│ ├── layout.tsx
│ ├── page.tsx
│ └── blog/
│ └── [slug]/
│ └── page.tsx
├── content/
│ ├── az/
│ │ └── ilk-meqale.mdx
│ └── en/
│ └── first-post.mdx
├── i18n/
│ ├── routing.ts
│ └── request.ts
└── messages/
├── az.json
└── en.json
Addım 2: i18n Konfiqurasiyası
Əvvəlcə src/i18n/routing.ts faylını yarat:
typescriptimport { defineRouting } from 'next-intl/routing'; import { createNavigation } from 'next-intl/navigation'; export const routing = defineRouting({ locales: ['az', 'en'], defaultLocale: 'az', localePrefix: 'as-needed' }); export const { Link, redirect, usePathname, useRouter } = createNavigation(routing);
Sonra src/i18n/request.ts:
typescriptimport { getRequestConfig } from 'next-intl/server'; import { routing } from './routing'; export default getRequestConfig(async ({ requestLocale }) => { let locale = await requestLocale; if (!locale || !routing.locales.includes(locale as any)) { locale = routing.defaultLocale; } return { locale, messages: (await import(`../../messages/${locale}.json`)).default }; });
next.config.ts faylına plugin əlavə et:
typescriptimport createNextIntlPlugin from 'next-intl/plugin'; const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts'); const nextConfig = {}; export default withNextIntl(nextConfig);
Addım 3: Middleware — Dil Yönləndirməsi
src/middleware.ts faylı yarat:
typescriptimport createMiddleware from 'next-intl/middleware'; import { routing } from './i18n/routing'; export default createMiddleware(routing); export const config = { matcher: ['/', '/(az|en)/:path*'] };
Bu middleware istifadəçini brauzerin dilinə görə avtomatik yönləndirir. Azərbaycandan girən istifadəçi birbaşa /az/ yoluna düşəcək.
Addım 4: MDX Blog Postlarını Oxumaq
src/lib/content.ts faylında postları oxuyan utility yaz:
typescriptimport fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; const contentDir = path.join(process.cwd(), 'src/content'); export function getPostsByLocale(locale: string) { const dir = path.join(contentDir, locale); if (!fs.existsSync(dir)) return []; return fs.readdirSync(dir) .filter((file) => file.endsWith('.mdx')) .map((file) => { const raw = fs.readFileSync(path.join(dir, file), 'utf-8'); const { data, content } = matter(raw); return { slug: file.replace('.mdx', ''), title: data.title, date: data.date, excerpt: data.excerpt, content }; }) .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); } export function getPostBySlug(locale: string, slug: string) { const posts = getPostsByLocale(locale); return posts.find((p) => p.slug === slug) || null; }
Nümunə MDX faylı — src/content/az/ilk-meqale.mdx:
mdx--- title: "Niyə Hər Developer Blog Yazmalıdır" date: "2026-03-08" excerpt: "Blog yazmaq karyeranı necə dəyişir — real nümunələrlə" --- ## Giriş Blog yazmaq sadəcə bilik paylaşmaq deyil, **öyrənməyin ən effektiv yoludur**.
Addım 5: Blog Səhifələri
src/app/[locale]/blog/[slug]/page.tsx:
tsximport { getPostBySlug, getPostsByLocale } from '@/lib/content'; import { MDXRemote } from 'next-mdx-remote/rsc'; import { notFound } from 'next/navigation'; type Props = { params: Promise<{ locale: string; slug: string }>; }; export async function generateStaticParams() { const locales = ['az', 'en']; return locales.flatMap((locale) => getPostsByLocale(locale).map((post) => ({ locale, slug: post.slug })) ); } export default async function BlogPost({ params }: Props) { const { locale, slug } = await params; const post = getPostBySlug(locale, slug); if (!post) notFound(); return ( <article className="prose prose-lg mx-auto max-w-2xl py-12"> <h1>{post.title}</h1> <time className="text-gray-500">{post.date}</time> <MDXRemote source={post.content} /> </article> ); }
Addım 6: Dil Dəyişdirici Komponent
Bu kiçik komponent istifadəçiyə dil seçməyə imkan verir:
tsx'use client'; import { usePathname, useRouter } from '@/i18n/routing'; export default function LocaleSwitcher({ current }: { current: string }) { const router = useRouter(); const pathname = usePathname(); const next = current === 'az' ? 'en' : 'az'; return ( <button onClick={() => router.replace(pathname, { locale: next })} className="rounded-md border px-3 py-1 text-sm font-medium hover:bg-gray-100 transition-colors" > {next === 'az' ? 'Azərbaycanca' : 'English'} </button> ); }
Deploy və Nəticə
Layihəni Vercel-ə deploy etmək bir dəqiqəlik işdir:
bashnpm run build # Əvvəl lokal yoxla git push # Vercel auto-deploy edəcək
Vercel-in hobby planı pulsuzdur — yəni bu blogu sıfır xərclə yayımlaya bilərsən.
Sən nə əldə etdin?
- ✅ Azərbaycan + İngilis dili dəstəyi olan SSG blog
- ✅ MDX ilə code block, komponent dəstəkli məqalələr
- ✅ SEO-friendly statik səhifələr
- ✅ Middleware ilə avtomatik dil yönləndirmə
- ✅ Portfolio üçün real layihə
Növbəti Addımlar
- Sitemap əlavə et —
next-sitemappaketi ilə - Dark mode — Tailwind-in
dark:prefiksi ilə - RSS feed — azərbaycanca RSS olan blog demək olar yoxdur
- View counter — Upstash Redis ilə serverdə saxla
Son Söz
Bakıda texnologiya sektoru sürətlə böyüyür. ABB-nin digital transformasiya komandası, Kapital Bank-ın fintech layihələri, PASHA Holding-in insurtech istiqaməti — hamısı React/Next.js bilən developerlərə ehtiyac duyur. Bu bloqu qur, 3-5 məqalə yaz, LinkedIn-də paylaş. İnan, nəticəsini görəcəksən.
Sualın varsa, Baku Stack-in Telegram kanalında yaz. Kod yazmağa davam! 🚀
Oxşar məqalələr
Git Workflow — Komanda İşi Üçün Branch Strategiyası
Komandada işləyirsən və Git branch-ləri qarışır? Bu məqalədə real layihələrdə istifadə olunan workflow strategiyalarını praktiki nümunələrlə öyrən.
Stripe Ödənişlərini Next.js-ə İnteqrasiya Et: Tam Praktiki Bələdçi
Azərbaycandan Stripe ilə ödəniş qəbul etmək istəyirsən? Next.js App Router + Stripe Checkout ilə sıfırdan real ödəniş sistemi qururuq — kod, izah və praktiki məsləhətlərlə.
OpenAI API-ni Öz Tətbiqinizə Əlavə Etmək — Başlanğıc Bələdçi
GPT modelini öz layihənizə necə inteqrasiya edəcəyinizi praktiki kod nümunələri ilə addım-addım öyrənin. API key almaqdan tutmuş production-a qədər.