Tema Geliştirme
VeloCMS teması dediğimiz şey aslında üç React bileşenini (BlogLayout, PostLayout ve PageLayout) ve bir de theme.json manifest dosyasını dışa aktaran bir TypeScript paketinden ibaret. Bütün sözleşme bu kadar basit. PocketBase'i, çoklu kiracılı yönlendirmeyi (multi-tenant routing) ya da ISR'ın nasıl çalıştığını bilmenize gerek yok. Siz sadece layout bileşenlerinizi oluşturun ve manifest'e bağlayın, gerisini VeloCMS halleder.
theme.json manifest dosyası
Her tema bir theme.json dosyasıyla başlar. Mağaza, temanızı anlamak, uyumluluğu doğrulamak ve önizleme kartını oluşturmak için işte bu dosyayı okur. ThemeManifest arayüzünün tamamı src/lib/themes/sdk/types.ts altında bulunuyor. İşte size minimal bir örnek:
{
"$schema": "https://velocms.org/schemas/theme-manifest.json",
"name": "velocms-theme-aurora",
"displayName": "Aurora",
"version": "1.0.0",
"description": "A clean, distraction-free reading theme with subtle gradient accents.",
"author": {
"name": "Jane Dev",
"email": "[email protected]",
"url": "https://janedev.io"
},
"type": "layout",
"category": "personal",
"tags": ["minimal", "reading", "personal-blog"],
"engines": {
"velocms": ">=1.0.0"
},
"preview": {
"thumbnail": "./preview/thumbnail.png",
"screenshots": [
"./preview/blog-listing.png",
"./preview/post-detail.png"
]
},
"exports": {
"components": {
"BlogLayout": "./src/BlogLayout.tsx",
"PostLayout": "./src/PostLayout.tsx",
"PageLayout": "./src/PageLayout.tsx"
}
},
"pricing": {
"model": "free"
}
}Layout bileşen sözleşmeleri
Üç layout bileşeniniz de tipli proplar alır. VeloCMS, gönderileri, site ayarlarını ve üye oturum verilerini bu arayüzler üzerinden size geçirir. Yani sizin herhangi bir veri çekmenize gerek kalmaz. Tipler src/components/themes/types.ts dosyasından geliyor:
import type { BlogLayoutProps } from "@velocms/theme-sdk";
export default function BlogLayout({
posts,
settings,
siteUrl,
searchEnabled,
member,
currentPage,
totalPages,
}: BlogLayoutProps) {
return (
<main>
<h1>{settings?.site_name ?? "My Blog"}</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>
<a href={`${siteUrl}/blog/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</main>
);
}import type { PostLayoutProps } from "@velocms/theme-sdk";
export default function PostLayout({
post,
settings,
siteUrl,
jsonLd,
member,
relatedPosts,
}: PostLayoutProps) {
return (
<article>
<h1>{post.title}</h1>
{/* jsonLd is a pre-built schema object — pass it to a <script> tag */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<div dangerouslySetInnerHTML={{ __html: post.content_html ?? "" }} />
</article>
);
}OKLCH token sistemi
VeloCMS, tüm renk token'ları için OKLCH kullanır. Bu sadece estetik bir tercih değil; OKLCH size algısal olarak tutarlı renk skalaları sunar. Yani marka renginizin %30 açıklıktaki hali, HSL'de olduğu gibi tuhaf, karanlık bir karmaşaya dönüşmez, gerçekten de ana rengin %30'u kadar parlak olur. Her temanın globals.css içinde tanımlanmış şu CSS değişkenlerine erişimi var:
/* Core semantic tokens — always available in theme components */
:root {
--background: oklch(0.98 0 0);
--foreground: oklch(0.15 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.15 0 0);
--muted: oklch(0.96 0.005 240);
--muted-foreground: oklch(0.55 0.01 240);
--border: oklch(0.9 0.005 240);
--ring: oklch(0.55 0.16 264);
--primary: oklch(0.55 0.16 264);
--primary-foreground: oklch(0.98 0 0);
}
/* Dark mode — automatically applied via .dark class on <html> */
.dark {
--background: oklch(0.12 0.005 240);
--foreground: oklch(0.95 0 0);
/* ... */
}Tema bileşenlerinizde bu token'lara referans veren Tailwind sınıflarını kullanın: bg-background, text-foreground, border-border gibi. Sakın hex kodlarını doğrudan yazmayın. Eğer öyle yaparsanız, temanız kullanıcının aydınlık/karanlık mod ayarına uymaz ve önizlemede bozuk görünür.
DemoFixtures ile yerel önizleme
Temanızı mağazaya göndermeden önce gerçekçi görünen verilerle test etmek oldukça kolay. Tema SDK'sı, sentetik gönderiler, site ayarları ve üye oturum verileri içeren bir DemoFixtures nesnesini dışa aktarır. Geliştirme yaparken bunu layout bileşenlerinize prop olarak geçmeniz yeterli:
import { DemoFixtures } from "@velocms/theme-sdk/testing";
import BlogLayout from "../src/BlogLayout";
// Use the DemoFixtures for local development
export default function Preview() {
return (
<BlogLayout
posts={DemoFixtures.posts}
settings={DemoFixtures.settings}
siteUrl="http://localhost:3000"
searchEnabled={false}
member={null}
currentPage={1}
totalPages={1}
/>
);
}Çalışan bir VeloCMS örneğindeki /preview/themes/[slug] rotası da aslında aynı işi yapar: kayıtlı temanızı yükler ve DemoFixtures verileriyle render eder. Mağazadaki küçük resim de zaten bu şekilde oluşturuluyor.
Mağazaya gönderim
Yayınlamaya hazır olduğunuzda, VeloCMS'te /developers adresine gidin. Gönderim süreci sizden theme.json manifest dosyanızı, 600x400 boyutunda bir küçük resim, en az iki tam sayfa ekran görüntüsü ve kısa bir açıklama isteyecek. Onay süreci 2-5 iş günü sürer; listelemeden önce erişilebilirlik, karanlık mod desteği ve mobil uyumluluk gibi konuları inceliyoruz.
Gelir paylaşımı 80/20 şeklinde: her satışın %80'i size kalır, %20'sini VeloCMS alır. Ücretsiz temalarda herhangi bir gelir paylaşımı söz konusu değil. Ödemeler aylık olarak Stripe Connect üzerinden yapılıyor, bu yüzden gönderim yaparken bir Stripe hesabınızın olması gerekecek.
Referans
theme.json manifesti — tüm alanlar
| Alan | Tip | Gerekli | Açıklama |
|---|---|---|---|
| `name` | `string` | Evet | Temanızın benzersiz kimliği. npm formatında olmalı. |
| `version` | `string` | Evet | Semantik versiyonlama (örn. "1.0.0"). |
| `description` | `string` | Evet | Temanızın kısa, tek cümlelik özeti. |
| `author` | `string` | Evet | Sizin veya şirketinizin adı. |
| `authorUrl` | `string` | Hayır | Web sitenize veya portfolyonuza bir bağlantı. |
| `tags` | `string[]` | Hayır | Temayı tanımlayan bir string dizisi (örn. "minimal", "dark", "portfolio"). |
| `price` | `number` | Evet | USD sent cinsinden fiyat (örn. $10.00 için 1000). Ücretsiz için 0. |
| `engine` | `string` | Evet | Temanın uyumlu olduğu VeloCMS versiyonu. "*" kullanın. |
Layout bileşen propları
Bunlar, VeloCMS'in üç layout bileşeninize geçtiği TypeScript prop tiplerinin birebir aynısıdır. Tasarımınızı bunlara göre yapın; asıl sözleşme budur, yukarıdaki rehber bölümlerindeki örnekler değil.
| Arayüz | Prop | Tip | Opsiyonel | Açıklama |
|---|---|---|---|---|
| `BlogLayoutProps` | `posts` | `Post[]` | Hayır | Yayınlanmış tüm gönderilerin bir dizisi. |
| `BlogLayoutProps` | `site` | `SiteSettings` | Hayır | Global site ayarları (başlık, açıklama vb.). |
| `BlogLayoutProps` | `member` | `MemberSession | null` | Hayır | Mevcut giriş yapmış üye veya null. |
| `PostLayoutProps` | `post` | `Post` | Hayır | Mevcut sayfanın tam gönderi nesnesi. |
| `PostLayoutProps` | `site` | `SiteSettings` | Hayır | Global site ayarları. |
| `PostLayoutProps` | `member` | `MemberSession | null` | Hayır | Mevcut giriş yapmış üye veya null. |
| `PageLayoutProps` | `page` | `Page` | Hayır | Mevcut sayfanın tam sayfa nesnesi. |
| `PageLayoutProps` | `site` | `SiteSettings` | Hayır | Global site ayarları. |
| `PageLayoutProps` | `member` | `MemberSession | null` | Hayır | Mevcut giriş yapmış üye veya null. |
OKLCH token referansı
| CSS değişkeni | Varsayılan (aydınlık) | Varsayılan (karanlık) | Kullanım |
|---|---|---|---|
| `--background` | `oklch(1 0 0)` | `oklch(0.17 0.01 230)` | Sayfa arka plan rengi. |
| `--foreground` | `oklch(0.17 0.01 230)` | `oklch(0.98 0.01 230)` | Ana metin rengi. |
| `--card` | `oklch(1 0 0)` | `oklch(0.17 0.01 230)` | Kartlar ve konteynerler için arka plan. |
| `--card-foreground` | `oklch(0.17 0.01 230)` | `oklch(0.98 0.01 230)` | Kartların içindeki metin rengi. |
| `--popover` | `oklch(1 0 0)` | `oklch(0.17 0.01 230)` | Açılır pencereler ve menüler için arka plan. |
| `--popover-foreground` | `oklch(0.17 0.01 230)` | `oklch(0.98 0.01 230)` | Açılır pencerelerin içindeki metin rengi. |
| `--primary` | `oklch(0.45 0.15 260)` | `oklch(0.7 0.2 260)` | Butonlar, linkler için ana marka rengi. |
| `--primary-foreground` | `oklch(0.98 0.01 230)` | `oklch(0.2 0.02 260)` | Ana renkli arka planlar üzerindeki metin rengi. |
| `--border` | `oklch(0.8 0.01 240)` | `oklch(0.25 0.02 240)` | İnce kenarlıklar ve ayırıcılar. |
| `--input` | `oklch(0.8 0.01 240)` | `oklch(0.25 0.02 240)` | Girdi alanları için kenarlık rengi. |
Token'lara eşlenen Tailwind sınıfları
| Tailwind sınıfı | CSS değişkeni | Kullanım amacı |
|---|---|---|
| `bg-background` | `--background` | Ana sayfa arka planı. |
| `text-foreground` | `--foreground` | Ana metin. |
| `bg-card`, `text-card-foreground` | `--card`, `--card-foreground` | Kartlar, konteynerler. |
| `bg-popover`, `text-popover-foreground` | `--popover`, `--popover-foreground` | Açılır menüler, diyaloglar. |
| `bg-primary`, `text-primary-foreground` | `--primary`, `--primary-foreground` | Butonlar, etiketler, linkler. |
| `border-border` | `--border` | Ayırıcılar, dış hatlar. |
| `border-input` | `--input` | Form girdileri. |
Tema gönderim kontrol listesi
| Gereksinim | Nasıl doğrulanır |
|---|---|
| Geçerli `theme.json` | Tema dizininizde `npx @velocms/theme-sdk validate` komutunu çalıştırın. |
| Karanlık mod desteği | İşletim sisteminizi karanlık moda alıp tüm sayfaları kontrol edin. |
| Mobil uyumluluk | Tarayıcı geliştirici araçlarını kullanarak iPhone, iPad ve Android görünümlerini kontrol edin. |
| Erişilebilirlik (WCAG AA) | Kontrast ve ARIA sorunlarını kontrol etmek için WAVE veya Axe gibi bir tarayıcı eklentisi kullanın. |
| Konsol hatası yok | Tarayıcı konsolunu açın ve temanızda gezinin. Konsol boş olmalı. |
| OKLCH token'ları kullanılıyor | Kodunuzda `#` veya `rgb(` araması yapın. Elle girilmiş renklere izin verilmez. |
Dahili tema implementasyonları
| Tema slug'ı | Şunlar için ideal | Şunun için buradan başlayın… |
|---|---|---|
| `terminal` | Minimalist bloglar, yazarlar. | Mümkün olan en basit implementasyon. |
| `aurora` | Fotoğraf ağırlıklı bloglar, portfolyolar. | `next/image` ile gelişmiş resim yönetimi. |
| `origin` | Kurumsal bloglar, pazarlama siteleri. | Karmaşık layout'lar ve çok sayıda özel bileşen. |