@fadymondy/nasaq-theme-sdk
v0.2.0
Published
Nasaq themes for any app: the catalog, CircleXO connect, and the Themes page.
Downloads
173
Readme
nasaq-theme-sdk
Nasaq themes for any app. An app built on it gets:
- Theme switching. The app's businesses (sites) pick a theme from the Nasaq catalog.
- Live themes from Nasaq Studio. A site connects its CircleXO organisation, chooses a Nasaq project, and from then on follows every theme that project publishes.
- A ready-made Themes page, built from stock Nasaq components.
SeatFor uses it, and Matjar is next.
It has two halves that share one contract:
| Half | Module | What it holds |
|---|---|---|
| Go | github.com/fadymondy/nasaq-theme-sdk | Theme model and mapping (theme), Nasaq client (nasaq), CircleXO connector with storage (circlexo), fake Nasaq for tests (nasaqtest) |
| npm | @fadymondy/nasaq-theme-sdk | Types, themeCSS, contrast helpers, API client; /react adds the Themes page and the CircleXO return |
Go
import (
"github.com/fadymondy/nasaq-theme-sdk/circlexo"
"github.com/fadymondy/nasaq-theme-sdk/nasaq"
"github.com/fadymondy/nasaq-theme-sdk/theme"
)
catalog := nasaq.New("matjar", nasaq.Static("https://ui.nasaq.app")) // the app's slug in Nasaq coverage
conn := &circlexo.Connector{
Hub: func(ctx context.Context) (cxo.Config, error) { return hubConfig(ctx) }, // the app's CircleXO client
NasaqAudience: func(context.Context) string { return "nasaq" },
Nasaq: catalog,
Store: &circlexo.SQLStore{DB: pool}, // or your own circlexo.Store
Vault: vault, // seals the refresh token at rest
Site: sites, // reads and writes a site's theme.Look
}
conn.StartSweep(ctx, log, 5*time.Minute, func(site string) { /* flush the site's caches */ })The pieces
themeholds the model.- Types:
SiteTheme,Look(action colour, its label colour, theme) andColorPair. Mapturns a Nasaq theme's tokens into a look. It drops any colour that would not render readably.Defaultputs the site's own colour back.Problemsvalidates a stored theme.- Every refusal is a
*theme.Errorwith an HTTP status and both English and Arabic text.
- Types:
nasaq.Clientreads the public catalog. The catalog is cached per URL and still answers from cache while Nasaq is down. The client also calls Nasaq's app API: projects, bind and the published core theme.Cardsbuilds the catalog that the Themes page shows.circlexo.Connectorhandles the CircleXO side:- It connects a site to its CircleXO organisation. The OIDC state is sealed, bound to both the site and the user, and lasts 15 minutes.
- It exchanges the site's refresh token for a Nasaq token.
- It binds a project and pulls the project's published theme.
- A sweep pulls every bound site. When a grant is lost, the site is marked
grant_lostand the sweep stops visiting it. Statusbuilds the Themes page'sThemeStatus.
circlexo.SQLStoreis the Postgres store.circlexo.Schemacreates its table.- You can point it at your own table with
Table,KeyandKeyType, for exampleTable: "tenant_circlexo_links", Key: "tenant_id". MemStoreis an in-memory store for tests.
The HTTP contract
The app serves these routes under one base, for example /api/tenant/theme. The npm client
calls them.
| Method | Path | Answer |
|---|---|---|
| GET | `` | ThemeStatus |
| GET | /catalog?locale= | { items: ThemeCard[] } |
| POST | /use {id} | ThemeStatus |
| POST | /reset | ThemeStatus |
| POST | /circlexo {action:"start", redirect_uri} | ThemeConnectView (auth_url) |
| POST | /circlexo {action:"finish", code, state} | ThemeConnectView |
| DELETE | /circlexo | ThemeStatus |
| GET | /projects | { items: Project[] } |
| POST | /bind {project_id} | ThemeStatus |
| POST | /pull | ThemeStatus |
Errors are JSON with a message. Use (*theme.Error).In(locale) for the text in the caller's
language.
npm
npm i @fadymondy/nasaq-theme-sdk @fadymondy/nasaqimport { createThemesClient, themeStyleSheet } from "@fadymondy/nasaq-theme-sdk"
// Public pages: the site's theme as Nasaq variables.
const css = themeStyleSheet(site.theme) // ":root{...}.dark{...}"
// The admin: the themes API over your own fetch.
const client = createThemesClient((path, init) => api(`/tenant/theme${path}`, init))import { ThemesPanel, CircleXOReturn, themeLabels } from "@fadymondy/nasaq-theme-sdk/react"
<ThemesPanel client={client} locale="ar" appName="Matjar" redirectUri={() => `${location.origin}/admin/themes/circlexo`} />
// On the redirect page:
<CircleXOReturn client={client} locale="ar" appName="Matjar" params={searchParams} onDone={() => router.replace("/admin/themes")} />The components use @fadymondy/nasaq/web and Tailwind utilities. Add the package to Tailwind's
sources next to Nasaq's:
@source "../node_modules/@fadymondy/nasaq-theme-sdk/dist";The copy is built in, in Arabic and English. {app} becomes appName. To change any string,
pass labels.
Products (Nasaq Studio themes)
Nasaq Studio builds themes for a product. The product package is that contract:
product.Product: the product id, the entities and fields a theme can bind to, and the page templates every theme must render (Matjar: home, collection, product, cart, checkout, account).- Seed packs: realistic data a theme is designed with (
matjar.LoadPack("sahar"): 13 products, 4 categories, 3 collections, pages, menus, a cart, checkout and account sample). Keys are stable, so seeding is idempotent and a reset removes exactly what a pack added. Adapter.Preview(template, pack, params): the view model of a template filled with a pack.product.Package: the published theme Studio sends withPUT /api/nasaq/theme.product.Receiver: the product's handler for that route (bearer link token, validation, bilingual errors);product.Pushis the Studio side.
import (
"github.com/fadymondy/nasaq-theme-sdk/product"
"github.com/fadymondy/nasaq-theme-sdk/product/matjar" // registers Matjar
)
mux.Handle(product.ThemePath, product.Receiver{
Product: matjar.ID,
Verify: func(ctx context.Context, r *http.Request, tok string) (string, error) { return store.TenantForLinkToken(ctx, tok) },
Apply: func(ctx context.Context, tenant string, p product.Package) (product.Applied, error) {
return store.ApplyBrand(ctx, tenant, matjar.BrandOf(p)) // colours, corners, font, hero
},
})npm: @fadymondy/nasaq-theme-sdk/products has the same packs (generated from the Go JSON by
npm run gen), the templates, the ThemePackage type and matjarLook.
Develop
go test ./... # Go
npm install && npm run build && npm test # npmLicense
MIT
