Skip to content

Commit 9371ac9

Browse files
committed
docs: AGENTS.md canonical at root, mirrored to packages on build
1 parent 7389155 commit 9371ac9

9 files changed

Lines changed: 661 additions & 405 deletions

File tree

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ packages/ui/src/types/
1818
packages/ui/dist/
1919
packages/ui-react/dist/
2020

21+
# Root AGENTS.md is the canonical source for AI-agent integration guidance.
22+
# `copyRootDocsToWorkspaces` in `scripts/build.ts` mirrors it into both
23+
# packages on every `bun run build` so the npm tarballs (which ship the file
24+
# via each package.json `files` allowlist) carry an up-to-date copy. The
25+
# per-package copies are build artifacts; never edit them directly, edit
26+
# root AGENTS.md. README.md and LICENSE follow the same mirror pattern but
27+
# remain git-tracked for GitHub package-directory UX.
28+
packages/ui/AGENTS.md
29+
packages/ui-react/AGENTS.md
30+
2131
# apps/docs/dist is mirrored from packages/ui/dist on each `bun run build`
2232
# so local preview at apps/docs/ matches the GitHub Pages layout exactly.
2333
apps/docs/dist/

AGENTS.md

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Roxy UI is the official web component library for the RoxyAPI catalog. Component
1414

1515
### Pick by user phrase
1616

17-
Map the user's natural-language request to a component first; fall back to the table below if the request names a specific endpoint.
17+
Map the natural-language request to a component first; fall back to the table below if the request names a specific endpoint.
1818

1919
| If the user says... | Render |
2020
|---|---|
@@ -78,9 +78,13 @@ Use the table below for the formal endpoint to component mapping.
7878
| `<roxy-data>` | Helper | Any response shape | Generic fallback renderer for unknown shapes |
7979
<!-- END:COMPONENTS -->
8080

81-
## SDK response envelope (read this first)
81+
## Common integration bugs (read this first)
8282

83-
The `@roxyapi/sdk` returns `{ data, error, request, response }`. **Always destructure `data` before passing to a component.** Passing the full envelope produces `[object Object]` in the rendered chart. This is the single most common integration bug.
83+
These are the bugs that come up over and over. Read this section before writing the first line of integration code.
84+
85+
### 1. Envelope not unwrapped
86+
87+
The `@roxyapi/sdk` returns `{ data, error, request, response }`. **Always destructure `data` before passing to a component.** Passing the full envelope renders `[object Object]`. This is the single most common integration bug.
8488

