Getting started

Core concepts

Authentication, the client, content model, caching, and theming knobs.

Before diving deeper, it helps to understand the core concepts behind the Vlozi Blog implementation.

Authentication

The SDK uses API keys to authenticate requests. Since most blog content is public, you should use a public key.

  • Public keys: Safe to expose in your frontend code (e.g., in React components). They provide read-only access to published content.
  • Secret keys: Should never be exposed to the client. Used for server-side administrative tasks.

The Vlozi client

The VloziClient is the core of the SDK. It handles all network requests, caching, and error handling. You typically instantiate it once and share it across your app.

const client = new VloziClient({
    apiKey: "pk_live_...", // Your public key
    baseUrl: "https://api.vlozi.app" // Your gateway URL
});

The provider pattern

To make the client available to all React components without prop drilling, use the VloziProvider. This uses React Context under the hood.

<VloziProvider client={client}>
    <App />
</VloziProvider>

Content model

Every blog post can have an optional category (single-select) and multiple tags (multi-select). This gives you two axes for organizing content:

  • Categories: Broad, hierarchical groupings (e.g., "Tutorials", "News", "Case Studies"). Each post belongs to zero or one category.
  • Tags: Cross-cutting labels (e.g., "react", "nextjs", "performance"). Each post can have multiple tags.

Both categories and tags are created and managed in the Vlozi Dashboard. The SDK provides hooks and components to list them and filter posts by them.

Filtering, search, and sort

The SDK supports powerful query capabilities when listing posts:

  • Category filter: Pass a category slug to show only posts in that category.
  • Tag filter: Pass a tag slug to show only posts with that tag.
  • Search: Free-text search across post titles and excerpts.
  • Sort: Order results by publishedAt, title, or createdAt.
  • Order: Choose asc (ascending) or desc (descending) direction.
// Example: Search for "react" tutorials, sorted by title A-Z
const { data } = usePosts({
    search: "react",
    category: "tutorials",
    sort: "title",
    order: "asc"
});

Caching strategy

The VloziClient ships with an in-memory LRU cache (default: 100 entries, 60s TTL, stale-while-revalidate window of 5×TTL). React hooks subscribe to cache changes via useSyncExternalStore, so calling client.invalidate(/foo/) or client.mutate(key, post) automatically re-renders consumers.

You can swap in your own implementation (Redis, Upstash, Cloudflare KV, etc.) by passing any object that implements the CacheAdapter interface to the client constructor:

new VloziClient({
    apiKey: "pk_*",
    baseUrl: "https://api.vlozi.app",
    cache: myRedisAdapter,           // CacheAdapter | false; false disables caching
    cacheTtlMs: 60_000,              // default TTL for cached GETs
});

Sanitization and hydration

Post HTML is sanitized server-side at write time. The SDK's <BlogContent> component re-runs a defense-in-depth sanitizer client-side, then progressively hydrates known rich blocks:

  • Mermaid diagrams<pre><code class="language-mermaid"> blocks are upgraded to live SVG via the mermaid package (lazy-loaded only when needed).
  • Carousels<div data-type="carousel"> placeholders become Embla-powered swipe carousels (with a known production gap — see Troubleshooting).
  • YouTube embeds — only youtube-nocookie.com/ and youtube.com/embed/ iframes survive sanitization. Watch URLs are stripped.
  • Inline body images — when you pass an imageComponent prop, every <img> tag is upgraded to your component (Next.js Image, Gatsby Image, etc.) via portal mounting.

The five --vlz-* CSS knobs

Every styled element in the SDK derives its color from one of five custom properties. Override these on .vlz-content (or any ancestor) to theme the prose without writing rule-by-rule overrides:

  • --vlz-accent — links, syntax keywords, blockquote rule, active states
  • --vlz-muted-fg — figcaptions, list markers, secondary text
  • --vlz-border — tables, <hr>, <details>, card borders
  • --vlz-surface — code blocks, table headers, card surfaces
  • --vlz-surface-hover — hover state on surfaces
/* shadcn-style HSL */
.vlz-content {
  --vlz-accent:        hsl(var(--primary));
  --vlz-muted-fg:      hsl(var(--muted-foreground));
  --vlz-border:        hsl(var(--border));
  --vlz-surface:       hsl(var(--muted) / 0.6);
  --vlz-surface-hover: hsl(var(--muted) / 0.8);
}
Blog · Getting startedEdit on GitHub