Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. sitemap.ts
- 2.1 Kod
- 2.2 Haqiqiy natija
- 2.3 Natija oynasida: sitemap mantiqi
- 2.4 Ko'p sitemap
- 3. robots.ts va manifest.ts
- 3.1 robots
- 3.2 manifest
- 3.3 Ikonkalar
- 4. OG rasmlar — opengraph-image.tsx
- 4.1 JSX'dan PNG
- 4.2 Har post uchun rasm
- 4.3 Kamchilik: qalin shrift chiqmadi
- 4.4 Twitter rasmi va tekshirish
- 5. JSON-LD
- 5.1 Nima
- 5.2 Nega < ni qochirish kerak
- 6. Hujumchi nigohi
- 7. Portfolio qadami: SEO fayllari va commit
- 7.1 Fayllar (holat 30)
- 7.2 Tekshiruv
- 7.3 Commit
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): fayl nomi → manzil
- 2-mashq (o'rta): sitemap'dan XML
- 3-mashq (qiyin): xavfsiz JSON-LD
- 4-mashq: Portfolio qadami
- 10. Real ishda
- Xulosa
- Manbalar
Next.js SEO fayllari: sitemap.ts, robots.ts, manifest va OG rasmlar
Qisqacha: Next.js
app/papkasidagi maxsus nomli fayllardan SEO fayllarini o'zi yasaydi:sitemap.ts→/sitemap.xml,robots.ts→/robots.txt,manifest.ts→/manifest.webmanifest,icon.svg→ favicon.opengraph-image.tsxesa JSX'dan PNG rasm chizadi (ImageResponse) — ijtimoiy tarmoqdagi havola rasmi. Bu fayllar ham statik (○) bo'lib, build vaqtida tayyorlanadi. JSON-LD — sahifa ichidagi tuzilgan ma'lumot; uni<belgisini qochirib yozish shart.
Bu darsda
sitemap.tsni bitta manbadan (loyihalar va postlar ro'yxatidan) yasaysiz va ko'p sitemap qachon kerakligini bilasiz.robots.tsvamanifest.tsni yozasiz va haqiqiy javoblarini ko'rasiz.opengraph-image.tsxbilan sayt va har post uchun OG rasm chizasiz; satori'ning cheklovlarini bilasiz.- Bosh sahifaga JSON-LD qo'shasiz va nega
<ni qochirish kerakligini jonli ko'rasiz. portfolioholat 30 ni commit qilasiz.
Oldin bilishingiz kerak: Metadata API, SPA uchun SEO, generateStaticParams, Route Handlers, XSS.
1. Nega bu kerak?
Oldingi darsda har sahifa o'z "muqovasini" oldi: sarlavha, tavsif, canonical. Lekin qidiruv tizimi saytga kirganda yana uchta savol beradi:
- Saytda qanday sahifalar bor? — sitemap.
- Qaysi joylarga kirmaslik kerak? — robots.txt.
- Telegram'da havola qanday rasm bilan ko'rinadi? — Open Graph rasmi.
SPA uchun SEO darsida bularni qo'lda yozgansiz: public/sitemap.xml faylini qo'lda to'ldirish, OG rasmni Figma'da chizish. Muammosi ma'lum: yangi blog posti qo'shdingiz — sitemap'ni yangilashni unutdingiz. Post sarlavhasini o'zgartirdingiz — OG rasmdagi eski sarlavha qoldi.
Next'da bu fayllar kod bo'ladi. Ma'lumot bitta joyda (loyihalar massivi, blog/ papkasi) — sitemap ham, OG rasm ham undan yasaladi.
Bitta manbadan bir nechta fayl:
flowchart LR
D["LOYIHALAR + blog/*.md"] --> S["sitemap.ts"]
D --> O["opengraph-image.tsx"]
D --> M["generateMetadata"]
S --> SX["/sitemap.xml"]
O --> P["PNG 1200×630"]
M --> H["og: teglar"]
R["robots.ts"] --> RX["/robots.txt"]
RX -.->|Sitemap:| SXChapda — ma'lumot, o'ngda — build natijasi. Post qo'shilsa, uchala o'ng tomon o'zi yangilanadi. robots.txt esa botga sitemap qayerdaligini aytadi (nuqtali chiziq).
Hayotiy o'xshatish: kutubxona. Sitemap — katalog kartochkalari, robots.txt — "Xodimlar uchun" eshigidagi yozuv, OG rasm — kitob muqovasining fotosurati. Yaxshi kutubxonachi kartochkalarni qo'lda emas, kitoblar ro'yxatidan avtomatik chiqaradi.
2. sitemap.ts
2.1 Kod
Kanondagi app/sitemap.ts (holat 30):
import type { MetadataRoute } from "next";
import { postlar } from "@/malumot/blog";
import { LOYIHALAR } from "@/malumot/loyihalar";
import { SAYT_URL } from "@/malumot/sozlama";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const oddiy = ["", "/haqimda", "/loyihalar", "/blog", "/aloqa"].map((y) => ({
url: `${SAYT_URL}${y}`,
}));
const loyihalar = LOYIHALAR.map((l) => ({
url: `${SAYT_URL}/loyihalar/${l.slug}`,
lastModified: `${l.sana}-01`,
}));
const blog = (await postlar()).map((p) => ({
url: `${SAYT_URL}/blog/${p.slug}`,
lastModified: p.sana,
}));
return [...oddiy, ...loyihalar, ...blog];
}| Qism | Nima |
|---|---|
MetadataRoute.Sitemap |
qaytadigan massiv turi: url, lastModified, changeFrequency, priority |
oddiy |
5 ta doimiy sahifa |
loyihalar |
har loyiha — sana ("2026-10") dan lastModified |
blog |
postlar fayllardan — await postlar() |
Yangi post qo'shsangiz — sitemap'ni qo'lda tahrirlamaysiz, keyingi build uni o'zi qo'shadi.
2.2 Haqiqiy natija
Build jadvalida (natijalar/tekshiruv-30.txt):
└ ○ /sitemap.xml 30d 1y○ — statik. 30d 1y — postlar keshining umri (Cache Components II): sitemap postlarga bog'liq, shuning uchun ular bilan birga yangilanadi. next start dagi javob (natijalar/30-seo.txt, boshi):
/sitemap.xml 200 application/xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com</loc>
</url>
<url>
<loc>https://example.com/loyihalar/vazifalar</loc>
<lastmod>2026-10-01</lastmod>
</url>Jami 11 ta URL: 5 oddiy + 3 loyiha + 3 post. Bosh sahifa manzili oxirida / siz — canonical bilan bir xil (oldingi darsdagi o'lchov).
2.3 Natija oynasida: sitemap mantiqi
sitemap() ning ishi — oddiy massiv yasash. Uni Next'siz yozib, XML'ga aylantiramiz:
const SAYT = "https://example.com";
const LOYIHALAR = [
{ slug: "vazifalar", sana: "2026-10" },
{ slug: "bahor", sana: "2026-09" },
];
const royxat = [
...["", "/aloqa"].map((y) => ({ url: SAYT + y })),
...LOYIHALAR.map((l) => ({
url: `${SAYT}/loyihalar/${l.slug}`,
lastModified: `${l.sana}-01`,
})),
];
for (const s of royxat) {
const lastmod = s.lastModified ? ` ${s.lastModified}` : "";
console.log(`${s.url}${lastmod}`);
}
console.log(`jami: ${royxat.length}`);Konsolda:
https://example.com
https://example.com/aloqa
https://example.com/loyihalar/vazifalar 2026-10-01
https://example.com/loyihalar/bahor 2026-09-01
jami: 4Next shu massivni yuqoridagi XML'ga aylantiradi. lastModified — Google'ga "bu sahifa qachon o'zgargan" ishorasi: o'zgarmagan sahifani qayta tekshirishga vaqt sarflamaydi.
2.4 Ko'p sitemap
Google bitta sitemap'da 50 000 URL'gacha qabul qiladi. Katta do'konda 200 000 mahsulot bo'lsa — sitemap bo'linadi. Next'da ikki yo'l:
- har bo'limda o'z fayli:
app/sitemap.tsvaapp/mahsulotlar/sitemap.ts; generateSitemaps()—[{ id: 0 }, { id: 1 }, …]qaytaradi,sitemap({ id })har bo'lakni yasaydi (/mahsulotlar/sitemap/0.xml…).
portfolio da 11 ta URL — bitta fayl yetarli.
Tekshirib ko'ring: Kanondagi sitemap'da
/loyihalar/vazifalar/rasm(rasm sahifasi) yo'q. Bu xatomi?
Javob
Yo'q, ataylab. Rasm sahifasi — loyiha skrinshotining kattalashtirilgan ko'rinishi, alohida qimmatli matni yo'q. Sitemap'ga faqat Google'da topilishi kerak bo'lgan sahifalar kiradi. Rasm sahifasi baribir o'z canonical'iga ega va havola orqali topiladi.
3. robots.ts va manifest.ts
3.1 robots
import type { MetadataRoute } from "next";
import { SAYT_URL } from "@/malumot/sozlama";
export default function robots(): MetadataRoute.Robots {
return {
rules: { userAgent: "*", allow: "/", disallow: "/api/" },
sitemap: `${SAYT_URL}/sitemap.xml`,
};
}Haqiqiy javob (natijalar/30-seo.txt):
/robots.txt 200 text/plain
User-Agent: *
Allow: /
Disallow: /api/
Sitemap: https://example.com/sitemap.xmlDisallow: /api/ — qidiruv botlari /api/qayta-yangila ga kirmasin. Bu himoya emas: robots.txt — iltimos, buyruq emas. Yomon niyatli bot uni o'qib, aynan yopiq yo'llarni qidiradi. Haqiqiy himoya — handler ichidagi sir tekshiruvi (Route Handlers).
3.2 manifest
manifest.ts — PWA darsidagi manifest.webmanifest ning kod ko'rinishi:
/manifest.webmanifest 200 application/manifest+json
{"name":"Aziz Karimov — portfolio","short_name":"Aziz","lang":"uz","start_url":"/","display":"browser","background_color":"#f7faf8","theme_color":"#1f6f4a","icons":[{"src":"/icon.svg","sizes":"any","type":"image/svg+xml"}]}display: "browser" — portfolio o'rnatiladigan ilova emas, oddiy sayt bo'lib qoladi. Manifest bu yerda brauzerga nom, rang va ikonkani aytadi. Next uni <head> ga <link rel="manifest"> bilan o'zi ulaydi.
3.3 Ikonkalar
app/icon.svg ni siz Layout darsida qo'ygansiz — u favicon bo'ldi. Boshqa nomlar ham bor:
| Fayl | Nima |
|---|---|
favicon.ico |
eski favicon (faqat app/ ildizida) |
icon.png, icon.svg |
zamonaviy favicon |
apple-icon.png |
iPhone bosh ekraniga qo'shilganda |
icon.tsx |
kod bilan chiziladigan ikonka (ImageResponse) |
4. OG rasmlar — opengraph-image.tsx
4.1 JSX'dan PNG
opengraph-image.tsx — ImageResponse qaytaradigan komponent. Next uni build vaqtida bajarib, PNG fayl qiladi. Kanondagi sayt rasmi (holat 30, qisqartirilgan — logotip bloki olib tashlangan):
import { ImageResponse } from "next/og";
export const alt = "Aziz Karimov — frontend dasturchi";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default function OgRasm() {
return new ImageResponse(
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
width: "100%",
height: "100%",
padding: 80,
background: "#f7faf8",
color: "#1f2a24",
}}
>
<div style={{ fontSize: 72, fontWeight: 700 }}>
Aziz Karimov
</div>
<div style={{ marginTop: 16, fontSize: 40 }}>
Frontend dasturchi — loyihalar, blog, case study
</div>
</div>,
size,
);
}| Eksport | Ma'nosi |
|---|---|
alt |
og:image:alt — rasm tavsifi (ekran o'quvchi va bot uchun) |
size |
1200×630 — Facebook va Telegram tavsiya etgan nisbat |
contentType |
og:image:type |
ImageResponse ichida satori kutubxonasi ishlaydi: u JSX'ni SVG'ga, keyin PNG'ga aylantiradi. Bu brauzer emas, shuning uchun CSS cheklangan. Next hujjati (ImageResponse) va satori qoidalaridagi cheklovlar:
- faqat flexbox va CSS'ning bir qismi —
display: gridishlamaydi; - har
divda bir nechta bola bo'lsa,display: "flex"aniq yozilishi kerak; - shrift — faqat
ttf,otf,woff(woff2 emas); - jami hajm (JSX, shriftlar, rasmlar) — 500 KB gacha.
4.2 Har post uchun rasm
app/(sayt)/blog/[slug]/opengraph-image.tsx — dinamik segment ichida. Unga ham params keladi, va u ham generateStaticParams bilan oldindan tayyorlanadi:
export async function generateStaticParams() {
return (await postlar()).map((p) => ({ slug: p.slug }));
}
export default async function PostOgRasmi({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const p = await postniOl((await params).slug);
return new ImageResponse(
<div style={{ display: "flex", flexDirection: "column" }}>
<div style={{ fontSize: 36 }}>Aziz Karimov · blog</div>
<div style={{ fontSize: 68, fontWeight: 700 }}>
{p?.sarlavha ?? "Blog"}
</div>
</div>,
size,
);
}Uslublar qisqartirildi (to'liq kod — holat 30 da: fon, padding, teglar qatori). Build jadvali:
├ /blog/[slug]/opengraph-image-zrbhtn
│ ├ ● /blog/portfolio-v2/opengraph-image-zrbhtn 30d 1y
│ ├ ● /blog/server-components/opengraph-image-zrbhtn 30d 1y
│ └ ● /blog/vazifalar-testlari/opengraph-image-zrbhtn 30d 1y
├ ○ /opengraph-image 30d 1yIkki yangi narsa. Birinchisi — ● (SSG): generateStaticParams bilan oldindan yasalgan sahifa belgisi. Ikkinchisi — fayl nomiga -zrbhtn qo'shimchasi: Next dinamik segment ichidagi rasm manziliga xesh qo'shadi. Siz bu manzilni yozmaysiz — metadata'da Next uni o'zi qo'yadi:
/blog/portfolio-v2: {"ogImage":"https://example.com/blog/portfolio-v2/opengraph-image-zrbhtn?7a2cc30a9c39bee3","ogType":"article"}Fayllar: /opengraph-image — 37 328 bayt, post rasmi — 41 196 bayt, ikkalasi PNG 1200×630 (natijalar/30-seo.txt).
4.3 Kamchilik: qalin shrift chiqmadi
Rasmda fontWeight: 700 yozilgan, lekin kanon tekshiruvi ko'rsatdi: sarlavha qalin emas. Sabab: shrift berilmagan — satori o'zining bitta standart shriftini ishlatadi, unda qalin variant yo'q. Brauzer "soxta qalin" chizib bera oladi, satori esa yo'q.
Bu holat 30 dagi ochiq kamchilik. next/font darsida Rubik shriftini qo'shganda OG rasmlarga ham fonts beriladi — va u yerda yangi tuzoq chiqadi (DataView xatosi).
Tekshirib ko'ring: Post OG rasmida
display: "grid"bilan ikki ustun qilmoqchisiz. Nima bo'ladi va qanday yechasiz?
Javob
Satori grid'ni qo'llamaydi — hujjat bo'yicha faqat flexbox. Ikki ustunni display: "flex" + flexDirection: "row" va har ustunga width: "50%" (yoki flex: 1) bilan qiling. OG rasm — oddiy tuzilma, flexbox yetarli.
4.4 Twitter rasmi va tekshirish
twitter-image.tsx — xuddi shu konvensiya, faqat twitter:image uchun. Alohida fayl bo'lmasa, X (Twitter) og:image ni oladi — portfolio da shuning uchun bitta rasm yetarli. Rasm faylining o'rni ham muhim: u qaysi papkada tursa, o'sha segment va uning bolalariga qo'llanadi. Root'dagi rasm hamma sahifaga, blog/[slug]/ dagisi faqat postlarga.
Rasmni qanday tekshirasiz? Uch bosqich:
- Brauzerda to'g'ridan oching:
/opengraph-image— PNG chiqishi kerak. - Sahifa manbasida
og:imageqatori to'liq manzil bilan (https://…) turganini tekshiring —metadataBaseishlayotganining belgisi. - Sayt internetga chiqqach, Telegram'da o'zingizga havola yuboring. Telegram ko'rinishni keshlaydi: rasmni o'zgartirsangiz, eski ko'rinish bir muddat qolishi mumkin. Rasm manzilidagi
?…qo'shimchasi (opengraph-image?bfd9fbf514465004) — Next qo'yadigan versiya belgisi: rasm o'zgarsa, belgi ham o'zgaradi va botlar yangisini oladi.
5. JSON-LD
5.1 Nima
JSON-LD (JSON Linked Data) — sahifaga qo'yiladigan tuzilgan ma'lumot: "bu sahifa — shu odamniki", "bu — maqola, muallifi va sanasi". Google uni boy natijalar (rich results) uchun o'qiydi. Lug'at — schema.org.
Kanondagi bosh sahifa (holat 30):
const JSON_LD = {
"@context": "https://schema.org",
"@type": "Person",
name: "Aziz Karimov",
jobTitle: "Frontend dasturchi",
url: SAYT_URL,
sameAs: [`https://github.com/${GITHUB_LOGIN}`, "https://t.me/sizning_kanal"],
};
// <main> ichida:
<script
type="application/ld+json"
// XSS: "<" qochiriladi (hujjat: guides/json-ld)
dangerouslySetInnerHTML={{
__html: JSON.stringify(JSON_LD).replace(/</g, "\\u003c"),
}}
/>sameAs — boshqa joylardagi profillar. t.me/sizning_kanal — o'zingiznikiga almashtiriladigan namuna.
5.2 Nega < ni qochirish kerak
JSON.stringify HTML uchun xavfsiz emas. Agar ma'lumotda </script> satri bo'lsa (masalan blog sarlavhasini foydalanuvchi yozgan bo'lsa), u skript tegini yopib qo'yadi va qolgani HTML sifatida o'qiladi. Natija oynasida ko'ramiz:
const malumot = { name: "Ali</script><script>alert(1)</script>" };
const xom = JSON.stringify(malumot);
const xavfsiz = xom.replace(/</g, "\\u003c");
console.log(xom);
const qochirilgan = xavfsiz.split("\\u003c").length - 1;
console.log(qochirilgan); // qochirilgan < soni
console.log(xom.includes("</script>"), xavfsiz.includes("</script>"));
console.log(JSON.parse(xavfsiz).name === malumot.name);Konsolda:
{"name":"Ali</script><script>alert(1)</script>"}
3
true false
trueIkkinchi qator — nechta < qochirilgani: uchalasi ham. Xavfsiz satrning o'zi (console.log(xavfsiz)) shunday chiqadi: {"name":"Ali\u003c/script>\u003cscript>alert(1)\u003c/script>"}. Biz uni sanoq va true/false bilan ko'rsatdik: natija oynasidagi solishtirish \u003c yozuvini ham < deb o'qiydi, chiqishning o'zi esa xuddi shunday. \u003c — < ning JSON ichidagi yozuvi. Brauzerning HTML tahlilchisi uni teg deb tanimaydi. JSON tahlilchisi esa yana < qilib o'qiydi — oxirgi qator buni tasdiqlaydi: ma'no o'zgarmadi. portfolio dagi ma'lumot o'zimizniki va xavfsiz, lekin qoida doimiy: dangerouslySetInnerHTML ga ketadigan JSON — har doim qochirilgan (XSS darsidagi tamoyil).
6. Hujumchi nigohi
- robots.txt — xarita, qulf emas.
Disallow: /admin/deb yozish hujumchiga "admin shu yerda" deb aytish bilan teng. Maxfiy yo'llar robots.txt'da emas, auth ortida bo'lsin. - JSON-LD orqali XSS. Ma'lumot foydalanuvchidan kelsa (izoh, mahsulot nomi), qochirilmagan
JSON.stringify— to'g'ridan skript qo'shish. Yuqoridagi qatorlar buni ko'rsatdi. - Dinamik OG rasm — og'ir endpoint. Agar OG rasm har so'rovda chizilsa (
ƒ), hujumchi minglab turli?title=bilan so'rab serverni band qiladi.portfolioda rasmlar build'da tayyor (○/●) — bu xavf yo'q.
7. Portfolio qadami: SEO fayllari va commit
7.1 Fayllar (holat 30)
Oldingi darsdagi metadata'ga qo'shiladi:
| Fayl | Natija |
|---|---|
app/sitemap.ts |
/sitemap.xml — 11 URL |
app/robots.ts |
/robots.txt — /api/ yopiq, sitemap havolasi |
app/manifest.ts |
/manifest.webmanifest |
app/opengraph-image.tsx |
/opengraph-image — sayt rasmi |
(sayt)/blog/[slug]/opengraph-image.tsx |
har post rasmi (●) |
(sayt)/page.tsx |
JSON-LD Person |
7.2 Tekshiruv
npm run lint
npm run tip
npm run build
npm run startBrauzerda /sitemap.xml, /robots.txt, /opengraph-image ni oching. Kanon o'lchovi (holat 30): 9 sahifada title shablon bo'yicha, canonical o'ziniki, og:image — root yoki o'z rasmi; JS 145.6 → 146.5 KB gzip (+0.9 — metadata uchun), axe 0, hydration 0.
7.3 Commit
git add -A
git commitCommit (kanon): SEO: title shabloni, canonical, OG/Twitter, viewport; sitemap, robots, manifest, OG rasmlar, JSON-LD.
Deploy'dan keyin (sayt internetda bo'lganda) Google Search Console'ga sitemap manzilini qo'shasiz — bu deploy darsida.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Yangi post sitemap'da yo'q | public/sitemap.xml qo'lda |
app/sitemap.ts — ma'lumotdan |
Sitemap'da localhost yoki example.com |
SAYT_URL o'zgartirilmagan, build eski |
To'g'ri SAYT_URL bilan qayta build |
| OG rasm build xatosi: grid | satori display: grid ni bilmaydi |
flexbox |
| OG rasmda matn qalin emas | shrift berilmagan | fonts (ttf/otf/woff) — next/font darsida |
public/ dagi robots.txt va app/robots.ts ziddiyati |
ikki manba | bittasini qoldiring |
| JSON-LD orqali sahifa buzildi | JSON.stringify qochirilmagan |
.replace(/</g, "\\u003c") |
OG rasm har so'rovda chiziladi (ƒ) |
keshlanmagan ma'lumot | generateStaticParams, "use cache" |
9. Mashqlar
Mashqlar kurs/mashqlar/23/30-seo-fayllar/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): fayl nomi → manzil
app/sitemap.ts→app/robots.ts→app/manifest.ts→app/opengraph-image.tsx→
Yechim
Fayl nomi — konvensiya: Next kengaytmasiz nomdan standart manzilni yasaydi. /sitemap.xml va /robots.txt — qidiruv tizimlari aynan shu manzillarni qidiradi. /opengraph-image manzilini siz yozmaysiz — Next uni og:image ga o'zi qo'yadi (dinamik segmentda xesh bilan).
2-mashq (o'rta): sitemap'dan XML
«sitemap mantiqi» blokidagi royxat ni haqiqiy XML satriga aylantiring: har element <url><loc>…</loc></url>, lastModified bo'lsa — <lastmod>…</lastmod> ham. Boshiga <urlset>, oxiriga </urlset>. Satrlarni map va join bilan yig'ing.
Yechim
const SAYT = "https://example.com";
const royxat = [
{ url: SAYT },
{ url: `${SAYT}/loyihalar/vazifalar`, lastModified: "2026-10-01" },
];
function xmlYasa(royxat) {
const urllar = royxat.map((s) => {
const lm = s.lastModified
? `<lastmod>${s.lastModified}</lastmod>`
: "";
return `<url><loc>${s.url}</loc>${lm}</url>`;
});
return ["<urlset>", ...urllar, "</urlset>"].join("\n");
}
console.log(xmlYasa(royxat));Konsolda:
<urlset>
<url><loc>https://example.com</loc></url>
<url><loc>https://example.com/loyihalar/vazifalar</loc><lastmod>2026-10-01</lastmod></url>
</urlset>Haqiqiy sitemap'da urlset da xmlns atributi ham bor va <loc> dagi & kabi belgilar qochiriladi — Next buni o'zi qiladi. Shuning uchun haqiqiy loyihada XML'ni qo'lda yasamaysiz.
3-mashq (qiyin): xavfsiz JSON-LD
jsonLdYoz(obyekt) funksiyasini yozing: <, > va & ni mos ravishda \u003c, \u003e, \u0026 ga almashtirsin (qo'shimcha ehtiyot). Keyin uch tekshiruv: natijada </script> yo'q, JSON.parse asl obyektni qaytaradi, & ham saqlanadi. replace funksiya bilan — satrni o'zgartirish.
Yechim
const ALMASHTIR = { "<": "\\u003c", ">": "\\u003e", "&": "\\u0026" };
function jsonLdYoz(obyekt) {
const satr = JSON.stringify(obyekt);
return satr.replace(/[<>&]/g, (b) => ALMASHTIR[b]);
}
const post = { headline: "React & Next: </script> tuzog'i" };
const satr = jsonLdYoz(post);
console.log(satr.includes("\\u0026"), satr.includes("\\u003e"));
console.log(satr.includes("</script>"));
console.log(JSON.parse(satr).headline === post.headline);Konsolda:
true true
false
true& ni qochirish — HTML entity'lar (<) bilan chalkashlikning oldini oladi. Next hujjati minimal yechim sifatida faqat < ni qochirishni ko'rsatadi; uchala belgini qochirish — keng tarqalgan qat'iyroq variant (masalan serialize-javascript kutubxonasi ham shunday qiladi).
4-mashq: Portfolio qadami
O'z portfolio ingizga sitemap.ts, robots.ts, manifest.ts, ikki opengraph-image.tsx va bosh sahifaga JSON-LD qo'shing. Build jadvalida ○ /sitemap.xml va ● belgili post rasmlarini toping. /opengraph-image ni brauzerda ochib, rasmni ko'ring — sarlavha qalinmi? Keyin oldingi dars metadata'si bilan birga commit qiling.
Yechim
Kutilgan build qatorlari — «Har post uchun rasm» bo'limidagi jadval kabi (xesh boshqa bo'lishi mumkin). Rasmda sarlavha qalin emas — bu kanondagi ochiq kamchilik, next/font darsida tuzatiladi. Commit — kanon xabari bilan yoki o'zingizniki.
10. Real ishda
- Har kontent saytida (blog, do'kon, yangiliklar)
sitemap.tsma'lumotlar bazasidan yasaladi; katta saytlarda —generateSitemapsbilan bo'laklarga. - Dinamik OG rasmlar — Vercel, GitHub, dev.to: har maqola yoki repo uchun avtomatik rasm. Telegram kanaliga post ulashganda chiroyli karta chiqadi — bosilish (CTR) oshadi.
- JSON-LD — e-commerce (
Product, narx, reyting), retseptlar (Recipe), tadbirlar: Google natijasida yulduzcha va narx ko'rinadi. Tekshirish — Google Rich Results Test. - Intervyu savoli: "Next'da sitemap qanday yasaladi?", "OG rasmni qanday avtomatlashtirasiz?" —
sitemap.tsvaopengraph-image.tsxni bilish va satori cheklovlarini aytish yetarli.
Xulosa
app/dagi maxsus fayllar SEO fayllariga aylanadi:sitemap.ts,robots.ts,manifest.ts,icon.*,opengraph-image.tsx.- Sitemap ma'lumotdan yasaladi (11 URL), postlar keshiga bog'lanib
○ 30d 1y; 50 000 dan ko'p URL —generateSitemaps. robots.txt— iltimos, himoya emas;/api/ni handler o'zi himoya qiladi.- OG rasm — satori: faqat flexbox, ttf/otf/woff, 500 KB; dinamik segmentda
generateStaticParamsbilan●va xeshli manzil. - JSON-LD
<qochirilib yoziladi — aks holda</script>orqali XSS.
Keyingi dars: next/image — loyiha rasmini avtomatik o'lchamlash, LCP uchun preload va proxy matcher topgan xatoning to'liq hikoyasi.
Manbalar
- Next.js hujjati (16.4.0,
node_modules/next/dist/docs/):sitemap.xml(generateSitemaps),robots.txt,manifest.json,opengraph-image,favicon, icon, and apple-icon,ImageResponse, "JSON-LD" guide — nextjs.org/docs/app/api-reference/file-conventions/metadata (2026-10-21 da o'qildi) - Kanon natijalari:
natijalar/30-seo.txt,natijalar/tekshiruv-30.txt,natijalar/tajriba/30-og_*.png; holat 30 diff - Google: "Build and submit a sitemap" (50 000 URL chegarasi) — developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap
- schema.org — Person
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!