8589
```ts
8690
// Wrong: passes the envelope
@@ -94,9 +98,79 @@ element.data = data;
9498

9599
Every snippet below follows this rule.
96100

97-
## Timezone format
101+
### 2. Hardcoded coordinates
102+
103+
Every chart endpoint (Western, Vedic, KP, synastry, transits, dasha, dosha, panchang) needs `latitude`, `longitude`, and `timezone`. Never ask the user to type coordinates. Call `/location/search` first, then feed the result into the chart endpoint.
104+
105+
```ts
106+
// Right
107+
const { data: cities } = await roxy.location.searchCities({ query: { q: 'Mumbai' } });
108+
const { latitude, longitude, timezone } = cities.cities[0];
109+
const { data: chart } = await roxy.astrology.generateNatalChart({
110+
body: { date, time, latitude, longitude, timezone },
111+
});
112+
```
113+
114+
### 3. Timezone format inconsistency
115+
116+
Every chart endpoint accepts `timezone` as either a decimal-hour offset (`5.5` for IST, `-5` for EST) or an IANA name (`'Asia/Kolkata'`, `'America/New_York'`). The decimal form is what `/location/search` returns; the IANA form is correct over DST boundaries. Pick one and stay consistent in a single integration. Mixing them does not break the API but makes the bug surface area larger.
117+
118+
### 4. Secret key in the browser
119+
120+
There are two key classes. **Secret keys are unprefixed** and grant full access; they belong server-side only (Node, Bun, Hono, Next.js route handlers, Workers, Edge functions). **Publishable keys** are prefixed `pk_live_*` or `pk_test_*` and are safe in the browser; they are locked to an origin allowlist at the API gateway. For widgets, embeds, vanilla HTML, and `data-publishable-key` use the publishable key. For the typed SDK on a server, use the secret key.
121+
122+
```ts
123+
// Server (Next.js route handler, Workers, Bun): secret key
124+
const roxy = createRoxy(process.env.ROXY_API_KEY!);
125+
126+
// Browser (widgets auto-mount): publishable key
127+
<div data-roxy-widget="natal-chart" data-publishable-key="pk_live_xxx" ...></div>
128+
```
129+
130+
### 5. Missing `'use client'` in Next.js App Router
131+
132+
The React components in `@roxyapi/ui-react` mount Custom Elements, which need the DOM. In the App Router, files that import them must declare `'use client'` at the top. Server Components can fetch with the SDK; the client component renders.
98133

99-
Every chart endpoint accepts `timezone` as either a decimal-hour offset (`5.5` for IST, `-5` for EST) or an IANA name (`'Asia/Kolkata'`, `'America/New_York'`). The decimal form is what `/location/search` returns; pick one and stay consistent within a single integration.
134+
```tsx
135+
// app/chart-view.tsx
136+
'use client';
137+
import { RoxyNatalChart } from '@roxyapi/ui-react';
138+
139+
export default function ChartView({ data }) {
140+
return <RoxyNatalChart data={data} />;
141+
}
142+
```
143+
144+
### 6. React 17 or 18 swallowing custom events
145+
146+
React 19 routes hyphenated DOM events through camelCase props correctly. React 17 and 18 do not. On 17/18, attach the listener with a ref:
147+
148+
```tsx
149+
const ref = useRef<HTMLElement>(null);
150+
useEffect(() => {
151+
const el = ref.current;
152+
if (!el) return;
153+
const handler = (e: Event) => setData((e as CustomEvent).detail);
154+
el.addEventListener('roxy-location-select', handler);
155+
return () => el.removeEventListener('roxy-location-select', handler);
156+
}, []);
157+
158+
return <roxy-location-search ref={ref} />;
159+
```
160+
161+
The React 19 path is `<RoxyLocationSearch onRoxyLocationSelect={handler} />`.
162+
163+
### 7. Local response interface drift
164+
165+
Do not declare `interface XyzData { ... }` for a RoxyAPI response. Import the spec-derived type from `@roxyapi/sdk` (or let the SDK return type flow through inference). Local interfaces drift the moment the spec changes; the component will keep compiling while rendering nothing.
166+
167+
```ts
168+
// Wrong
169+
interface NatalChart { planets: ...; houses: ...; }
170+
171+
// Right
172+
import type { NatalChartResponse } from '@roxyapi/sdk';
173+
```
100174

101175
## Integration patterns
102176

@@ -173,15 +247,15 @@ export function BirthChartView() {
173247
const form = document.querySelector('roxy-endpoint-form');
174248
form.addEventListener('roxy-submit', async (e) => {
175249
const { values } = e.detail;
176-
const { data: kundli } = await roxy.vedic.generateBirthChart({ body: values });
250+
const { data: kundli } = await roxy.vedicAstrology.generateBirthChart({ body: values });
177251
document.querySelector('roxy-vedic-kundli').data = kundli;
178252
});
179253
</script>
180254
```
181255

182256
### Pattern 4: widgets auto-mount (no JavaScript wiring)
183257

184-
Use a publishable key (`pk_live_*` or `pk_test_*`) for client-side embeds. Get one at <https://roxyapi.com/account>. Publishable keys are origin-restricted at the API gateway. Register the customer's domain (e.g. `https://customer.com`) when creating the key, and the gateway will reject requests from any other origin. Never use a secret key in client-side code (secret keys are unprefixed and live server-side only).
258+
Use a publishable key (`pk_live_*` or `pk_test_*`) for client-side embeds. Get one at <https://roxyapi.com/account>. Publishable keys are origin-restricted at the API gateway. Register the customer domain (e.g. `https://customer.com`) when creating the key, and the gateway will reject requests from any other origin. Never use a secret key in client-side code (secret keys are unprefixed and live server-side only).
185259

186260
```html
187261
<script
@@ -265,7 +339,7 @@ When listing domains in user-visible copy, use the canonical order: Western astr
265339
- Use `@roxyapi/ui-react` for React projects. Use `@roxyapi/ui` directly elsewhere.
266340
- Do not write your own kundli component. The lifted layout in `<roxy-vedic-kundli>` is the canonical RoxyAPI render path.
267341
- Do not call astrology endpoints with hardcoded coordinates. Always geocode first via `<roxy-location-search>` or `roxy.location.searchCities()`.
268-
- Do not declare a local `interface XyzData` to describe a RoxyAPI response. Import the type from the spec-derived bundle: `import type { XyzResponse } from '@roxyapi/ui'` (or the SDK's typed methods). Local interfaces drift the moment the spec changes.
342+
- Do not declare a local `interface XyzData` to describe a RoxyAPI response. Import the type from the spec-derived bundle: `import type { XyzResponse } from '@roxyapi/sdk'`. Local interfaces drift the moment the spec changes.
269343
- Do not write Tailwind utility classes inside a component. The Shadow DOM boundary stops them at the door. Theme through `--roxy-*` CSS custom properties on `:root` or per element instead.
270344
- Do not fetch inside chart, table, or card components. They are stateless: pass `data` as a prop. Documented exceptions are `<roxy-location-search>`, `<roxy-endpoint-form>`, and the widgets auto-mount script.
271345
- Do not redefine theme tokens or invent your own naming. Override the existing `--roxy-*` custom properties; the full list is in `THEMING.md`.

0 commit comments

Comments
 (0)