Skip to main content

Theme Dev Preview

The SDK theme dev preview lets you test a theme you're building locally against a real profile page — with live user data, real link icons, and real installed apps — without uploading a bundle or changing the profile's active theme for anyone else.


How to use it

  1. Create a Developer Project at My Apps → Developer Mode and point it at your local dev server (e.g. https://shuuka-theme.local).
  2. Note the numeric project ID shown in the dev mode page.
  3. Open any profile URL and append ?dev_theme={id}:
    https://shuuka.com/username?dev_theme=2
  4. The page renders with your local theme. No other visitor sees the change.

Only the authenticated profile owner can use ?dev_theme. It is silently ignored for all other visitors.


What the platform does

When ?dev_theme={id} is present:

  1. The API fetches your local theme.config.json and merges it with the user's active theme settings — keeping profile data, links, and app layout intact.
  2. config.iframe in the merged result is replaced entirely with your theme's own iframe section. This prevents the user's production card settings (background, shadow, radius, etc.) from leaking into your theme's card design through inline CSS.
  3. The theme entry URL is set to https://api.shuuka.com/en/v1/dev-theme/{id}/entry.
  4. The profile page loads an <iframe> pointed at that URL.
  5. The API proxy fetches index.html from your dev server, rewrites ./-relative asset paths to serve through the proxy (so /sdk/js/… imports resolve correctly), and returns the modified HTML.

Path resolution inside your iframe

Your theme iframe runs from api.shuuka.com (the proxy URL), not from your dev server's origin. URL resolution changes accordingly:

Path typeExampleResolves to
./-relative./dist/index.jsProxied to your dev server ✅
Root-relative SDK/sdk/js/index.jsapi.shuuka.com/sdk/js/…
Root-relative icons/social_icons/shuuka-Instagram.pngapi.shuuka.com/social_icons/…
Vite dev src/src/index.jsapi.shuuka.com/src/index.js404

Important: When your dev server is running Vite, the theme's src/index.js module is served by Vite at /src/index.js. When proxied through the API, this path 404s because there is no /src/ directory on the API server.

Production bundle (./dist/index-xxx.js) is not affected — it uses a ./ relative path, which the proxy rewrites correctly.

What this means for your SCSS

Because src/index.js (the CSS vars bridge) does not load in Vite dev proxy mode, all your CSS custom properties need var(…, fallback) defaults in your SCSS that match your theme.config.json exactly:

.shk-theme__app-card {
background: var(--app-card-bg, rgba(255, 248, 230, 0.045));
border-radius: var(--app-card-radius, 18px);
box-shadow: var(--app-card-shadow, 0 8px 32px rgba(0, 0, 0, 0.60));
border-color: var(--app-card-border-color, rgba(201, 168, 76, 0.12));
}

.shk-theme__link {
width: var(--links-icon-size, 52px);
height: var(--links-icon-size, 52px);
}

Initial appearance will look correct. Live dashboard preview edits will only propagate after a hard reload (when using Vite dev mode). With the production built dist, both initial appearance and live preview work fully.


Requirements for your theme files

theme.config.json

Must include an iframe section, a links section, and meta.color_scheme:

{
"meta": {
"name": "My Theme",
"version": "1.0.0",
"color_scheme": "dark"
},
"config": {
"iframe": {
"background": "rgba(0, 0, 0, 0.5)",
"border_radius": 16,
"shadow": "md",
"padding": 0,
"border_style": "solid",
"border_width": 1,
"border_color": "rgba(255, 255, 255, 0.1)"
},
"links": {
"visible": true,
"alignment": "center",
"wrap": true,
"item_size": 48,
"spacing": 8
}
}
}

Without the iframe section, the platform replaces config.iframe with [] — no inline card CSS vars are set, only your SCSS fallbacks apply.

Without color_scheme, embedded app iframes receive no dark/light signal and default to light mode.

src/index.js

Must implement applyIframeCssVars(cfg) and applyLinksCssVars(cfg) and call them inside the shuuka:contextSnapshot / shuuka:ctx message handler. These functions write CSS custom properties to :root, keeping card and link styles in sync with dashboard preview changes.

See the platform developer reference (docs/SDK_THEME_DEV_PREVIEW.md) for the canonical implementation.


Social icons in dev preview

Social network link icons are rendered as:

<img src="/social_icons/shuuka-Instagram.png" alt="" loading="lazy">

Inside your proxied iframe (origin: api.shuuka.com), the root-relative path resolves to api.shuuka.com/social_icons/shuuka-Instagram.png — served from the API server's public/social_icons/ directory.

If icons appear missing:

  1. Open browser DevTools → Network → filter social_icons
  2. Confirm requests return 200 from api.shuuka.com
  3. If 404: a file is missing from the API server's public/social_icons/ folder

Keeping local dev and the platform-apps bundle in sync

Once your theme is ready to be published, the files in resources/platform-apps/Themes/<name>/ must be identical to your local dev source.

# Verify they are in sync:
diff resources/platform-apps/Themes/<name>/src/index.js \
/path/to/your-theme-local/src/index.js

# After any change to src/index.js, rebuild the dist:
cd resources/platform-apps/Themes/<name>
npm run build

The built dist/ is what the proxy serves in production via the ./ relative path.