# Soft Hours Diary CDN — Complete AI Integration Context

Use this document as the canonical implementation reference for the public Soft Hours Diary emoji and flag CDN. Do not invent asset types, quality values, routes or response fields.

## Service

- CDN base: [https://softhoursdiary-emojis.pages.dev/[](https://softhoursdiary-emojis.pages.dev/[)
- Main brand website origin: https://softhoursdiary.pages.dev
- Simple image URL usage: no script, package, API key or authentication.
- JSON resolver: GET https://softhoursdiary-emojis.pages.dev/[api/v1/asset
- Optional browser helper: https://softhoursdiary-emojis.pages.dev/[soft-hours-diary.js
- Documentation: https://softhoursdiary-emojis.pages.dev/[api/
- REST API guide: https://softhoursdiary-emojis.pages.dev/[api/rest/
- Playground: https://softhoursdiary-emojis.pages.dev/[api/playground/

## Choose an integration

1. **Simple direct URL (recommended for fixed assets):** use a normal HTML `img` or CSS background with the exact public path. No JavaScript or package is needed.
2. **JSON API (for dynamic applications):** call `GET /api/v1/asset` with `type`, `id`, and optional `quality`. The endpoint returns a JSON object containing a resolved image URL. No package or API key is needed.
3. **Optional browser helper:** load `/soft-hours-diary.js` with a script tag when reusable DOM helpers or custom elements are useful. It exposes `window.SoftHoursDiary`. This is a standalone browser script, not an npm package.

## Exact asset paths

### Emoji

- Canonical type: `emoji`; accepted alias: `emojis`.
- Quality: `svg` (default) or `png`.
- SVG path: `/emojis/svg/{unicode}.svg`.
- PNG path: `/emojis/72x72/{unicode}.png`.
- ID: hexadecimal Unicode code point(s), lowercase, joined by hyphens for multi-code-point sequences.
- A literal Unicode emoji can be supplied to the JSON resolver or browser helper; it is normalised to hexadecimal.
- Example SVG: https://softhoursdiary-emojis.pages.dev/[emojis/svg/1f632.svg
- Example PNG: https://softhoursdiary-emojis.pages.dev/[emojis/72x72/1f632.png

### Flag SVG

- Type: `flag`.
- Quality: `s`, `m`, `l`; default `m`.
- Path: `/flag/{quality}/{CODE}.svg`.
- IDs are normalised to uppercase.
- Example: https://softhoursdiary-emojis.pages.dev/[flag/l/IN.svg

### Flag icons

- Canonical type: `flags`; aliases: `flag-icon`, `flagicon`.
- Quality: `1x1` or `4x3`; default `4x3`.
- Path: `/flags/{quality}/{code}.svg`.
- IDs are normalised to lowercase.
- Example: https://softhoursdiary-emojis.pages.dev/[flags/4x3/in.svg

## JSON resolver API

### Endpoint

`GET https://softhoursdiary-emojis.pages.dev/[api/v1/asset`

Required query parameters:
- `type`: `emoji`, `flag` or `flags` (aliases above are accepted).
- `id`: Unicode hex/literal emoji sequence or flag code.

Optional:
- `quality`: defaults to `svg` for emoji, `m` for flag, and `4x3` for flag icons.

Examples:
- `/api/v1/asset?type=emoji&id=1f632&quality=svg`
- `/api/v1/asset?type=emoji&id=%F0%9F%98%B3&quality=svg`
- `/api/v1/asset?type=flag&id=IN&quality=l`
- `/api/v1/asset?type=flags&id=IN&quality=4x3`

### Success response

```json
{
  "ok": true,
  "data": {
    "type": "emoji",
    "id": "1f632",
    "quality": "svg",
    "path": "/emojis/svg/1f632.svg",
    "url": "https://softhoursdiary-emojis.pages.dev/[emojis/svg/1f632.svg",
    "mimeType": "image/svg+xml"
  },
  "meta": {
    "apiVersion": "1.0.0"
  }
}
```

### Error response

```json
{
  "ok": false,
  "error": {
    "code": "invalid_quality",
    "message": "Emoji quality must be \"svg\" or \"png\"."
  },
  "meta": {
    "apiVersion": "1.0.0"
  }
}
```

Errors use HTTP 400 for missing or invalid parameters, 405 for unsupported methods, and 500 for unexpected server errors. Supported methods are GET, HEAD and OPTIONS. Responses are JSON. The resolver is public and read-only, requires no API key and supports cross-origin fetch with wildcard CORS. It has no user-specific data and uses short public caching for successful URL resolutions.

Important: a valid response means the URL was constructed. It does not confirm that a corresponding image file exists. The browser or your HTTP client determines whether the asset URL returns an image successfully.

### Fetch example

```js
async function getAssetUrl({ type, id, quality }) {
  const params = new URLSearchParams({ type, id, quality });
  const response = await fetch(
    "https://softhoursdiary-emojis.pages.dev/[api/v1/asset?" + params
  );
  const result = await response.json();

  if (!response.ok || !result.ok) {
    throw new Error(result.error?.message || "Asset lookup failed.");
  }

  return result.data.url;
}
```

## Simple direct URL examples

```html
<img
  src="https://softhoursdiary-emojis.pages.dev/[emojis/svg/1f632.svg"
  alt="Surprised face"
  width="36"
  height="36"
  loading="lazy"
  decoding="async"
>
```

```css
.reaction {
  width: 32px;
  height: 32px;
  background: url("https://softhoursdiary-emojis.pages.dev/[emojis/svg/1f632.svg") center / contain no-repeat;
}
```

## Optional browser helper (no package)

Load:

```html
<script defer src="https://softhoursdiary-emojis.pages.dev/[soft-hours-diary.js"></script>
```

Use `window.SoftHoursDiary` after the script loads.

- `getUrl({ type, quality, id, baseUrl? })` → absolute URL string.
- `emojiUrl(id, { quality?, format?, baseUrl? }?)` → emoji URL.
- `flagUrl(id, { quality?, baseUrl? }?)` → flag URL.
- `flagIconUrl(id, { quality?, baseUrl? }?)` → flag icon URL.
- `createImage(options)` → HTMLImageElement.
- `mount(target, options)` → updates or appends an image.
- `scan(scope?)` → processes data-shd attributes.
- `createReactComponents(React)` → React adapter functions.
- `registerElements()` → registers supported custom elements.

The helper constructs URLs locally. It does not make a request or guarantee file availability.

## React

For a fixed asset, render a regular image:

```jsx
export function Reaction() {
  return (
    <img
      src="https://softhoursdiary-emojis.pages.dev/[emojis/svg/1f632.svg"
      alt="Surprised face"
      width={36}
      height={36}
      loading="lazy"
      decoding="async"
    />
  );
}
```

For dynamic asset IDs, call the JSON resolver and use the returned `data.url` in state or fetch it in a server component.

## Next.js

For a fixed image, a regular `img` needs no configuration. If using `next/image`, add `softhoursdiary-emojis.pages.dev` to `images.remotePatterns`. For dynamic IDs, fetch the JSON resolver from a Server Component and render its `data.url`. Do not assume the endpoint checks file availability.

## TypeScript

The JSON API response shape is:

```ts
type AssetType = "emoji" | "flag" | "flags";
interface AssetApiSuccess {
  ok: true;
  data: {
    type: AssetType;
    id: string;
    quality: string;
    path: string;
    url: string;
    mimeType: "image/svg+xml" | "image/png";
  };
  meta: { apiVersion: "1.0.0" };
}
interface AssetApiError {
  ok: false;
  error: { code: string; message: string };
  meta: { apiVersion: "1.0.0" };
}
type AssetApiResponse = AssetApiSuccess | AssetApiError;
```

Use runtime checks on JSON responses; TypeScript annotations do not validate network data.

## CORS

- Static CDN file responses use the configured exact allowlist origin: `https://softhoursdiary.pages.dev`.
- Ordinary `img` rendering does not require CORS permission to read the response.
- The JSON resolver Function sets its own `Access-Control-Allow-Origin: *` because it is a public read-only URL resolver with no credentials or user data.
- If Pages Functions are used, their CORS headers must be returned by the Function itself; static `_headers` rules do not automatically configure Function-generated responses.

## Crawler policy

The documentation tree is indexable. `robots.txt` asks crawlers not to crawl raw asset folders and the JSON resolver route. Asset responses also carry `X-Robots-Tag: noindex, nofollow, nosnippet`. Robots directives are advisory, not access control. Asset files remain public and direct requests remain possible.

## Performance and accessibility

- Use meaningful alt text for informative images; use empty alt text for decorative images.
- Set width and height to reduce layout shift.
- Lazy-load below-the-fold images.
- Prefer direct image URLs for fixed assets; use the JSON resolver only when URL parameters are dynamic.
