Quickstart
Quickstart — Urja in five minutes
The shortest path from "I don't have a key" to "rendered visuals in my app." For the full surface, see the integration guide.
1. Get a key (30 seconds)
Email admin@insightsbyomkar.com with a one-line description of what you're building. You'll get back a JWT scoped to a plan (free / pro / max). Store it as URJA_API_KEY (or whatever name you prefer) in your env — never commit it.
Heads up: a lot of Urja is public, no key required — tokens, fonts, motion, icons, flags, ornaments, pricing-card and umbrella-hero scenes. If that's all you need, skip to step 3.
2. Install the client (optional, 30 seconds)
The typed URL builders + React ThemeProvider ship in the urja-client package:
npm install urja-client
Not using React, or want zero dependencies? Skip the install — every Urja endpoint is a plain GET. Write the URL by hand and you're done.
3. Load the theme (1 minute)
Drop these tags into your document head. They load the --ds-* semantic token layer, the self-hosted Fraunces + Inter fonts, and the motion primitives — all public, no JWT required.
<!-- Tokens: --ds-bg-*, --ds-text-*, --ds-accent-gold, etc -->
<link rel="stylesheet"
href="https://urja.insightsbyomkar.com/api/v1/tokens?format=css&version=1.4.0" />
<!-- Fonts: @font-face + WOFF2 binaries, preload the above-the-fold face -->
<link rel="preload"
href="https://urja.insightsbyomkar.com/api/v1/fonts/display/display-400-normal-latin.woff2"
as="font" type="font/woff2" crossorigin="anonymous" />
<link rel="stylesheet"
href="https://urja.insightsbyomkar.com/api/v1/fonts?format=css&families=display,sans" />
<!-- Motion: easings, durations, 9 UI primitives -->
<link rel="stylesheet"
href="https://urja.insightsbyomkar.com/api/v1/motion?format=css&set=all" />
After those load, your page gets:
- Any
color: var(--ds-text-strong)/background: var(--ds-bg-canvas)
style rules resolve to brand-correct values with automatic light/dark switching via prefers-color-scheme and [data-theme="dark"].
font-family: var(--ds-font-display)/var(--ds-font-sans)works
anywhere.
.m-hover-lift,.m-stagger-in,.m-modal-enter, etc, are
available class names.
Using React + urja-client
One-line setup replaces all three <link> tags:
import { VisualThemeProvider } from "urja-client";
export default function RootLayout({ children }) {
return (
<VisualThemeProvider tokensVersion="1.4.0">
{children}
</VisualThemeProvider>
);
}
4. Render your first visual (1 minute)
Everything Urja returns is a cacheable GET. You can drop any URL straight into an <img>.
Pricing-card atmosphere (public)
<img
src="https://urja.insightsbyomkar.com/api/v1/scene?type=pricing-card&product=netra&tier=pro"
alt="Netra pricing card atmosphere"
width="600" height="400" />
Country flag (public)
<img
src="https://urja.insightsbyomkar.com/api/v1/illustrate?type=flag&country=IN&style=full&size=32"
alt="India flag"
width="48" height="32" />
Character render (needs key)
<img
src="https://urja.insightsbyomkar.com/api/v1/character?pose=listening&mood=attentive&size=256"
alt="Lucky listening"
width="256" height="256" />
Wait — that image tag has no key in it. You have two options:
Option A — server-side proxy. Recommended for production. Route the request through your own backend, which attaches the JWT:
// app/api/urja/character/route.ts (Next.js App Router)
export async function GET(req: Request) {
const url = new URL(req.url);
const upstream = new URL(
"https://urja.insightsbyomkar.com/api/v1/character",
);
url.searchParams.forEach((v, k) => upstream.searchParams.set(k, v));
const res = await fetch(upstream, {
headers: { authorization: `Bearer ${process.env.URJA_API_KEY}` },
});
return new Response(await res.arrayBuffer(), {
status: res.status,
headers: {
"content-type": res.headers.get("content-type") ?? "image/svg+xml",
"cache-control": res.headers.get("cache-control") ?? "public, max-age=86400",
},
});
}
Then use <img src="/api/urja/character?pose=listening" />.
Option B — ephemeral key via query param. For prototypes only — browser-visible keys leak. Don't ship this to production.
5. Read the rate-limit headers
Every authenticated response carries these headers. Read them from your proxy's fetch response and thread them to your client if you want to show quota-aware UI:
X-RateLimit-Limit-Minute/X-RateLimit-Remaining-Minute/X-RateLimit-Reset-MinuteX-RateLimit-Limit-Day/X-RateLimit-Remaining-Day/X-RateLimit-Reset-DayRetry-After— only on429, seconds to wait.
See the rate-limit section of the integration guide for the full table.
Typed URL builders
If you installed urja-client, use the typed helpers to avoid hand-concatenating query strings:
import {
buildPricingCardUrl,
buildUmbrellaHeroUrl,
buildSceneUrl,
buildCharacterUrl,
buildTokensUrl,
} from "urja-client";
const bg = buildPricingCardUrl({ product: "netra", tier: "max" });
const hero = buildUmbrellaHeroUrl({ motion: "drift" });
const scene = buildSceneUrl({ pose: "listening", background: "aurora" });
const character = buildCharacterUrl({ pose: "resting", mood: "quiet" });
const cssHref = buildTokensUrl({
format: "css",
layer: "semantic",
version: "1.4.0",
});
Next steps
- Integration guide — every endpoint, auth, caching, errors,
full parameter tables.
- Framework recipes — copy-paste setups for Next.js,
Astro, plain HTML, vanilla JS.
- Health endpoint —
GET /api/healthreturns live
service status + version.
— per-release notes. Per-track changelogs in docs/changelog/.
Stuck? Email admin@insightsbyomkar.com.
