Skip to content
Twilight React Playground
ثيم رائدaren

page

objectBeginnerserverbrowserlive demo

Loads one of the merchant's own content pages, such as About us or the privacy policy, by its page id.

import { page } from '@salla.sa/twilight-theme-engine/api/page';

In plain words

Besides products, merchants write simple pages in the Salla dashboard: about us, terms, shipping policy. page.find(id) returns one of them: its name and its content, which is HTML the merchant wrote.

The id is the number at the end of the page's address: for …/about-us/page-1061977328 it is 1061977328.

Signature

page.find(slug: string): Promise<ApiPageResponse>
page.findOrThrow(slug: string): Promise<ApiPageResponse>   // any failure → NotFoundError
page.queries.detail(slug: string)                          // key ['pages', 'detail', slug]

// Not exported; use Awaited<ReturnType<typeof page.find>>
interface ApiPageResponse {
  id: number;
  name: string;
  slug?: string;
  content?: string;     // merchant HTML
  type?: string;
  url?: string;
  metadata?: { title?: string; description?: string };
  created_at?: { published_time?: string; modified_time?: string };
}

Try it live

A merchant's own page (about us, privacy…), found through the footer menu and loaded by its id.Try this: step through the pages: each one is a separate cached query keyed by its id.
Storefront canvas · en · LTR

Reading the footer menu for page links…

Controls
What a theme writes
import { useQuery } from '@tanstack/react-query';
import { page } from '@salla.sa/twilight-theme-engine/api/page';

/** pageId is the number at the end of a page link: …/about-us/page-1061977328 */
export function StorePage({ pageId }: { pageId: string }) {
  const { data } = useQuery(page.queries.detail(pageId));
  if (!data) return null;

  return (
    <article>
      <h1>{data.name}</h1>
      <div className="content-entry" dangerouslySetInnerHTML={{ __html: data.content ?? '' }} />
    </article>
  );
}

Example

app/routes/policy.page-$id.tsx (loader)
import { page } from '@salla.sa/twilight-theme-engine/api/page';

/** A custom route whose URL ends in page-<id>, like the engine's own page route. */
export async function loader({ params }: { params: { id: string } }) {
  const found = await page.findOrThrow(params.id); // a missing page shows the 404 page
  return { title: found.name, html: found.content ?? '' };
}

How it behaves

  • Endpoint: GET pages/{id}. Public.

  • The engine page route is /{-$locale}/$slug/page-{$id}, and its loader calls page.findOrThrow(params.id): whatever the parameter is called, the id is what travels.

  • The engine PageSingle renders content with dangerouslySetInnerHTML, after replacing &nbsp; with spaces.

Gotchas

  • The parameter is named slug, but the API wants the page id. On the demo store a page's slug (the words before /page-) answered HTTP 410; its id answered the page.

  • ApiPageResponse is not exported. Type a result with Awaited<ReturnType<typeof page.find>>.

  • content is raw HTML written in the Salla dashboard. Render it only where the store owner's content belongs, as the engine page does.

Related

Source and docs