یک توکن API را داخل JavaScript صفحه میگذارید؛ دمو کار میکند و پروژه تحویل میشود. چند هفته بعد توکن از DevTools برداشته میشود، Webhook یک سفارش را دوبار میفرستد، موجودی منفی میشود و تیم نمیداند منبع حقیقت کدام سیستم است. مشکل «کمبود کدنویسی» نبود؛ افزونهای بدون مرز اعتماد، قرارداد داده و برنامه خرابی ساخته شده بود.
توسعه سایتساز با CSS، JavaScript یا API میتواند فاصله میان قابلیت آماده و نیاز واقعی کسبوکار را پر کند؛ اما فقط وقتی لایه توسعه درست انتخاب شود. هدف این راهنما افزودن کد به هر قیمت نیست. یاد میگیرید نیاز را به Capability قابلآزمون تبدیل کنید، کمپیچیدگیترین Extension point را انتخاب کنید، Secret و داده حساس را از Browser دور نگه دارید، API و Webhook قابلاتکا بسازید و پیش از قفلشدن، مسیر خروج را تمرین کنید.
منظور از توسعه سایتساز با کد و API چیست؟
«سایتساز» یک معماری واحد نیست. ممکن است سرویس SaaS بسته، فروشگاهساز دارای App platform، CMS متنباز با Page builder یا Frontend بصری متصل به Backend خارجی باشد. توسعهپذیری نیز میتواند فقط CSS سفارشی، اجرای JavaScript در Browser، Embed در iframe، Function سمت سرور، App رسمی، REST/GraphQL API، Webhook یا خروجی Headless باشد.
بنابراین پیش از نوشتن کد این شش مرز را ثبت کنید:
- مرز اجرا: Browser، Backend پلتفرم یا سرویس بیرونی؛
- مرز داده: چه دادهای خوانده یا نوشته میشود و منبع حقیقت کجاست؛
- مرز هویت: کاربر، مدیر، App یا سرویس با چه مجوزی عمل میکند؛
- مرز چرخه عمر: نسخه API، Release، Deprecation و Rollback؛
- مرز عملیات: Log، Alert، Retry، Reconciliation و Support؛
- مرز خروج: کد، داده، URL، Asset و Workflow چگونه قابلانتقالاند.
اول Outcome بنویسید، نه نام فناوری
درخواست «به API حسابداری وصل شویم» هنوز Requirement نیست. Outcome را به زبان سفر کاربر و عملیات بنویسید:
| جزء | نمونه برای همگامسازی سفارش |
|---|---|
| Actor | خریدار، مسئول مالی و سرویس حسابداری |
| Trigger | پرداخت قطعی یا تأیید دستی سفارش |
| Outcome | سند فروش حداکثر تا پنج دقیقه ایجاد و شناسه آن روی سفارش ثبت شود |
| Guardrail | یک سفارش بیش از یک سند نسازد؛ مبلغ و مالیات تغییر نکند |
| Failure | قطع API، Timeout، پاسخ تکراری، داده نامعتبر و لغو سفارش |
| Evidence | Trace مشترک، نرخ Sync موفق، صف خطا و گزارش مغایرت روزانه |
| Owner | مالک فرایند مالی، نه فقط توسعهدهنده Integration |
وقتی Outcome روشن باشد، ممکن است یک Automation بومی کافی باشد و API سفارشی هیچ ارزش اضافهای نداشته باشد. برعکس، اگر Guardrail یا Reconciliation لازم در ابزار آماده وجود ندارد، کد سفارشی توجیه پیدا میکند.
نردبان توسعهپذیری سایتساز
| پله | راهحل | مناسب برای | ریسک اصلی |
|---|---|---|---|
| ۰ | تنظیمات و Component بومی | Layout، فرم و Workflow استاندارد | محدودیت تجربه و داده |
| ۱ | App/Plugin رسمی | نیاز رایج با Support و Upgrade path | مجوز زیاد، هزینه و Vendor lock-in |
| ۲ | CSS و Design token | ظاهر، Responsive و Brand | Selector شکننده و Accessibility regression |
| ۳ | JavaScript Client | تعامل محلی و Progressive enhancement | افشای Secret، XSS و Performance |
| ۴ | Embed/iframe | Widget مستقل و ایزوله | UX، Consent، Resize و ارتباط Cross-origin |
| ۵ | Backend/Serverless function | منطق حساس، Secret، Validation و Proxy | Quota، Cold start و Observability |
| ۶ | API/Webhook/iPaaS | همگامسازی و Workflow بین سیستمها | Duplicate، Ordering، Drift و Reconciliation |
| ۷ | Sidecar/Headless/Custom | Capability شکافدار یا مقیاس پیچیده | TCO، عملیات و دوپارگی تجربه |
اصل «کمترین پله مؤثر» هزینه نگهداری را محدود میکند. اگر یک CSS محدود مسئله را حل میکند، ساخت App و Backend لازم نیست. اگر عملیات پرداخت یا دسترسی به داده خصوصی مطرح است، JavaScript مرورگر پله اشتباه است؛ حتی اگر Demo کوتاهتر شود.
ماتریس Fit: پلتفرم را گسترش دهیم یا عوض کنیم؟
| نشانه | Configure/Extend | Integrate/Sidecar | Migrate/Custom |
|---|---|---|---|
| نیاز متمایز اما محدود | اغلب مناسب | در صورت داده بیرونی | معمولاً زود است |
| منطق دامنه پیچیده | ممکن است شکننده شود | Backend بیرونی محتمل | اگر هسته محصول است بررسی شود |
| API/Quota کافی نیست | نامناسب | Buffer/Batch شاید کمک کند | اگر Hard limit است محتمل |
| Checkout یا Auth بسته | فقط Extension point مجاز | بر اساس Policy | در شکاف حیاتی محتمل |
| تیم عملیات کوچک | مزیت بزرگ | Managed sidecar | هزینه پنهان بالا |
| نیاز شدید به Portability | Exit drill لازم | داده و منطق بیرونی | کنترل بیشتر، نه رایگان |
برای سنجش Hard quota، بازار App و مسیر رشد، راهنمای مقیاسپذیری سایتساز را ببینید. اگر Capability gap پایدار و حیاتی است، برنامه مهاجرت از سایتساز را پیش از توسعه بیشتر ارزیابی کنید.
Snapshot قابلیتها در ۱۰ اوت ۲۰۲۶
نام محصول، Plan و API دائماً تغییر میکنند. این جدول نمونهای برای روش ارزیابی است، نه رتبهبندی یا تضمین دائمی:
| اکوسیستم | Extension surface نمونه | نکته چرخه عمر |
|---|---|---|
| Wix / Velo | Frontend code، Backend web module، Secret Manager، HTTP function و Data API | فایلهای قدیمی .jsw منسوخ و .web.js مسیر فعلی است؛ Quota و Plan باید تازه بررسی شود |
| Shopify | App، Function/UI extension، Admin/Storefront API و Webhook | بسیاری از APIها نسخه سهماهه دارند و نسخه Stable حداقل دوره پشتیبانی مشخص دارد |
| Webflow | Custom code، Data/Designer/Browser API، App و Webhook | Scope و نوع Client تعیین میکند چه Endpointی قابلدسترسی است |
| WordPress | Hook، Plugin، Theme، REST API و کد کامل Backend | کنترل بیشتر با مسئولیت Patch، Compatibility، Hosting و Security بیشتر همراه است |
در Wix، Web module برای نگهداشتن منطق و فراخوانی Third-party در Backend و اعمال Permission طراحی شده است؛ مستندات رسمی هشدار میدهد کد Client عمومی است و Secret باید Backend بماند. مستندات رسمی Wix Web Modules
در Shopify، نسخههای Stable API طبق برنامه فصلی منتشر میشوند و Webhook payload نیز Version دارد؛ درخواست به نسخه بازنشسته ممکن است به قدیمیترین نسخه در دسترس Fall forward شود. نسخه مورد استفاده را از Header کنترل و ارتقا را پیش از موعد تست کنید. مستندات رسمی Shopify API versioning
Webflow سطحهای Data، Designer و Browser API را جدا میکند و Scopeهای Read/Write بر اساس Resource دارد؛ برای نمونه Scopeهای Custom code فقط برای نوع مشخصی از Client در دسترساند. مرجع رسمی Webflow Developer
Capability register بسازید
پیش از انتخاب پلتفرم یا شروع Sprint، هر قابلیت حیاتی را در رجیستر قابلاستناد نگه دارید:
| فیلد | نمونه |
|---|---|
| Capability | ثبت Webhook سفارش پرداختشده |
| Surface | App-specific subscription / HTTPS endpoint |
| Plan/Region | پلن و کشور حساب آزمایشی |
| Quota | نرخ API، Timeout و Payload size |
| Security | HMAC، Scope و Secret rotation |
| Lifecycle | API version، Deprecation channel و موعد تست |
| Evidence | لینک سند، تاریخ مشاهده و PoC |
| Exit | Export event/order و Reconciliation |
جمله «پلتفرم API دارد» کافی نیست. باید Endpoint لازم، Field، فیلتر، Pagination، Rate limit، Scope، Webhook، Export و Sandbox همان Plan را ثابت کنید. قابلیت Preview یا Beta را معادل Production-ready نگیرید.
CSS سفارشی: لایه ارائه، نه منطق کسبوکار
CSS برای Typography، فاصله، رنگ، Layout و Stateهای Focus/Hover مناسب است. از Selectorهایی که به کلاسهای تولیدشده یا DOM داخلی پلتفرم وابستهاند دوری کنید؛ Update ویرایشگر میتواند آنها را بشکند. ترجیحاً:
- یک Namespace یا Wrapper پایدار برای کد سفارشی داشته باشید؛
- Design token و Custom property را به جای مقدارهای تکراری تعریف کنید؛
- RTL، Zoom ۲۰۰%، متن بلند فارسی و حالت خطا را تست کنید؛
- Focus visible، Contrast و Reduced motion را حفظ کنید؛
- Overrideها را با Owner، دلیل، Selector و تاریخ انقضا ثبت کنید.
CSS نباید عنصر مخفیشده را از Accessibility tree یا منطق حذفشده فرض کند. تغییر ظاهر «غیرفعال» بدون تغییر Semantic و Permission میتواند کاربر و ابزار کمکی را گمراه کند.
JavaScript Client: هر چیزی که میفرستید عمومی است
کد Browser، Source map، Network request و Storage برای کاربر قابلمشاهده یا دستکاریاند. API key خصوصی، Client secret، منطق قیمتگذاری قابلاعتماد، Permission check یا دسترسی Admin را در Frontend نگذارید. Validation Client برای تجربه سریع مفید است، اما Validation و Authorization نهایی باید در Backend انجام شود.
کارهای مناسب Client
- تعامل UI و Progressive enhancement؛
- محاسبه تقریبی غیرحساس با تأیید نهایی Server؛
- نمایش State و Error؛
- فراخوانی Backend محدود با Session و Permission؛
- Telemetry حداقلی با Consent و حذف PII.
کارهای نامناسب Client
- نگهداری Secret یا Refresh token؛
- اعتماد به role، price، discount یا object ID دریافتی؛
- فراخوانی مستقیم API دارای Credential مشترک؛
- ثبت پرداخت یا موجودی فقط بر اساس پاسخ UI؛
- تزریق HTML بدون Sanitization یا اجرای Script ناشناس.
Embed و iframe را قرارداد مستقل ببینید
Embed سریع است، اما دامنه اعتماد Third-party را به صفحه میآورد. برای هر Widget، منشأ، داده جمعآوریشده، Cookie/Consent، CSP، دسترسی postMessage، Sandbox، Resize، Keyboard، Screen reader، Loading و Failure fallback را تعریف کنید.
در postMessage مبدأ را دقیق بررسی کنید؛ پیام با Origin دلخواه را نپذیرید. iframe را با کمترین Capability در sandbox اجرا کنید و فقط Permission لازم را باز کنید. اگر Widget از دسترس خارج شد، مسیر اصلی خرید یا تماس نباید بیدلیل نابود شود.
کد Third-party بودجه و مالک میخواهد
| خطر | کنترل | شاهد |
|---|---|---|
| JavaScript سنگین | Performance budget، lazy load و حذف routeهای غیرلازم | Long task، INP و bundle bytes قبل/بعد |
| Supply-chain | Allowlist، نسخه Pin، CSP/SRI در صورت امکان | موجودی Script و تغییر Hash |
| Privacy | Data map، Consent و کمینهسازی | Requestهای واقعی Browser |
| Failure | Timeout، fallback و circuit breaker در Backend | Chaos/blocked-domain test |
| مالکیت مبهم | Owner، purpose و expiry | Third-party registry |
Backend function: مرز اعتماد واقعی
منطق حساس، Secret، Permission، اتصال پرداخت، نوشتن داده و فراخوانی API خصوصی باید در Backend پلتفرم یا سرویس Sidecar اجرا شود. Backend فقط به دلیل مخفیبودن کد امن نیست؛ Endpoint آن همچنان قابلفراخوانی است. هر Function باید این قرارداد را داشته باشد:
actor → authentication → function permission → object authorization
input schema → business rule → dependency call → output allowlist
timeout → retry policy → audit event → error contractدر WordPress، Route سفارشی REST یک permission_callback مستقل دارد؛ Callback اصلی نباید جای مجوزدهی را بگیرد. مستندات رسمی WordPress REST routes
Secret را چگونه مدیریت کنیم؟
- Secret را در کد، Git، CSS، HTML، Browser storage یا Log نگذارید؛
- Secret Manager پلتفرم یا Vault سازمانی را بهکار ببرید؛
- برای هر محیط و Integration Credential جدا بسازید؛
- Scope و عمر Token را حداقل کنید؛
- Rotation بدون Downtime و Revocation اضطراری را تمرین کنید؛
- دسترسی Human و Workload را جدا و Audit کنید؛
- Leak scan را در Repository، Build artifact و Log اجرا کنید.
Wix نیز Secret را فقط برای Backend توصیه میکند و هشدار میدهد تغییر نام یا حذف Secret میتواند کد مصرفکننده را بشکند. مستندات رسمی Wix Secrets Manager
OAuth: ورود با گوگل نام یک دکمه نیست
OAuth پروتکل تفویض دسترسی است و OpenID Connect لایه هویت را اضافه میکند. Flow را از نمونه تصادفی وبلاگ کپی نکنید. Redirect URI دقیق، State/Nonce، PKCE برای Client عمومی، ذخیره امن Token، Scope حداقلی، Refresh rotation، Revocation و جلوگیری از Open redirect را طراحی و تست کنید.
RFC ۹۷۰۰ که در ۲۰۲۵ بهعنوان Best Current Practice منتشر شد، توصیههای امنیتی OAuth ۲.۰ را بهروزرسانی و برخی الگوهای قدیمی را ناامن یا منسوخ میداند؛ از جمله تأکید بر Authorization Code، PKCE و محدودکردن Token. RFC ۹۷۰۰؛ امنیت OAuth ۲.۰
API contract پیش از کد
| بخش قرارداد | تصمیم لازم |
|---|---|
| Resource | Order، Customer، Product و مالک هر Domain |
| Identifier | شناسه داخلی، شناسه خارجی و Mapping پایدار |
| Schema | Field، type، required/null، enum، money و unit |
| Locale/time | UTF-۸، فارسی، timezone، UTC timestamp و تقویم نمایش |
| Operation | Create/Update/Upsert، side effect و idempotency |
| Concurrency | Version/ETag، last-write rule و conflict state |
| Pagination | Cursor/offset، ordering و snapshot consistency |
| Error | status، code، retryable، correlation ID و field error |
| Limit | rate، burst، payload، timeout و bulk operation |
| Lifecycle | version، compatibility، deprecation و sunset |
برای طراحی عمیق Resource، Error، Idempotency و نسخهبندی، راهنمای قرارداد و قابلیت اطمینان API وب را بخوانید. این مقاله تمرکز خود را بر Extension داخل محدودیت سایتساز نگه میدارد.
Source of Truth را برای هر Field مشخص کنید
عبارت «همگامسازی دوطرفه» اغلب تعارض پنهان میسازد. به جای تعیین یک سیستم برای همهچیز، مالک هر Field و Transition را مشخص کنید:
| داده | مالک پیشنهادی نمونه | جهت | تعارض |
|---|---|---|---|
| عنوان و تصویر محصول | PIM/CMS | به سایتساز | ویرایش مقصد ممنوع یا Override ثبتشده |
| قیمت فروش | Pricing/ERP | به فروشگاه | نسخه قیمت و زمان اثر |
| موجودی قابلفروش | OMS/WMS | به فروشگاه | Reservation و Oversell policy |
| سفارش | Store/OMS بر اساس State | رویداد به ERP | Idempotent create و status map |
| رضایت بازاریابی | Consent system | کنترلشده | Purpose و timestamp مقدم است |
معماری کامل یکپارچهسازی، Semantic mapping، Reconciliation و Exit در راهنمای یکپارچهسازی سایت پوشش داده شده است.
Webhook خبر است، نه منبع حقیقت
Webhook به مقصد خبر میدهد رویدادی رخ داده است، اما ممکن است تکراری، دیر، نامرتب یا گم شود. Handler قابلاتکا این مسیر را طی میکند:
Receive raw body
→ verify signature + timestamp
→ reject replay/invalid source
→ store event ID atomically
→ acknowledge quickly
→ enqueue durable work
→ process idempotently
→ retry with backoff/jitter
→ dead-letter after policy
→ reconcile with source APIShopify صریحاً Ordering وبهوک را تضمین نمیکند، توصیه میکند Delivery با HMAC بررسی و Duplicate با Webhook ID نادیده گرفته شود و برای رخدادهای ازدسترفته Job تطبیق دورهای وجود داشته باشد. مستندات رسمی Shopify Webhooks
Webflow نیز Timestamp و Signature را در Header وبهوک ارائه میدهد. الگوریتم و Raw body باید مطابق نسخه سند Provider پیاده شود؛ قبل از Parse یا تغییر Encoding، امضا را با روش رسمی Verify کنید. مستندات رسمی Webflow Webhooks
Idempotency جلوی اثر تکراری را میگیرد
Retry طبیعی است؛ ایجاد دوباره سفارش، سند، Refund یا پیامک طبیعی نیست. برای Operation اثرگذار یک Idempotency key پایدار تعریف کنید، نتیجه نخست را اتمیک ذخیره کنید و تکرار همان Key/Intent را به همان نتیجه برگردانید. اگر Payload برای Key قبلی تغییر کرد، Conflict بدهید؛ آن را درخواست جدید فرض نکنید.
شناسه Webhook میتواند برای Dedup دریافت مفید باشد، اما Idempotency کسبوکاری گاهی به کلید دیگری مانند source-order-id + operation + version نیاز دارد. TTL را از حداکثر Window تکرار، Retry و Reconciliation طولانیتر بگیرید.
Retry را فقط برای خطای Retryable انجام دهید
| وضعیت | رفتار معمول | نکته |
|---|---|---|
| Timeout / 5xx | Retry محدود با exponential backoff و jitter | Operation باید idempotent باشد |
| 429 | احترام به Retry-After و Rate limit | Queue و Backpressure لازم است |
| 401 | Refresh کنترلشده یا توقف | Loop بینهایت Refresh نسازید |
| 403 | توقف و بررسی Scope/Policy | Retry معمولاً مجوز نمیسازد |
| 400/422 | Dead-letter یا اصلاح داده | همان Payload احتمالاً دوباره شکست میخورد |
| 409/412 | خواندن نسخه و حل تعارض | Last write wins را بیدلیل اعمال نکنید |
Reconciliation بیمه همگامسازی است
حتی Webhook خوب Delivery تضمینشده مطلق نیست. Job تطبیق باید بر اساس updated_at یا Cursor پایدار رکوردهای تغییرکرده را از Source بگیرد، اختلاف را دستهبندی و بدون Duplicate اصلاح کند. گزارش روزانه این موارد را نشان دهد:
- رکورد موجود در Source و غایب در Target؛
- Version یا مبلغ متفاوت؛
- State transition نامعتبر؛
- Event دریافتشده اما پردازشنشده؛
- Dead-letter با عمر و Owner؛
- Last successful cursor و فاصله Sync.
Authorization را برای هر Object و Function اعمال کنید
اینکه کاربر Endpoint را میبیند یا Token معتبر دارد به معنی مجازبودن روی هر سفارش یا Field نیست. Server باید هم Function-level permission و هم Object-level authorization را بررسی کند. ID ترتیبی یا UUID جای کنترل دسترسی را نمیگیرد. پاسخ را با Allowlist Field بسازید و ورودی را مستقیم به Object داخلی Bind نکنید.
OWASP API Security Top ۱۰، نقض مجوزدهی سطح Object را از ریسکهای اصلی میداند و بررسی دسترسی روی هر Object ID را لازم میشمارد. راهنمای رسمی OWASP BOLA و ممیزی امنیت API، OAuth و JWT برای تست کاملتر مفیدند.
CORS کنترل دسترسی نیست
CORS تعیین میکند Browser چه پاسخ Cross-origin را در اختیار JavaScript بگذارد؛ مانع فراخوانی مستقیم مهاجم از Server یا ابزار HTTP نمیشود. Endpoint باید مستقل از Origin، Authentication و Authorization داشته باشد. اگر Credential استفاده میشود، Origin wildcard نگذارید و Preflight/Cache را دقیق تنظیم کنید.
SSRF و اتصال به URL دلخواه
اگر Widget یا Backend URL ورودی کاربر را Fetch کند، مهاجم ممکن است به شبکه داخلی، Metadata endpoint یا فایلهای حساس درخواست بفرستد. Destination را Allowlist، DNS/IP resolution را کنترل، Redirect را محدود، Scheme/Port را مشخص و پاسخ/حجم/Timeout را سقفگذاری کنید. Proxy عمومی برای «حل CORS» نسازید.
پرداخت را با JavaScript قطعی نکنید
بازگشت کاربر از صفحه بانک یا موفقیت UI بهتنهایی سند پرداخت نیست. نتیجه باید Server-to-server با شناسه تراکنش، مبلغ، Merchant، Currency و State سفارش Verify شود؛ Operation ثبت قطعی Idempotent باشد و Callback/Webhook تکراری یا نامرتب را تحمل کند. راهنمای اتصال امن درگاه پرداخت قرارداد کامل Initiate/Return/Verify/Settle/Reconcile را پوشش میدهد.
داده شخصی را کمینه و عمر آن را تعیین کنید
API و App آماده گاهی Fieldهای بیشتری از نیاز میگیرند. برای هر داده، Purpose، مبنای مجاز، Scope، محل ذخیره، Retention، دسترسی، Subprocessor و حذف را ثبت کنید. Log و Dead-letter نیز دادهاند؛ Payload کامل مشتری را برای Debug نامحدود نگه ندارید. Token و PII را Mask و دسترسی Support را Audit کنید.
تستپذیری از همان قرارداد آغاز میشود
| لایه تست | چه چیزی ثابت میشود؟ |
|---|---|
| Unit | Mapping، Validation، Money/Date و State transition |
| Contract | Schema و Compatibility Consumer/Provider |
| Integration Sandbox | Auth، Scope، Rate limit و خطاهای واقعی |
| Webhook replay | Signature، Duplicate، Ordering و Retry |
| Negative security | Object/Function authorization، Injection و SSRF |
| E2E | Journey از UI تا سیستم مقصد و Reconciliation |
| Accessibility | Keyboard، focus، label، error و iframe |
| Performance | Script budget، API latency، Queue و Rate limit |
| Upgrade | API/Platform/App نسخه بعدی با Fixture واقعی |
| Exit drill | Export کامل و بازسازی Workflow خارج از Vendor |
محیطها و داده تست را جدا کنید
Dev، Staging و Production باید Site/Account، Credential، Webhook destination، Queue و Dataset جدا داشته باشند. اگر Provider Sandbox ندارد، داده مصنوعی با Prefix و Cleanup policy بسازید. ارسال پیامک، ایمیل، سند مالی یا پرداخت واقعی از Staging را مسدود کنید. Feature flag محیطی نباید تنها با متغیر قابلدستکاری Client کنترل شود.
Release کد سفارشی در سایتساز
- تغییر را در Repository با Review و Secret scan نگه دارید.
- Build قابلتکرار و Artifact نسخهدار بسازید.
- Contract/Unit/Security/Accessibility test را اجرا کنید.
- در Preview یا Staging همان Plan تست کنید.
- با Feature flag یا درصد کم فعال کنید.
- Outcome، Error، Latency و Queue را Verify کنید.
- در صورت نقض Guardrail، Rollback تمرینشده اجرا کنید.
اگر پلتفرم History یا Rollback محدود دارد، نسخه کامل Script/Config، روش تزریق و Snapshot تنظیمات را خارج از آن نگه دارید. برای طراحی Pipeline، Artifact و Progressive delivery از راهنمای CI/CD امن استفاده کنید.
Observability هر Integration
| Signal | Metric/Log پیشنهادی | Alert |
|---|---|---|
| تقاضا | call/event rate بر route/topic | جهش غیرعادی یا توقف کامل |
| موفقیت | business success و status class | نقض SLO |
| Latency | p50/p95/p99 dependency | Tail بالاتر از Timeout budget |
| Queue | depth و oldest-message age | عمر بیشتر از Sync SLO |
| Retry/DLQ | retry rate و dead-letter count | رشد پایدار یا رکورد حیاتی |
| Data quality | mapping/validation/conflict | مغایرت مبلغ، موجودی یا Consent |
| Lifecycle | API version و deprecation date | نزدیکشدن Sunset |
| Cost | call، execution، egress و app fee | بودجه واحد تجاری |
Correlation ID را از درخواست کاربر تا Queue و API مقصد حمل کنید، اما داده حساس را در آن نگذارید. Log باید Actor، Action، Resource، Result و Version را برای Audit نشان دهد.
SLO یکپارچهسازی را بر Business outcome ببندید
Uptime Endpoint کافی نیست. نمونه SLOهای بهتر:
- ۹۹٫۹٪ سفارشهای پرداختشده حداکثر تا پنج دقیقه در OMS ثبت شوند؛
- هیچ سفارش به دلیل Retry بیش از یک سند مالی نسازد؛
- ۹۹٫۵٪ تغییرهای موجودی در ۶۰ ثانیه منتشر شوند؛
- همه مغایرتهای مالی تا پایان روز Reconcile شوند؛
- هیچ Secret در Bundle و Log عمومی ظاهر نشود.
اعداد بالا فقط نمونهاند. SLO واقعی را از تحمل فرایند، هزینه خطا و توان تیم تعیین کنید. Error budget به شما میگوید توسعه Feature را ادامه دهید یا Reliability را مقدم کنید.
Performance: سرعت صفحه و سرعت فرایند جدا هستند
Script Third-party میتواند Parsing، Long task و INP را بد کند؛ API کند میتواند Backend function یا Worker را نگه دارد؛ Queue میتواند تجربه کاربر را سریع نگه دارد اما تکمیل فرایند را به تأخیر بیندازد. برای هر Extension دو بودجه تعریف کنید:
- بودجه Browser: bytes، request، main-thread time، LCP/INP و Privacy؛
- بودجه Workflow: API latency، timeout، retry، queue age و completion SLO.
کار غیرضروری را Lazy load کنید، اما کنترل حیاتی Consent یا امنیت را طوری عقب نیندازید که Race condition بسازد. Cache فقط برای پاسخهایی بهکار رود که Key، TTL و Invalidation صحیح دارند.
TCO توسعه سایتساز
TCO سالانه Extension =
Plan + App/API usage + Backend/Queue/Storage + Development
+ Test/Monitoring/Security + Support + Upgrade/Deprecation
+ Incident/Data correction + Migration/Exit reserveکد اولیه اغلب کوچکترین بخش هزینه است. API نسخهای، Webhook نامطمئن، Plugin بدون Maintainer و DOM override شکننده هزینه هر Update را بالا میبرند. برای هر Extension نرخ تغییر، Bus factor، زمان بازیابی و جایگزین را امتیاز دهید. بدهیهای پذیرفتهشده را در رجیستر بدهی فنی با Owner و تاریخ بازبینی نگه دارید.
سایتساز رایگان و کدنویسی سفارشی
پلن رایگان ممکن است Custom code، دامنه، API، Webhook، Export، تعداد Request یا حذف Branding را محدود کند. PoC روی پلن رایگان ارزشمند است، اما نتیجه آن را به Production تعمیم ندهید. Plan مقصد، قیمت تمدید و سقفهای واقعی را با حساب آزمایشی بسنجید. جزئیات تصمیم در راهنمای محدودیت سایتساز رایگان آمده است.
ملاحظات ویژه ایران
- دسترسی و قرارداد: Eligibility رسمی کشور، حساب، پرداخت و Policy سرویس را پیش از وابستگی حیاتی بررسی کنید؛ از هویت یا مسیر پرداخت غیرواقعی برای دورزدن محدودیت استفاده نکنید.
- شبکه: API و CDN خارجی را از چند اپراتور ایران و در اختلال بینالملل تست کنید؛ Timeout و Queue آفلاین داشته باشید.
- درگاه داخلی: Callback و Verify سروری، مبلغ ریال/تومان و Reconciliation را با Sandbox/مستند رسمی همان PSP تست کنید.
- داده فارسی: ی/ک، نیمفاصله، اعداد، RTL، BiDi، شماره موبایل، کدپستی و آدرس را در Contract و Fixture بگنجانید.
- زمان: ذخیره UTC، نمایش تقویم/Timezone محلی و مرز روز مالی را صریح کنید.
- Privacy و محل داده: مقصد، Subprocessor، Retention و امکان حذف/Export را مستند کنید.
- خروج: از Dependency خارجی نسخه جایگزین، Export و Runbook تغییر Provider داشته باشید.
پرسشنامه ارزیابی Vendor
| حوزه | پرسش قابلاثبات |
|---|---|
| قابلیت | کدام API/Extension در Plan و Region ما Production است؟ |
| سقف | Rate، Burst، Execution، Payload، Storage و Concurrent limit چیست؟ |
| نسخه | Release cadence، Deprecation notice و Sunset policy چیست؟ |
| Webhook | Signature، Retry، Duplicate، Ordering، Log و Replay چگونهاند؟ |
| امنیت | Scope، OAuth، Secret، Audit log و Incident notification چیست؟ |
| داده | Export کامل، Delete، Backup، Residency و Subprocessor چیست؟ |
| عملیات | SLA، Status page، Support escalation و Recovery چیست؟ |
| خروج | کد، URL، Asset، CMS، Order و Redirect چگونه منتقل میشوند؟ |
نمونه عملی: اتصال موجودی سایتساز به انبار
فرض کنید فروشگاه روی سایتساز است و انبار منبع حقیقت موجودی. طرح ایمن:
- SKU داخلی و External ID را با Mapping versioned نگه دارید.
- رویداد تغییر موجودی از انبار با Signature وارد Endpoint شود.
- Endpoint پس از Verify و Dedup، Event را در Queue پایدار بگذارد و سریع پاسخ دهد.
- Worker مقدار قابلفروش را با API نسخهدار و Idempotency به فروشگاه Upsert کند.
- ۴۲۹/5xx با Backoff؛ 4xx دادهای به DLQ برود.
- Job دورهای همه تغییرهای پس از Cursor را Reconcile کند.
- Dashboard عمر صف، نرخ Conflict، Oversell و Last successful sync را نشان دهد.
- در زمان قطع API، Policy فروش موجودی کم یا توقف SKU پرریسک فعال شود.
«لحظهای» را وعده مبهم نگذارید. SLO مثلاً ۶۰ ثانیه و رفتار در قطع ارتباط را با عملیات فروش توافق کنید.
Runbook ۱: Secret در Frontend افشا شده است
- Credential را فوراً Revocation/Rotate کنید؛ حذف Script بهتنهایی کافی نیست.
- Log استفاده، Scope و بازه افشا را حفظ و بررسی کنید.
- دسترسی و داده تغییرکرده را Reconcile کنید.
- Call را به Backend منتقل و Scope/عمر Token را کم کنید.
- Secret scan و Test عدم حضور در Bundle/Log اضافه کنید.
- علت، اثر و اقدام پیشگیرانه را در Incident record ثبت کنید.
Runbook ۲: Webhook تکراری سفارش دوباره ساخته است
- پردازش Topic را Pause یا Feature flag را خاموش کنید.
- Event ID، Order ID و آثار مالی/موجودی را استخراج کنید.
- رکوردهای تکراری را با مالک کسبوکار اصلاح و Audit کنید.
- Dedup اتمیک و Business idempotency key اضافه کنید.
- Fixture تکرار، Ordering معکوس و Retry را به Test suite بیفزایید.
- مغایرت Window حادثه را Reconcile کنید.
Runbook ۳: نسخه API بازنشسته شده است
- Header و نسخه واقعی پاسخ را با نسخه درخواستشده مقایسه کنید.
- Field/enum/behavior تغییرکرده را از Contract diff پیدا کنید.
- نسخه جدید را با Payloadهای Production anonymized در Staging تست کنید.
- Consumer و Webhook handler را سازگار و Canary کنید.
- پس از Verify، Subscription و Client را همزمان ارتقا دهید.
- تقویم Deprecation و Owner را اصلاح کنید.
Runbook ۴: صف همگامسازی عقب افتاده است
- Oldest message age و Business impact را بسنجید.
- ورودی، Rate limit مقصد، Worker error و Poison message را تفکیک کنید.
- Backpressure بگذارید و Retry storm را متوقف کنید.
- پیام خراب را به DLQ منتقل؛ بقیه صف را باز کنید.
- Capacity موقت را فقط با رعایت Limit مقصد افزایش دهید.
- پس از بازیابی، Reconciliation و گزارش مغایرت اجرا کنید.
Runbook ۵: Update سایتساز کد سفارشی را شکسته است
- Feature flag/Script را Disable یا نسخه قبلی را Restore کنید.
- DOM/API/Permission/Policy تغییرکرده را با Release note تطبیق دهید.
- Selector یا Adapter را در Preview نسخه جدید اصلاح کنید.
- Visual، Accessibility، Journey و Contract regression اجرا کنید.
- وابستگی به DOM خصوصی را با Extension surface پایدار جایگزین کنید.
- اگر تکرارشونده و حیاتی است، Trigger مهاجرت را بازبینی کنید.
RACI توسعه سایتساز
| خروجی | مسئول اجرا | پاسخگو | مشورت | آگاه |
|---|---|---|---|---|
| Outcome و Guardrail | Product/Operations | Business owner | Engineering | Support |
| Capability/Plan evidence | Solution architect | Tech lead | Procurement | Product |
| Threat/Data model | Developer/Security | Security owner | Privacy | Operations |
| Code/Contract/Test | Developer/QA | Engineering lead | Platform | Product |
| Release/Observability | Platform/SRE | Service owner | Developer | Support |
| Reconciliation/Incident | Operations | Process owner | Engineering/Finance | Stakeholders |
برنامه ۹۰ روزه توسعه کنترلشده
| بازه | خروجی | Gate |
|---|---|---|
| روز ۰ تا ۳۰ | Outcome، capability register، data/source map، threat model و PoC | Plan/Quota/Export و کمترین پله مؤثر ثابت است |
| روز ۳۱ تا ۶۰ | Contract، Backend/Queue، Secret، tests، telemetry و runbook | Duplicate/failure/upgrade tests پاس میشوند |
| روز ۶۱ تا ۹۰ | Canary، SLO، reconciliation، TCO، exit drill و operational handoff | Outcome زیر بار واقعی و خرابی کنترلشده برقرار است |
چکلیست پیش از انتشار Extension
- Outcome، Owner، SLO و Kill criterion روشن است؛
- پله سادهتر با Evidence رد شده است؛
- Plan، Region، Quota، Scope و API version ثبت شدهاند؛
- هیچ Secret یا Permission نهایی در Client نیست؛
- Object/Function authorization و Input/Output allowlist تست شدهاند؛
- Webhook امضا، Duplicate، Ordering، Retry و Reconciliation دارد؛
- Money، Timezone، فارسی/RTL و State map آزموده شدهاند؛
- Performance، Accessibility، Privacy و Security gate پاس شدهاند؛
- Dashboard، Alert، DLQ، Runbook و Support owner وجود دارند؛
- Rollback، Export و Exit drill انجام شده است.
پرسشهای متداول توسعه سایتساز با کد و API
تفاوت کد سفارشی و API در سایتساز چیست؟
کد سفارشی میتواند ظاهر، رفتار Client یا منطق Backend پلتفرم را تغییر دهد؛ API قرارداد ارتباط با قابلیت یا سیستم دیگر است. این دو متضاد نیستند: Frontend میتواند Backend function را صدا بزند و Backend از API بیرونی استفاده کند. مرز داده و اعتماد مهمتر از نام فناوری است.
آیا میتوان API key را در JavaScript سایت قرار داد؟
اگر Key محرمانه یا دارای دسترسی است، خیر؛ هر چیزی در Browser برای کاربر قابلمشاهده و استفاده مجدد است. Secret را در Secret Manager و Backend نگه دارید و Frontend فقط Endpoint محدود با Authentication، Authorization، Validation و Rate limit را فراخوانی کند.
بهترین سایتساز برای کدنویسی سفارشی کدام است؟
بهترین عمومی وجود ندارد. نیاز شما باید روی Extension surface، Plan/Region، API field، Quota، Backend، Webhook، Security، Export، هزینه و توان تیم تست شود. Wix، Shopify، Webflow و WordPress مدلهای متفاوتی دارند و قابلیتهایشان تغییر میکند؛ PoC روی Journey حیاتی تصمیم معتبرتری میدهد.
چه زمانی از سایتساز به پلتفرم اختصاصی مهاجرت کنیم؟
وقتی Capability gap حیاتی و تکرارشونده است، Hard quota یا Policy Outcome را متوقف میکند، Overrideها شکنندهاند، هزینه Extension از گزینه جایگزین بیشتر شده یا Export/Operations قابلقبول نیست. مهاجرت را با TCO، Readiness، Reconciliation، SEO و Rollback بسنجید؛ نه با علاقه به فناوری.
Webhook بهتر است یا Polling؟
Webhook برای خبر نزدیک به زمان واقعی و کاهش Polling مناسب است، اما ممکن است تکراری، نامرتب یا ازدسترفته باشد. Polling یا Job تطبیق برای بازیابی اختلاف لازم میماند. معماری رایج Webhook امن و صفدار برای سرعت، همراه Reconciliation دورهای برای صحت است.
جمعبندی
ارزش سایتساز در این است که بخش استاندارد را با عملیات کمتر فراهم کند. اگر هر نیاز را با کد عمیق، DOM override و Integration اختصاصی حل کنید، ممکن است همان پیچیدگی پلتفرم سفارشی را با کنترل کمتر بسازید. توسعه خوب از Outcome شروع میشود، کمترین پله مؤثر را انتخاب میکند و مرز Client، Backend، API و Webhook را صریح نگه میدارد.
یک Extension آماده Production فقط «کار میکند» نیست: Secret امن، Permission سطح Function و Object، Contract نسخهدار، Idempotency، Retry کنترلشده، Queue، Reconciliation، تست Upgrade، Observability، SLO، Rollback و Exit دارد. اگر پلتفرم این مسیر را با هزینه و ریسک قابلقبول پشتیبانی کند، آن را گسترش دهید؛ اگر نه، شکاف را با وصلههای بیشتر پنهان نکنید.






