Files
ta1sph.info/PROJECT_MEMORY.md
T
2026-10-16 09:15:37 +03:00

122 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROJECT_MEMORY — ta1sph.info
> Claude'un bu proje için kalıcı hafızası. Her görev sonunda güncellenir. Kısa ve güncel tutulur.
> Son güncelleme: 2026-10-16 · Güncelleyen: Claude (Siteyi Kur — yayın)
## 1. Durum
- **Aşama:** Siteyi Kur tamamlandı — **site yayında** (2026-10-16, commit `486e34b`). Artık `Makale Ekle` / `Uygulama Düzenle` / `Yayına Al` akışları.
- **Tamamlanan:** Aşama 0–8 (kod). Docker imajı yerelde build + çalıştırma + volume kalıcılığı test edildi (test kalıntıları silindi). Lighthouse (yerel): A11y/BP/SEO 100; Perf temiz koşullarda 98–100. Yayında PageSpeed Insights ile doğrulanmalı.
- **Açık işler (kullanıcı tarafı):** Dokploy'da www → apex 301 (Advanced → Redirects; 2026-10-16 itibarıyla www hâlâ 200 veriyor). Volume `ta1sph-data` → `/app/data` doğrulanmalı (yazı oku → `/api/views/top/` → redeploy sonrası korunuyor mu). Google Search Console + sitemap. PageSpeed Insights. Volume yedeği. 3 örnek yazı (`örnek`) gerçek yazılar gelince silinecek. Hakkımda tanıtım paragrafı. İsteğe bağlı: HSTS başlığı (`server.mjs`).
- **Bilinen sorunlar:** Arama (Pagefind) `astro dev`'de çalışmaz, yalnızca build sonrası. Kullanıcının elle başlattığı dev sunucusu yeni koleksiyonu görmüyorsa yeniden başlatılmalı. `npm audit`: 2 orta seviye (postcss-selector-parser 6.0.10, @tailwindcss/typography sabitliyor) — yalnızca build zamanı, düzeltme typography'yi eski sürüme düşürdüğü için uygulanmadı.
## 2. Ortam
- Astro 7.4.0 · TailwindCSS 4.3.3 (`@tailwindcss/vite`) · TypeScript 6 strict · zod = `astro/zod` (ayrı paket yok)
- @astrojs/node 11.1.8 · mdx 8.1.0 · sitemap 3.7.4 · rss 4.0.19 · astro-icon 1.2.0 · pagefind 1.5.2
- Yerel: Node v26.11.1, npm 12.2.0, Docker 29.8.1 · `package.json` engines: node >=24 · Docker: `node:24-slim`
- Repo: `origin` = https://gitea.ta1sph.info/suphicakir/ta1sph.info.git · Branch: `main` · **Push'u kullanıcı yapar** (Claude push etmez)
- Canlı: https://ta1sph.info (Dokploy, HomeServer Atlas; Traefik + Let's Encrypt, sertifikalar 2027-01-14'e kadar). Dokploy uygulaması: Gitea provider "Atlas", Autodeploy açık → `main`'e push = yayın. DNS: turkticaret.net (A @ / www → 159.146.61.151, sabit IP); Atlas LAN IP 192.168.1.108
## 3. Dosya Haritası
- `astro.config.mjs` — site/trailingSlash/static + node adapter, mdx, sitemap (`/_styleguide/` hariç), astro-icon (tabler), Tailwind vite plugin
- `src/styles/global.css` — tema token'ları (light/dark, `data-theme`), fontlar, `.surface-alt` (khaki bölüm), `.headline`, `.link-strong`, reduced-motion
- `src/data/site.json` (ad, açıklama, nav, footer, `ui` metinleri, postsPerPage) · `src/data/social.json` (boş `href` → gizli) · `src/lib/data.ts` (zod; hata build'i kırar)
- `src/layouts/BaseLayout.astro` — head (ThemeInit, Seo, RSS alternate), skip link, Header, `main#main`, Footer
- `src/components/` — `Seo` (title/desc/canonical/OG/Twitter + WebSite/Person JSON-LD graph, `jsonLd` prop'u ile ek düğüm), `ThemeInit` (FOUC önleyici inline), `ThemeToggle`, `Header` (mobil menü = native `popover`, JS yok), `Footer` (4 sütun), `Container`, `GridLines`, `SectionHeading` (eyebrow + kırmızı çizgi), `Button` (primary/secondary/link), `Badge` (solid/outline/category), `Card`, `ExternalLink`
- `src/data/home.json` — `seo`, `hero`, `sections[]` (`feature` | `cards` | `latestPosts`); şema `data.ts` → `home`, `HomeSection`. Tanıtım metinleri sitelerin kendi tanıtımlarından (2026-10-16 tarandı)
- `src/pages/index.astro` — sections'ı sırayla render eder; arka plan dönüşümlü (hero khaki → paper, khaki…)
- `src/components/Section.astro` (tam genişlik bölüm + GridLines, `alt` = khaki) · `src/components/home/` — `Hero`, `FeatureSection` (numara + ikon | çağrı işareti/alan adı | başlık+metin+CTA; 3 sütun grid çizgileriyle hizalı), `CardGrid`, `LatestPosts` (slot), `Numeral` (dev rakam `::before` ile → a11y/kontrast dışı)
- `Button` — `external` prop'u (target/rel + sr-only "yeni sekmede açılır")
- `src/content.config.ts` — `blog` koleksiyonu (glob `**/index.{md,mdx}`, id = klasör adı), zod şeması (kapak varsa `coverAlt` zorunlu)
- `src/data/categories.json` (slug/ad/açıklama/ikon) · `src/data/blog.json` (blog arayüz metinleri, paylaşım URL şablonları `{url}`/`{title}`); `data.ts` → `categories`, `blog`, `fmt()`
- `src/lib/posts.ts` — `getPosts` (prod'da draft hariç, bilinmeyen kategori build'i kırar), URL yardımcıları, `readingMinutes` (body/200), tag/kategori sayımları, `featuredPosts`, `adjacentPosts`, `chunk`/`pageUrl`/`pageParam` · `src/lib/dates.ts` — `dateBadges`, `formatDate` (tr-TR, Europe/Istanbul), `isoDay`
- `src/lib/markdown-plugins.mjs` — Sätteri HAST eklentileri: `figurePlugin` (`![alt](img "Altyazı")` → figure/figcaption), `externalLinksPlugin` (dış link → yeni sekme)
- `src/pages/blog/[...page].astro` (/blog/, /blog/sayfa/n/) · `blog/[slug].astro` (detay + BlogPosting/BreadcrumbList JSON-LD, kod kopyala script'i) · `blog/kategori/[category]/[...page].astro` · `blog/etiket/[tag]/[...page].astro` · `src/pages/rss.xml.ts`
- `src/components/blog/` — `BlogListing` (liste düzeni + sidebar), `PostCard` (row/stack, kapaksızsa kategori ikonu), `DateBadges`, `Pager`, `Sidebar`, `SearchBox` (Pagefind JS API, özel UI), `ShareBar`, `Toc`, `Breadcrumbs`, `DiyNotice`
- `global.css` — `.article-prose` (prose token eşlemesi), Shiki çift tema, `.code-copy`
- `src/lib/views.ts` — `node:sqlite` sayaç (`$DATA_DIR/views.db`, varsayılan `./data`; Docker'da `/app/data` volume). Tablolar: `views(slug,count)`, `hits(hash,at)` 24 sa, `salts(day,salt)` günlük tuz. IP saklanmaz; `clientIp` önce `X-Forwarded-For`; `isBot` UA filtresi (headless dahil)
- `src/pages/api/views/[slug].ts` (POST, 204; bilinmeyen slug 404) · `src/pages/api/views/top.ts` (GET `?limit=1..10`, JSON `{slug,title,url,count}`, 5 dk cache) — ikisi `prerender = false`
- Yazı sayfası `sendBeacon('/api/views/<slug>/')`; Sidebar script'i `/api/views/top/` ile `ol[data-featured]`'ı değiştirir, eksikleri build-time yedekle tamamlar
- `src/data/about.json` (künye + ekipman grupları) · `src/data/contact.json` (harita lat/lng/zoom, bilgi satırları; `email` HTML'de açık yazılmaz, JS ile birleştirilir) · `src/data/pages.json` (yasal sayfa ortak metinleri, 404)
- `src/pages/hakkimda.astro` (ProfilePage JSON-LD) · `src/pages/iletisim.astro` (Leaflet + OSM, görünür olunca dinamik import; `divIcon` içinde `.tower-pin`) · `src/pages/[legal].astro` + `src/content/legal/{gizlilik,lisans,sorumluluk-reddi}.md` (koleksiyon `legal`, frontmatter `updated`) · `src/pages/404.astro`
- `src/components/PageHeader.astro` (khaki başlık + tek h1; blog listesi de kullanır) · `src/components/CodeCopy.astro` (Markdown'ı sarar, kod bloklarına Kopyala düğmesi)
- `LICENSE` (MIT) · `LICENSE-CONTENT` (CC BY-SA 4.0, resmî legalcode.txt'den)
- `src/lib/og.ts` — Satori + Sharp ile 1200×630 OG PNG (khaki, grid çizgileri, kule ikonu); latin-ext fontlar ayrı aile adıyla yedek (`RubikExt`, `InterExt`) · `src/pages/og/[slug].png.ts` (yazı başına) · `src/pages/og-default.png.ts` (diğer sayfalar). `Seo` varsayılanı `/og-default.png`; kapaklı yazıda kapak 1200px JPEG
- `src/pages/site.webmanifest.ts`, `src/pages/robots.txt.ts` (`/api/` kapalı, sitemap satırı) — `site.json`'dan
- `public/fonts/*.woff2` + `src/styles/fonts.css` — **üretilir:** `npm run fonts` (`scripts/subset-fonts.mjs`, subset-font; Latin+Türkçe+sembol, wght Rubik 400–900 / Inter 400–700; 188 KB → 66 KB). Kaynak `@fontsource-variable/*` (devDeps). BaseLayout iki latin dosyasını preload eder
- `public/favicon.{svg,ico}`, `apple-touch-icon.png`, `icon-192/512.png`, `icon-maskable-512.png` — **üretilir:** `npm run icons` (`scripts/generate-icons.mjs`; kırmızı zemin + siyah kule, 16px için kalın varyant)
- `scripts/check-site.mjs` — `npm run check:site` (build sonrası): tek h1, alt, title/description/canonical, tekrar eden id, iç link + anchor
- `server.mjs` — üretim girişi (`npm start`): `ASTRO_NODE_AUTOSTART=disabled` ile Astro handler'ını sarar; `compression` (br/gzip), güvenlik başlıkları, SIGTERM'de düzgün kapanma. `/_astro/*` immutable cache adapter'dan
- `src/pages/api/health.ts` — `GET /api/health/` (trailing slash!) → `{status, db}`; DB yoksa 503
- `Dockerfile` (node:24-slim, build → `npm prune --omit=dev` → runtime; USER node; HEALTHCHECK; VOLUME /app/data) · `.dockerignore` · `docker-compose.yml` (Dokploy Compose alternatifi)
- Bağımlılıklar: runtime yalnızca `astro`, `@astrojs/node`, `compression`; geri kalan her şey devDependencies (imaj 531 MB, ~200 MB'ı node:24-slim)
- `src/dev/Styleguide.astro` — `astro.config.mjs`'deki `devRoutes` entegrasyonu ile sadece `astro dev`'de `/styleguide/` (`_` önekli sayfalar Astro'da rota olmaz)
- `src/lib/slug.ts` — Türkçe karakter dönüştürücü `slugify`
- `scripts/new-post.mjs` — `npm run new:post -- "Başlık"` → `src/content/blog/<slug>/index.md` (draft: true); `slug.ts`'yi Node type-stripping ile import eder
- `docs/design-reference/` — Huemint Magazine ekran görüntüleri · `CLAUDE.md` → `AGENTS.md` + bu dosya
- Build: `astro build && pagefind --site dist/client` · statik çıktı `dist/client`, sunucu `dist/server/entry.mjs`
## 4. Kararlar (ADR)
| Tarih | Karar | Gerekçe |
| ---------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| 2026-10-15 | Statik çıktı + `@astrojs/node` ile sadece `/api/views` dinamik | "Öne çıkan = en çok okunan" için sayaç gerekli; site geri kalanı statik ve hızlı |
| 2026-10-15 | Sayaç: SQLite, volume `/app/data` (sürücü: aşağıdaki 2026-10-16 kararı) | Harici servis yok, ev sunucusunda basit ve kalıcı |
| 2026-10-15 | Arama: Pagefind | Statik, sunucusuz, Türkçe destekli |
| 2026-10-15 | Harita: Leaflet + OpenStreetMap | API anahtarı / ücret yok, KVKK dostu |
| 2026-10-15 | İkonlar: astro-icon + Tabler | Tutarlı çizgi seti, anten kulesi ve marka ikonları mevcut |
| 2026-10-15 | Lisans: Kod MIT, içerik CC BY-SA 4.0 | Kaynak gösterilerek serbest kullanım talebi |
| 2026-10-15 | Kanonik alan: apex `ta1sph.info`, www → 301 | SEO tekilleştirme |
| 2026-10-15 | Fontlar self-host (Fontsource: Rubik + Inter) | Performans + gizlilik |
| 2026-10-16 | Ek token'lar: `accent-fill`/`on-accent-fill`, `accent-text` (khaki'de fg'ye döner) | Ölçüm: ink/red 4.46, red-strong/khaki 3.85 → küçük metin AA'yı geçmiyordu. Kırmızı zeminli butonlar ≥19px bold |
| 2026-10-16 | Docker testleri **temiz git klonundan** yapılır (çalışma dizininden değil) | Yoksayılan/commit'lenmemiş dosyalar yerel testte görünmez; Dokploy repo'dan klonlar |
| 2026-10-16 | Sıkıştırma konteyner içinde (`server.mjs` + `compression`), Traefik ayarı yok | Kullanıcının Dokploy'da ek middleware kurmasına gerek kalmaz |
| 2026-10-16 | Docker taban imajı `node:24-slim` (LTS) | `node:sqlite` 24 ve 26'da uyarısız test edildi; 24 LTS Nisan 2028'e kadar destekli |
| 2026-10-16 | Kalıcı veri için Dokploy'da named volume (bind mount değil) | Named volume ilk mount'ta imajdaki `node` sahipliğini alır; bind mount root olur → yazma hatası |
| 2026-10-16 | Yazı başına OG görseli build'de (Satori) — kullanıcı kararı bana bıraktı | Paylaşımlarda başlıklı kart; harici servis yok |
| 2026-10-16 | Favicon = kırmızı kare + siyah anten kulesi (Tabler) | "TA1" 16px'te okunmuyor; vurgu rengi + İletişim ikonuyla tutarlı |
| 2026-10-16 | Fontlar alt kümelenip `public/fonts`'tan; `build.inlineStylesheets: 'always'` | LCP'yi geciktiren render-blocking CSS + 190 KB font; ölçümde FCP 2,3 → ~1 sn |
| 2026-10-16 | Leaflet CSS iletisim.astro'da statik import | `inlineStylesheets: 'always'` dinamik CSS importunu 404'e düşürüyordu |
| 2026-10-16 | noindex sayfalarda canonical yok (404) | 404'ün `/404/` canonical'ı var olmayan URL'yi gösteriyordu |
| 2026-10-16 | Yasal metinler Markdown koleksiyonu (`src/content/legal`), tek dinamik rota | Uzun metin için prose; yeni yasal sayfa = yeni .md |
| 2026-10-16 | Leaflet işaretçisinde döndürme iç elemanda (`.tower-pin`) | CSS `rotate` özelliği Leaflet'in `translate3d`'sinden önce uygulanıp konumu kaydırıyordu |
| 2026-10-16 | Karanlık harita = karolara CSS `invert` filtresi | İkinci karo sağlayıcısı / API anahtarı gerekmez |
| 2026-10-16 | SQLite sürücüsü `node:sqlite` (better-sqlite3 değil) — kullanıcı onayı | Native derleme yok, ek paket yok; Node 26'da uyarısız. Docker imajı Node ≥24 olmalı (A8'de kesinleşecek) |
| 2026-10-16 | Astro `checkOrigin` açık kalıyor | Tarayıcı `Sec-Fetch-Site: same-origin` gönderir; başka sitelerden sayaç şişirme engellenir. curl testlerinde bu başlık eklenmeli |
| 2026-10-16 | Astro 7 Markdown = Sätteri; eklentiler `markdown.processor: satteri({ hastPlugins })` | remark/rehype eklentileri bu işlemcide çalışmaz |
| 2026-10-16 | Okuma süresi `post.body` kelime sayısından (remark eklentisi yok) | Liste sayfalarında `render()` gerekmez, Sätteri'de remark yok |
| 2026-10-16 | Sayfalama `[...page]` + `sayfa/<n>` (Astro `paginate()` değil) | Spec URL'leri `/blog/sayfa/n/`; tek dosyada 1. sayfa + diğerleri |
| 2026-10-16 | Arama UI'ı kendi bileşenimiz (Pagefind JS API), indeks yalnızca `data-pagefind-body` (yazı gövdeleri) | Tasarımla uyum, Türkçe metinler JSON'da |
| 2026-10-16 | Shiki `github-*-high-contrast`, zemin `--surface` | Kod renkleri AA kontrastı |
| 2026-10-16 | Dekoratif dev rakamlar CSS `::before` içeriği | axe/Lighthouse aria-hidden metinde bile kontrast hatası veriyordu |
| 2026-10-16 | Kuruluş/site tanıtımları yalnızca sitelerin kendi ifadelerinden | Uydurma bilgi yok; Telegram kartlarında açıklama yok (doğrulanmadı) |
| 2026-10-16 | Mobil menü native `popover` | Escape/odak/light-dismiss JS'siz |
| 2026-10-16 | Pagefind CLI postbuild (`astro-pagefind` yok) | Daha az bağımlılık; node adapter çıktısı `dist/client` |
| 2026-10-16 | Skill repoya kopyalanmadı, kullanıcı düzeyinde | Çift kopya senkron riski |
| 2026-10-15 | Locator KN41KB99HW → 41.08307 N, 28.91094 E | Harita merkezi |
## 5. İçerik Envanteri
| Slug | Başlık | Kategori | Oluşturma | Güncelleme | Durum |
| ------------------------------ | ----------------------------------------------------- | -------- | ---------- | ---------- | -------------------------- |
| dmr-temel-kavramlar | DMR'ye Giriş: Talkgroup, Timeslot ve Color Code | dmr | 2026-10-01 | — | yayında · örnek · featured |
| roleler-ve-ctcss-tonu | Röle Kullanırken CTCSS Tonu Neden Gerekli? | roleler | 2026-10-08 | 2026-10-15 | yayında · örnek |
| uhf-ground-plane-anten-mantigi | UHF Ground Plane Anten: Çalışma Mantığı ve Boy Hesabı | antenler | 2026-10-14 | — | yayında · örnek · diy |
## 6. Değişiklik Günlüğü (en yeni üstte)
- 2026-10-16 | Yayına Al | İlk yayın: DNS (apex+www), Dokploy uygulaması, Let's Encrypt; canlı doğrulama (sayfalar, API, br, başlıklar, sitemap, RSS) | — (sunucu tarafı)
- 2026-10-16 | Yayına Al (fix) | `.gitignore` `data/` → `/data/`: `src/data/*.json` hiç commit'lenmemişti, Dokploy build'i kırıldı; temiz klon + Docker ile doğrulandı | `.gitignore`, `src/data/`
- 2026-10-16 | Siteyi Kur A8 | Dockerfile, .dockerignore, compose, server.mjs (sıkıştırma + güvenlik başlıkları), /api/health, build-only bağımlılıklar devDeps'e; Docker'da uçtan uca test | `Dockerfile`, `.dockerignore`, `docker-compose.yml`, `server.mjs`, `src/pages/api/health.ts`, `src/lib/views.ts`, `package.json`, `README.md`
- 2026-10-16 | Siteyi Kur A7 | OG görselleri (yazı başına + varsayılan), favicon seti + manifest, robots.txt, font alt kümeleme + preload, CSS inline, site denetim script'i, Lighthouse | `src/lib/og.ts`, `src/pages/{og,og-default.png,robots.txt,site.webmanifest}*`, `scripts/{generate-icons,subset-fonts,check-site}.mjs`, `public/`, `src/styles/fonts.css`, `Seo.astro`, `BaseLayout.astro`, `astro.config.mjs`
- 2026-10-16 | Siteyi Kur A6 | Hakkımda, İletişim (Leaflet harita, gizlenmiş e-posta), Gizlilik/Lisans/Sorumluluk Reddi, 404, LICENSE dosyaları; PageHeader + CodeCopy ortak bileşenleri; axe temiz | `src/pages/{hakkimda,iletisim,[legal],404}.astro`, `src/content/legal/`, `src/data/{about,contact,pages}.json`, `src/components/{PageHeader,CodeCopy,Card}.astro`, `LICENSE*`, `global.css`
- 2026-10-16 | Siteyi Kur A5 | Görüntülenme sayacı (node:sqlite, anonim, 24 sa tekil, bot filtresi), top API, sidebar öne çıkanlar API + yedek; uçtan uca test | `src/lib/views.ts`, `src/pages/api/views/`, `src/components/blog/Sidebar.astro`, `src/pages/blog/[slug].astro`, `src/lib/posts.ts`
- 2026-10-16 | Siteyi Kur A4 | Blog: koleksiyon, liste/kategori/etiket arşivleri + sayfalama, detay (paylaş, TOC, DIY, kod kopyala, lisans satırı), sidebar (Pagefind arama), RSS, ana sayfa son yazılar, 3 örnek yazı; axe temiz | `src/content*`, `src/pages/blog/`, `src/pages/rss.xml.ts`, `src/components/blog/`, `src/lib/{posts,dates,markdown-plugins}`, `src/data/{blog,categories}.json`, `astro.config.mjs`, `global.css`
- 2026-10-16 | Siteyi Kur A3 | Ana sayfa: hero, 4 kuruluş, Telegram, son yazılar (boş durum), site tanıtımları; axe temiz | `src/data/home.json`, `src/components/home/`, `src/components/Section.astro`, `src/pages/index.astro`, `src/lib/data.ts`
- 2026-10-16 | Siteyi Kur A2 | Token'lar, tema anahtarı, SEO bileşeni, layout, header/footer, temel bileşenler, site/social JSON, dev styleguide; axe temiz (2 tema) | `src/styles/`, `src/components/`, `src/layouts/`, `src/data/`, `src/lib/data.ts`, `src/dev/`, `astro.config.mjs`
- 2026-10-16 | Siteyi Kur A1 | İskelet: Tailwind 4, mdx, sitemap, node, icon, rss, fontlar, pagefind, prettier, new:post | `astro.config.mjs`, `package.json`, `scripts/`, `src/lib/slug.ts`, `src/styles/`, `README.md`
- 2026-10-16 | Siteyi Kur A0 | Ortam kontrolü; hafıza + docs kitten projeye kopyalandı | `CLAUDE.md`, `PROJECT_MEMORY.md`, `docs/`
- 2026-10-15 | Kurulum | Skill, CLAUDE.md ve PROJECT_MEMORY.md eklendi | `.claude/`, `CLAUDE.md`, `PROJECT_MEMORY.md`