Bu sayfa bir partner uygulamasını sıfırdan test mağazasında çalıştırıp Tecof barındırmasına dağıtmayı adım adım anlatır. Örnekler Next.js App Router ve TypeScript kullanır.
Gerekenler
| Gereksinim | Not |
|---|---|
| Node.js 20+ | @tecof/cli Node ≥20 ister; uygulamanızın kullandığı @tecof/app-sdk Node ≥18 ile çalışır (bağımlılıksız; node:crypto + fetch) |
| Aktif partner üyeliği | Uygulama geliştirici programına kayıtlı, durumu active partner. Bkz. Uygulama Geliştirme |
| Test mağazası | Ekip üyesi olduğunuz bir Tecof mağazası. Onaysız uygulama yalnız test mağazalarına kurulur |
1. CLI Kurulumu#
npm i -g @tecof/cli
tecof --help2. Giriş: tecof login#
CLI, tarayıcıda onaylanan bir cihaz akışıyla giriş yapar; parola terminale yazılmaz.
tecof login
tecof whoamiCLI bir doğrulama kodu (ABCD-EFGH biçiminde) ve onay adresi (https://app.tecof.com/cli?code=ABCD-EFGH biçiminde) gösterir.
Akış:
- CLI
POST /api/developer/cli/device { clientName }ile cihaz kodu alır:{ deviceCode, userCode: "ABCD-EFGH", verificationUri, expiresIn: 600, interval: 5 }. verificationUriadresini açıp panelde oturum açmış olarak isteği onaylarsınız ya da reddedersiniz. Onay ekranı CLI adını, IP'yi, istek zamanını, yetkilendirilecek hesabı ve (varsa) partner hesabını gösterir. Girişin kendisi partner üyeliği istemez; uygulama komutları istek anında aktif partner üyeliği arar.- CLI 5 saniyede bir
POST /api/developer/cli/token { deviceCode }ile yoklar:
| Yanıt | Anlamı |
|---|---|
428 authorization-pending | Henüz onaylanmadı, yoklama sürer |
403 authorization-denied | İstek panelde reddedildi |
410 device-code-expired | 10 dakika içinde onaylanmadı; tecof login ile yeniden başlayın |
200 { token: "tcfd_…", expiresAt, partner: { id, name } | null, user: { id, email } } | Giriş tamam; partner üyeliği olmayan kullanıcıda partner null |
Cihaz token'ı (tcfd_…) kişisel hesabınıza bağlıdır; 30 gün geçerlidir ve 14 gün kullanılmazsa düşer. Token işletim sisteminin anahtarlığında (macOS Anahtar Zinciri, Linux Secret Service; yoksa ~/.config/tecof/credentials.json, izin 0600) saklanır; ~/.config/tecof/config.json yalnız üst bilgiyi (apiUrl, tokenExpiresAt, partner, user) tutar. Farklı bir API adresine (ör. yerel backend) bağlanmak için tecof login --api <url> kullanın. Ayrıntılar: Güvenlik ve CI.
Açık CLI oturumlarınızı panelde https://app.tecof.com/cli?tab=tokens sayfasında, tecof tokens ls / tecof tokens revoke <id> ile ya da API'de GET /api/developer/cli/tokens ve DELETE /api/developer/cli/tokens/:id ile yönetebilirsiniz. tecof logout geçerli token'ı sunucuda da iptal eder.
3. Proje Oluşturma: tecof app init#
tecof app init isbasi-demo --template starter --name "İşbaşı Demo"
cd isbasi-demo
npm install| Seçenek | Açıklama |
|---|---|
[dir] | Proje klasörü |
--template starter | Başlangıç şablonu |
--template actions | Aksiyon örnekleri içeren şablon |
--name | Uygulama adı |
tecof app init uygulamayı geliştirici hesabınızda sunucuda oluşturur, tecof.app.json içine id / clientId bağını yazar ve istemci sırrını .env.local dosyasına kaydeder. İstemci sırrı yalnız .env.local dosyasında tutulur ve commit edilmez.
Mevcut bir uygulamaya bağlanmak için tecof app link --app <id> kullanın. İstemci sırrı yalnız oluşturma ve döndürme anında bir kez gösterildiğinden app link sırrı sunucudan alamaz: CLI ya tecof app secret rotate ile yeni sır almanızı önerir ya da elinizdeki sırrı elle girmenizi kabul eder.
Proje yapısı#
starter şablonunun ürettiği düzen (@tecof/cli 0.2.0). actions şablonu buna ek olarak app/actions/[key]/ (iframe aksiyonu) ve app/api/actions/[key]/route.ts (API aksiyonu) içerir.
isbasi-demo/
├── tecof.app.json # uygulama yapılandırması (commit edilir)
├── .env.local # TECOF_CLIENT_ID / TECOF_CLIENT_SECRET / TECOF_API_URL (commit EDİLMEZ)
├── next.config.ts · postcss.config.mjs · tsconfig.json
├── lib/
│ ├── tecof.ts # TecofApp örneği + withSession yardımcısı (yalnız sunucu)
│ └── settings-model.ts # ayar formunun tek şeması (istemci + sunucu)
└── app/
├── layout.tsx · providers.tsx # Geist + TecofAppProvider (@tecof/app-ui)
├── globals.css # Tailwind 4 + React Suite + @tecof/app-ui katmanları
├── app-shell.tsx # AppShell: başlık, durum, sekmeler
├── page.tsx # genel bakış
├── settings/ # ayarlar sayfası + AppForm
└── api/
├── session/route.ts # oturum token'ı ile korunan örnek uç
├── settings/route.ts # validateOnServer + Vault
└── webhooks/route.ts # createWebhookHandler (webhooks.path)Arayüz kuralları için Tasarım kimliği, form ve doğrulama için Formlar ve şema.
Ortam değişkenleri#
# .env.local
TECOF_CLIENT_ID=tcfa_xxxxxxxxxxxxxxxx
TECOF_CLIENT_SECRET=tcfs_xxxxxxxxxxxxxxxx
TECOF_API_URL=https://api.tecof.com
# TECOF_PREVIOUS_CLIENT_SECRET=tcfs_... # yalnız harici barındırmada, sır döndürmeden sonraki 24 saatSDK örneği#
// lib/tecof.ts — yalnız sunucu kodunda içe aktarın
import { TecofApp } from "@tecof/app-sdk";
export const tecof = new TecofApp({
clientId: process.env.TECOF_CLIENT_ID!,
clientSecret: process.env.TECOF_CLIENT_SECRET!,
previousClientSecret: process.env.TECOF_PREVIOUS_CLIENT_SECRET, // isteğe bağlı: sır döndürme geçişi
apiUrl: process.env.TECOF_API_URL, // verilmezse TECOF_API_URL okunur
});İstemci sırrını taşıyan değişkenleri asla NEXT_PUBLIC_ önekiyle tanımlamayın; tarayıcı paketine girer.
4. Test Mağazasında Geliştirme: tecof app dev#
Test mağazasını tanımlayın#
tecof.app.json içindeki testStores dizisine mağaza kimliğini (merchantId) ekleyin. Yalnız ekip üyesi olduğunuz mağazalar kabul edilir; listesini GET /api/developer/test-stores döner.
{
"testStores": ["66f0c0ffee0000000000abcd"]
}Yapılandırmayı sunucuya gönderin:
tecof app config pushYerel sunucu ve tünel#
tecof app dev --tunnel cloudflaredtecof app dev yerel geliştirme sunucunuzu başlatır (varsayılan port 3000, --port ile değişir), tünelle dışarı açar ve tünel adresini uygulamanın devUrl değeri olarak kaydeder (PUT /api/developer/apps/:id/dev-url). Kurallar:
devUrl8 saat geçerlidir; süre dolunca komutu yeniden çalıştırın.devUrlyalnız test mağazası kurulumlarında geçerlidir ve oradaappUrl'in yerine geçer: panel iframe'i, webhook teslimatları ve API aksiyonları tünel adresinize gider (adres teslimat anında çözülür). Diğer mağazalar her zamanappUrl'i kullanır.
--tunnel | Davranış |
|---|---|
cloudflared | Cloudflare tüneli açar |
none | Tünel açmaz |
<url> | Kendi açtığınız tünel adresini (ör. başka bir tünel aracı) devUrl olarak kaydeder |
Böylece test mağazasında sipariş oluşturduğunuzda order.paid gibi webhook'lar ve panelden çalıştırdığınız aksiyonlar doğrudan yerel sunucunuza düşer. Tünel açmadan yalnız imza mantığını denemek için Aksiyonlar → Yerelde test bölümündeki imzalı curl örneğini kullanabilirsiniz.
Test mağazasına kurun#
Panelde kurulum bağlantısını açın:
https://app.tecof.com/app/apps/install/tcfa_xxxxxxxxxxxxxxxxOnay ekranı istenen kapsamları ve (varsa) planları gösterir. Onaydan sonra uygulamanız app.installed webhook'unu alır ve panelde "Uygulamalarım" altında açılır.
5. Dağıtım#
Tecof barındırmalı (hosting: "tecof") bir uygulamayı iki yolla yayınlarsınız:
| Yol | Ne yapar | Durum |
|---|---|---|
tecof app push | Yalnız değişen dosyaları yükler ve numaralı bir sürüm açar; staged derlemeyi önizleyip yeniden derlemeden canlıya alırsınız, gerekirse anında geri alırsınız | Önerilen |
tecof app deploy | Tüm kaynağı arşivleyip yükler ve doğrudan yayınlar | Çalışmaya devam eder |
Sürümler ve Geri Alma: tecof app push#
tecof app push -m "Fatura listesi" # staged sürüm açar, ör. v5
tecof app versions # sürüm listesi
tecof app promote v5 # yeniden derlemeden canlıya alır
tecof app rollback # bir önceki canlı sürüme döner
tecof app logs v5 # sürümün derleme günlüğü- Uygulamanın alan kimliği
app_<tecof.app.json içindeki id>olur;tecof spaces ls --kind appuygulama alanlarını listeler. - Her push
maindalının o anki hâlinin üstüne kurulur ve klasör istenen son durum sayılır: klasörde olmayan dosyalar depodan silinir. Uygulamalarda.tecof/klasörü ve yerel taban kullanılmaz. tecof.app.jsonpush ile gönderilmez; staged kod canlıdaki yapılandırmayı değiştirmesin diye. Yapılandırma değiştiysetecof app config pushçalıştırın.- Depo, Vercel projesi, alan adı ve ortam değişkenleri yoksa ilk push onları ilk
tecof app deploygibi kurar. Ortam değişkenleri (aşağıdaki tablo) her push'ta derlemeden önce yeniden yazılır. - Staged sürüm tam bir üretim derlemesidir ama alan adı almaz.
tecof app promote vNalan adlarını yeniden derlemeden bu sürüme çevirir vemaindalını sürümün commit'ine hızlı ileri alır.--prodcommit'i doğrudanmaindalına yazar ve derleme bitince canlıya çıkar. promote,rollbackvepush --prodonay ister; ajan ve CI ortamlarında--yesgerekir.tecof app deployyayınları da sürüm listesinde (source: "cli") görünür; geri alma onlarda da çalışır.- Kendi sunucunuzda barındırılan uygulamalarda (
hosting: "external") sürüm komutları çalışmaz. - Geliştirici portalında uygulamanın Sürümler sekmesi aynı sürümleri gösterir; canlıya alma ve geri alma oradan da yapılır.
Kurallar ve ayrıntılar: Sürümler, Canlıya Alma ve Geri Alma. CI'dan yayın: GitHub Actions örneği.
Tek Adımda Dağıtım: tecof app deploy#
tecof app deploy -m "İlk sürüm"
tecof app deployments # dağıtım listesi ve durumları
tecof app logs <deploymentId> # derleme günlüğütecof app deploy önce tecof.app.json dosyasını gönderir, sonra Tecof barındırmasına şu adımlarla dağıtır:
- CLI projeyi kök klasörlü bir
.tar.gzarşivine paketler ve yükler (POST /api/developer/apps/:id/deployments, multipartbundle+message). - İlk dağıtımda Tecof sizin için şunları açar:
- GitHub org reposu
tecof-app-<slug> - Vercel projesi
tecof-app-<slug> - Ortam değişkenleri (aşağıdaki tablo)
- Alan adı
<slug>.apps.<Tecof alan adı>(varsayılan alt alanapps) — örneğinisbasi.apps.tecof.site. Alan adı kurulamazsa uygulamahttps://tecof-app-<slug>.vercel.appadresinde yayınlanır
- GitHub org reposu
- Dosyalar tek commit ile varsayılan dala yazılır; Vercel üretim derlemesini başlatır. Önceki dağıtımda olup yeni pakette bulunmayan dosyalar repodan silinir (repo her dağıtımda paketin birebir kopyasıdır).
- Dağıtım durumu:
queued→building→ready|error|canceled. Durumreadyolunca uygulamanınappUrldeğeri otomatik güncellenir.
Paket sınırları
| Kural | Değer |
|---|---|
| Hariç tutulanlar | node_modules, .next, .git, .vercel, .env* |
| Toplam boyut | ≤ 25 MB |
| Dosya sayısı | ≤ 3000 |
| Dosya başına | ≤ 5 MB |
.env* dosyaları yüklenmez. Sırlar dağıtım ortamına Tecof tarafından verilir:
| Değişken | İçerik |
|---|---|
TECOF_CLIENT_ID | İstemci kimliği |
TECOF_CLIENT_SECRET | İstemci sırrı |
TECOF_API_URL | Tecof API adresi |
TECOF_APP_URL | Uygulamanın yayın adresi |
NEXT_PUBLIC_TECOF_CLIENT_ID | İstemci kimliği (tarayıcı) |
NEXT_PUBLIC_TECOF_API_URL | Tecof API adresi (tarayıcı) |
Sırrı döndürdüğünüzde (tecof app secret rotate) Vercel ortam değişkeni güncellenir ve yeniden dağıtım tetiklenir.
Kendi sunucunuz (hosting: "external")#
hosting: "external" seçildiğinde appUrl zorunludur ve https:// olmalıdır (geliştirmede yalnız http://localhost / http://127.0.0.1 kabul edilir). Dağıtım sizin sorumluluğunuzdadır; yukarıdaki ortam değişkenlerini kendiniz tanımlarsınız.
CLI Komutları#
| Komut | Açıklama |
|---|---|
tecof login [--api <url>] [--no-browser] | Cihaz akışıyla giriş |
tecof logout | Token'ı sunucuda iptal eder ve yerelden siler |
tecof whoami | Giriş yapılan kullanıcı ve partner |
tecof status · tecof doctor | Bağlı alan ve oturum özeti · ortam denetimi |
tecof app init [dir] [--template starter|actions] [--name <ad>] [--slug <slug>] | Uygulamayı sunucuda oluşturur, şablondan proje açar, sırrı .env.local'e yazar |
tecof app link [--app <id|clientId|slug>] | Klasörü mevcut bir uygulamaya bağlar (sırrı alamaz; döndürme ya da elle giriş) |
tecof app info | Bağlı uygulamanın bilgileri |
tecof app config push | tecof.app.json'u sunucuya gönderir; art arda hatalar yüzünden pasife alınmış webhook aboneliklerini yeniden etkinleştirir |
tecof app dev [--port <n>] [--tunnel cloudflared|none|<url>] | Yerel sunucu (varsayılan 3000) + tünel + devUrl kaydı |
tecof app push [-m <mesaj>] [--prod] | Yalnız değişen dosyaları yükler, numaralı sürüm açar (varsayılan staged) |
tecof app versions [vN] | Sürüm listesi ya da tek sürümün durumu |
tecof app promote vN · tecof app rollback [vN] | Sürümü yeniden derlemeden canlıya alır · önceki canlı sürüme döner |
tecof app deploy [-m <mesaj>] | Tüm kaynağı paketleyip doğrudan yayınlar |
tecof app deployments | app deploy dağıtımlarının listesi |
tecof app logs <vN|deploymentId> | Sürümün ya da dağıtımın derleme günlüğü |
tecof app secret rotate | İstemci sırrını döndürür (eski sır 24 saat geçerli kalır) |
tecof app open [--install] | Uygulamayı geliştirici portalında ya da kurulum sayfasında açar |
tecof spaces ls · tecof tokens … · tecof setup agent | Alanlar, CI token'ları, kodlama ajanı kurulumu |
tecof theme … | Tema komutları: Tema Geliştirme: Hızlı Başlangıç |
Tüm komutlar, seçenekler, çıkış kodları ve JSON makbuzları: CLI Başvurusu.
tecof.app.json Referansı#
Yapılandırma tecof app config push, tecof app deploy ya da geliştirici API'sinin PUT /api/developer/apps/:id/config ucuyla yazılır. Sunucu dosyayı doğrular, bilinmeyen alanları atar ve hataları şu biçimde döner:
{
"success": false,
"messageCode": "invalid-app-config",
"data": {
"issues": [
{ "path": "actions[0].key", "code": "…", "message": "…" }
]
}
}Tam örnek#
{
"id": "6720aa00bb11cc22dd33ee44", // portal/CLI bağı (isteğe bağlı, sunucu yok sayar)
"clientId": "tcfa_xxxxxxxxxxxxxxxx", // bilgi amaçlı
"name": "Logo İşbaşı",
"slug": "isbasi",
"hosting": "tecof", // "tecof" | "external"
"appUrl": "https://isbasi.apps.tecof.site", // external'da zorunlu; tecof'ta dağıtım sonrası otomatik
"embedded": true,
"scopes": ["orders:read", "customers:read", "products:read"],
"webhooks": {
"path": "/api/webhooks",
"events": ["order.paid", "order.cancelled", "order.refunded"]
},
"actions": [
{
"key": "create-invoice", "type": "iframe", "placement": "order.detail",
"title": { "tr": "İşbaşı'nda fatura kes", "en": "Create İşbaşı invoice" },
"path": "/actions/create-invoice", "presentation": "modal"
}
],
"navigation": [
{ "label": { "tr": "Faturalar", "en": "Invoices" }, "path": "/invoices" }
],
"settings": [
{ "key": "apiKey", "label": { "tr": "API anahtarı", "en": "API key" }, "type": "secret", "required": true },
{ "key": "invoiceMode", "label": { "tr": "Fatura tipi", "en": "Invoice mode" }, "type": "select",
"options": [
{ "value": "draft", "label": { "tr": "Taslak", "en": "Draft" } },
{ "value": "issued", "label": { "tr": "Kesilmiş", "en": "Issued" } }
] }
],
"appEvents": {
"publishes": [
{ "name": "invoice.created", "description": { "tr": "Fatura oluşturuldu", "en": "Invoice created" } }
],
"subscribes": ["app.kargo.shipment.created"]
},
"plans": [
{
"key": "standart", "name": { "tr": "Standart", "en": "Standard" },
"description": { "tr": "Aylık plan", "en": "Monthly plan" },
"price": 199, "currency": "TRY", "interval": "month", "trialDays": 14,
"features": [{ "tr": "Sınırsız fatura", "en": "Unlimited invoices" }]
}
],
"listing": {
"shortDescription": { "tr": "Siparişleri İşbaşı'nda faturalayın", "en": "Invoice orders in İşbaşı" },
"description": { "tr": "…", "en": "…" },
"category": "accounting",
"supportEmail": "destek@ornek.com",
"supportUrl": "https://ornek.com/destek",
"privacyUrl": "https://ornek.com/gizlilik",
"websiteUrl": "https://ornek.com",
"media": { // isteğe bağlı, yalnız birinci parti; yazılmayan görsel store-assets/ varsayılanı
"icon": "store-assets/icon.png",
"cover": "store-assets/cover.png",
"screenshots": ["store-assets/screenshots/01-genel-bakis.png", "store-assets/screenshots/02-faturalar.png"]
}
},
"testStores": ["66f0c0ffee0000000000abcd"]
}Alanlar#
| Alan | Tip | Kural |
|---|---|---|
id | string | İsteğe bağlı; CLI/portal bağı. Sunucu yok sayar |
clientId | string | Bilgi amaçlı (tcfa_…) |
name | string | Uygulama adı |
slug | string | ^[a-z][a-z0-9-]{2,39}$; global tekil; oluşturulduktan sonra değişmez. Metafield namespace'i, uygulama olayı öneki ve barındırma alan adı bundan türer |
hosting | "tecof" / "external" | Tecof barındırması ya da kendi sunucunuz |
appUrl | string | external'da zorunlu; tecof'ta dağıtım ready olunca otomatik yazılır |
embedded | boolean | Panelde iframe arayüzü var mı |
scopes | string[] | Yalnız uygulamaya açık kapsamlar. Bkz. Kapsamlar |
webhooks.path | string | Webhook teslimat yolu (appUrl'e göre). Tanımlı değilse yaşam döngüsü olayları (app.installed vb.) ve uygulama olayları da teslim edilemez |
webhooks.events | string[] | Olay kataloğundan; her olayın gerektirdiği okuma kapsamı scopes içinde olmalı. * kapalı. Bkz. Webhook'lar |
actions | object[] | En fazla 12. Bkz. Aksiyonlar |
navigation | object[] | En fazla 8; { label: { tr, en }, path } |
settings | object[] | Yerel ayar formu, en fazla 30 alan; select için options: [{ value, label }]. Bkz. Ayarlar |
appEvents.publishes | object[] | { name, description: { tr, en } }. Bkz. Uygulamalar Arası İletişim |
appEvents.subscribes | string[] | app.<slug>.<ad> ya da app.<slug>.* |
plans | object[] | En fazla 4; boşsa uygulama ücretsizdir. Bkz. Ücretlendirme |
listing.shortDescription, listing.description | { tr, en } | Katalog metinleri |
listing.category | string | Mağazada bu sırayla gösterilir: accounting (Muhasebe), shipping (Kargo ve Lojistik), management (Yönetim), marketing (Pazarlama), marketplace (Pazaryeri), other (Diğer). Yazılmazsa other. Eski anahtarlar hâlâ kabul edilir ama kullanmayın: invoicing → accounting, analytics / crm / automation → management olarak kaydedilir ve yanıtta category-deprecated uyarısı döner. Listede olmayan değer yapılandırmayı reddeder (invalid-value) |
listing.supportEmail, supportUrl, privacyUrl, websiteUrl | string | Destek ve yasal bağlantılar |
listing.media.icon, listing.media.cover | string | Yalnız birinci parti uygulamada kullanılır. Repodaki ikon (512×512) ve kapak (1600×900, logosuz) görselinin repo köküne göre yolu: / ile başlamaz; . ya da .. bölümü, boş bölüm ve \ içermez; en fazla 200 karakter, uzantı png / jpg / jpeg / webp. Yazılmazsa store-assets/icon.png ve store-assets/cover.png; yazılan ama repoda olmayan yol missing olur, varsayılana düşmez. Repodaki tecof.app.json'da listing.media hiç yoksa Tecof'ta saklı yapılandırmadaki geçerlidir. Bkz. Mağaza Görselleri |
listing.media.screenshots | string[] | En fazla 8, yinelenmeyen ekran görüntüsü yolu (1280×800), yazıldığı sırayla; yol kuralları ve çözüm sırası aynı. Yazılmazsa store-assets/screenshots/ içindeki görseller ad sırasıyla |
testStores | string[] | Mağaza kimlikleri; yalnız ekip üyesi olduğunuz mağazalar kabul edilir |
Kurallar#
- Tüm
pathalanlarıappUrl'e göredir ve/ile başlar. Mutlak URL verileceksehttps://zorunludur; yalnız geliştirme adresi olarakhttp://localhostvehttp://127.0.0.1kabul edilir. scopesyalnız uygulama kapsam listesinden seçilir; kapalı kapsamlar (code:*,sandbox:run,deploy:write,memory:*,domains:write,ai:generate) reddedilir.- Kapsam artışı mevcut kurulumlara otomatik geçmez. Kurulum
pendingScopesalır; mağaza onaylayana kadar eski kapsamla çalışır. Kapsam azalması anında uygulanır. - Onaylanmış bir uygulamada
listingveplansdeğişiklikleri canlıya hemen yansır; kapsam artışı yeniden inceleme ister (inceleme sürerken mevcut sürüm yayında kalır). Bkz. Yayınlama ve İnceleme. - Birinci parti uygulamalarda Tecof mağaza görsellerini (
listing.mediayolları ya dastore-assets/varsayılanları) repodan kendisi çeker: oluşturmada ya da repoya bağlamada, yöneticinin Repodan çek işleminde ve her başarılı üretim dağıtımından sonra. Partner uygulamalarında ikon ve ekran görüntüleri portaldan ya da medya uçlarından yüklenir. Bkz. Mağaza Görselleri.
Sonraki Adımlar#
- Kimlik Doğrulama ve Kapsamlar — oturum token'ı ve imza doğrulama
- API ile Veri Erişimi — sipariş ve müşteri okuma
- Webhook'lar —
order.paiddinleme - Örnek Uygulama: Logo İşbaşı — uçtan uca örnek