Back to Arky

Arky Docs

Implementation docs for using Arky as the backend under custom websites.

Arky is a backend for a custom website. The frontend can be Astro, Svelte, React, Vue, plain TypeScript, or an agent-generated storefront. Arky provides the Admin, the records, the storefront APIs, the SDK helpers, and the modules behind the website.

Build From This Mental Model

Keep the website custom. Put repeat backend work in Arky: Content, commerce, bookings, forms, customers, actions, store email, newsletters, support, Admin, API, and SDK.

The Storefront Contract

import { initialize } from "arky-sdk/storefront";
import { createOrderToken } from "arky-sdk/utils";

export const arky = initialize("arky_pk_...", {
	locale: "en",
	createVisitorIdentity: () => ({
		customer_id: crypto.randomUUID(),
		session_id: crypto.randomUUID(),
	}),
	createSessionId: () => crypto.randomUUID(),
	createId: () => crypto.randomUUID(),
	createOrderToken,
});

arky.pageViews.send({ path: location.pathname, referrer: document.referrer });

const { items: [catalog] } = await arky.eshop.catalog.find();
const cart = arky.eshop.cart({ buyer: { type: "customer" }, catalog_id: catalog.id });
await cart.load();

After initialize, use only the modules the website needs. A content site might use content, forms, actions and pageViews. A storefront adds eshop.cart, products, promotions and checkout. A service business adds bookings through the cart. A newsletter is a free customer group people join.

Three rules hold everywhere:

  1. The app picks every id. Creates carry a UUID v4 from your createId, or one you pass. The SDK keeps a pending id until its answer and sends the same request again under it, so a retry never makes a duplicate.
  2. Changes carry what they read. Updates and actions send the expected_updated_at they read; a stale one is refused.
  3. Language is explicit, and the key decides the channel. The storefront sends its language, and its publishable key belongs to one sales channel. Every product read and cart names its catalog. Arky never falls back to a default.

Build Order

  1. Call initialize once when the page or app starts.
  2. Read editable copy from Content collections and entries.
  3. Add commerce or bookings when the flow needs products, carts, availability, quotes or checkout.
  4. Track important moments with action keys such as lead.submitted or checkout.started, and count page views with pageViews.send.
  5. Connect the store’s own Resend account, verify its domain there, add a sending address and pick the template of each moment, so receipts, sign-in codes and the other emails go out from the store’s own address.
  6. Add a chat flow, support email by forwarding, and a newsletter when the client needs them.

Core Modules

ModuleUse it for
ContentCollections, entries, blocks, media and localization
CommerceProducts, variants, catalogs, carts, promotions, orders, payments, checkout
BookingsBooking services, resources, offerings, availability, booking lines
Customer groupsFree or paid memberships, renewals, member prices and newsletters
FormsLead capture, intake, quote requests, applications
CustomersVisitor and signed-in customers, sign-in codes, email changes
ActionsFirst-party facts for timelines and experiment goals
Page viewsPage views, pages, countries, referrers and unique visitors, counted from a beacon that stores nothing
EmailThe store’s own Resend account, sending and receiving addresses, the template of each moment, broadcasts
SupportFixed-step chat flows, team replies, support email by forwarding
API & SDKFramework-agnostic storefront and Admin access

Common Starting Points

Content website

const website = await arky.content.load({ collection: { key: "website" } });
const post = await arky.content.load({ entry: { collection_id: blogId, slug: "launch" } });

Product storefront

const { items: [catalog] } = await arky.eshop.catalog.find();
const { items: products } = await arky.eshop.product.find({ catalog_id: catalog.id, limit: 20 });
await arky.eshop.cart({ buyer: { type: "customer" }, catalog_id: catalog.id }).ensure();

Service booking

const { items: services } = await arky.eshop.bookingService.find({ catalog_id: catalog.id });
const calendar = arky.eshop.bookingCalendar({ buyer: { type: "customer" }, catalog_id: catalog.id });
await calendar.select({ booking_service_id: services[0].id });
calendar.selectFirstAvailableDate();

Support chat

const chat = await arky.support.conversation.start({ language: "en", flow_key: "default" });

Next