
# Bolt.new astrology app, vibe coding guide

> Ship a daily horoscope page, a Life Path calculator, or a tarot reading inside a [Bolt.new](https://bolt.new) app in about twenty minutes, with the API key in Bolt Secrets and never in the bundle.

Bolt builds JavaScript apps from a chat prompt: Node.js on the backend, any framework you like on the front. RoxyAPI gives that app a spiritual-data backend you did not have to write. Three things decide whether it works on the first try: the agent knowing where the truth lives, the key sitting in Secrets rather than a file, and every RoxyAPI call happening in a server function.

## 1. Put the truth sources in project knowledge

Knowledge is background context Bolt applies to every prompt in a project, which is where this belongs rather than in one chat turn. Click the **gear icon** in the top center, choose **All project settings**, open **Knowledge**, and paste:

```
RoxyAPI: one REST API for astrology, Vedic astrology, forecasting, human design, numerology, tarot and 18+ insight domains on one key. Base URL https://roxyapi.com/api/v2. Auth is the X-API-Key header, read from the ROXY_API_KEY secret, called from a server function only, never from browser code.

Where the truth lives, in this order:
1. The docs MCP server at https://roxyapi.com/mcp/docs. Streamable HTTP, no key, one tool: search_docs. Search it before every endpoint, field, SDK method and integration step.
2. https://roxyapi.com/AGENTS.md, read in full before any code. Auth rules, the location-first rule, request body shapes, the error contract, field formats, domain gotchas.
3. The OpenAPI spec, one per domain at https://roxyapi.com/api/v2/{domain}/openapi.json, where the paths are relative to the domain. Read one domain spec, never the combined one at https://roxyapi.com/api/v2/openapi.json: that is 259+ endpoints of schema.
4. No MCP available? Fetch https://roxyapi.com/llms.txt instead.

Rules that do not bend:
- Never say RoxyAPI lacks a feature without searching those first. Never guess a path: a 404 returns a suggestion field with the closest valid one.
- Every chart, horoscope, panchang, dasha and compatibility call needs latitude, longitude and timezone. Resolve them with GET /location/search?q={city} first and pass its timezone through. Never ask a person for coordinates.
- A 200 is clean JSON with no wrapper. Errors are { error, code }, and a 400 carries issues[] with every field problem at once. Retry only 429 and 5xx.
- Add ?lang= for any of en, tr, de, es, hi, pt, fr, ru, zh-Hans, zh-Hant. Machine values stay English; human text translates.
- Install @roxyapi/sdk for typed calls rather than hand-rolling fetch once there is more than one endpoint.
```

**Tip: Bolt can also query the docs server itself while it builds. In the chatbox click the **plus icon**, choose **Connectors**, then **Manage connectors**, then **Custom MCP server**. Name it, set the URL to `https://roxyapi.com/mcp/docs`, set **Transport type** to `HTTP`, and leave **Authentication** on `None`: the docs server is public and needs no key.**

## 2. Put the key in Secrets

Bolt prompts you for a secret the moment a feature needs one, with a link to the Secrets tab. To add it first, click the **database icon** in the top center, open **Secrets**, set **Name** to `ROXY_API_KEY`, paste the value from [your account](/account) into **Value**, and click **Create secret**.

Secrets exist so a server function can read a credential without it ever reaching a browser. That is exactly the shape RoxyAPI needs.

**Warning: Do not put the key in a `.env` file the frontend can read, and never let the agent prefix it for client exposure (`VITE_`, `NEXT_PUBLIC_`, `PUBLIC_`). Those prefixes inline the value into the bundle at build time and anyone with DevTools can copy it. If a page genuinely has no server side, the answer is a publishable `pk_` key locked to your origin, minted at [your account](/account), and the [widgets](/docs/widgets). Also avoid pasting a live key into the chat body: use the Secrets tab.**

## 3. Ask for the feature

Describe what you want. For a whole app rather than one feature, copy a ready prompt from [AI prompts](/docs/prompts): **Add RoxyAPI to an existing app** is the one that fits Bolt, because it makes the agent pick the endpoint from the spec, keep the key server side, and prove the call before it stops.

Two Bolt-specific lines worth adding to any request:

- Put the RoxyAPI call in a server function that reads `ROXY_API_KEY` from the project secret, and have the page call that function, never `roxyapi.com`.
- Cache anything daily for at least an hour.

## Check what Bolt built

Server functions live under the **database icon**, **Server Functions**, with **View Logs** per function when a call fails. Four things to confirm before you publish:

1. The key comes from the secret, never a string literal or a committed file.
2. The header is `X-API-Key`, not `Authorization: Bearer`.
3. No file marked as client code mentions the key or calls `roxyapi.com`.
4. Daily content is cached, not refetched on every render.


### curl

Prove the key works before you blame the generated code:

```bash
curl "https://roxyapi.com/api/v2/astrology/horoscope/aries/daily" \
  -H "X-API-Key: $ROXY_API_KEY"
```

### The server side

Wherever Bolt puts the handler, these are the lines that matter:

```typescript
async function getHoroscope(sign: string, lang?: string) {
  const url = new URL(`https://roxyapi.com/api/v2/astrology/horoscope/${sign}/daily`);
  if (lang) url.searchParams.set('lang', lang);

  const res = await fetch(url, {
    headers: { 'X-API-Key': process.env.ROXY_API_KEY! },
  });
  if (!res.ok) {
    const { error, code } = await res.json();
    throw new Error(`${code}: ${error}`);
  }
  return res.json();
}
```

On a Node runtime the key reads as `process.env.ROXY_API_KEY`. If Bolt generated a Deno style edge function instead, the same line is `Deno.env.get('ROXY_API_KEY')`. Everything else is identical.

### TypeScript SDK

Past the second endpoint, ask Bolt to install [`@roxyapi/sdk`](/docs/sdk) and use it everywhere. Typed methods, exact response types, one client:

```typescript
import { createRoxy } from '@roxyapi/sdk';

const roxy = createRoxy(process.env.ROXY_API_KEY!);

const { data, error } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'aries' },
});
if (error) throw new Error(error.code);
console.log(data.overview, data.luckyNumber, data.luckyColor);
```

### The response

`GET /astrology/horoscope/{sign}/daily` returns, with no wrapper:

```json
{
  "sign": "aries",
  "date": "2026-09-10",
  "overview": "...",
  "love": "...",
  "career": "...",
  "health": "...",
  "finance": "...",
  "advice": "...",
  "column": "...",
  "events": [
    {
      "type": "sign-ingress",
      "at": "2026-09-10T16:21:14Z",
      "bodies": ["Mercury"],
      "sign": "libra",
      "house": 7,
      "through": "2026-09-30T11:44:42Z"
    }
  ],
  "luckyNumber": 9,
  "luckyColor": "Red",
  "moonSign": "Virgo",
  "moonPhase": "Waning Crescent Moon",
  "energyRating": 4
}
```


## Anything with a birth chart needs a place first

Every chart, panchang, dasha, compatibility and synastry call needs `latitude`, `longitude` and `timezone`. A server function proxying `GET /location/search?q={query}` gives you all three from a city name, so nobody has to type coordinates.

The search returns `{ total, limit, offset, cities }`, and each city carries `city`, `province`, `country`, `iso2`, `latitude`, `longitude`, `timezone` and `utcOffset`. Feed `latitude`, `longitude` and `timezone` straight into `POST /astrology/natal-chart` alongside `date` as `YYYY-MM-DD` and `time` as `HH:MM:SS`. `timezone` takes an IANA name such as `"America/New_York"`, resolved server side to the daylight-saving-correct offset for that date, or decimal hours such as `-5`.

Debounce the city input at 300ms and a full chart costs two calls.

## The five fixes

| What went wrong | What to say in chat |
|---|---|
| The key exposed to the client | Rename any `VITE_`, `NEXT_PUBLIC_` or `PUBLIC_` prefixed RoxyAPI variable to `ROXY_API_KEY` and read it from the project secret in a server function. |
| Fetch inside a client component | Move the RoxyAPI fetch into a server function and have the component call that function. |
| The key inlined in source | Search the project for the literal key string and replace every occurrence with the secret lookup. |
| No caching | Cache daily content for at least an hour. A horoscope page with an autofetch hook and no cache burns a month of quota in an afternoon. |
| No error handling | Return the upstream status and the `{ error, code }` body. 401 is the key, 429 is quota, 400 carries `issues[]` with every field problem at once. |

## Publish

Bolt hosting is the default, and your secrets travel with the project. To publish to Netlify instead, connect the account first: **gear icon**, **All project settings**, **Applications** under Account settings, then **Connect** in the Netlify section. Then open **Domains & Hosting**, pick **Netlify** in the hosting dropdown, close settings, and click **Publish**.

**Warning: The switch to Netlify only works on a project that has never been published to Bolt hosting. After the first Bolt publish there is no way back; you would need a fresh unpublished copy.**

## Gotchas

- **JavaScript only.** Bolt supports Node.js on the backend and browser-native frontend code. A Python or PHP backend is not an option here, so the RoxyAPI SDK you want is the TypeScript one.
- **Backend only key.** A secret `sk_` key belongs in Secrets and is read by server functions. Browser code gets a publishable `pk_` key locked to your origin, or nothing.
- **Rotate what leaks.** If a key ever reaches a chat log, a commit, or a screenshot, mint a new one at [your account](/account) and delete the old.
- **Check `.gitignore` before the first push** if you sync the project to GitHub.
- **Prefer IANA timezones.** `"Europe/London"` resolves to the correct offset for the birth date. A decimal offset such as `-5` knows nothing about daylight saving.
- **Mobile has no Code view, project settings or database**, so add secrets and knowledge from a desktop browser.

## What to build next

- **Domain guides**, for which endpoints to call in what order:
  - [Western Astrology](/docs/guides/astrology), [Vedic Astrology](/docs/guides/vedic-astrology), [KP Astrology](/docs/guides/kp), [Forecast](/docs/guides/forecast), [Human Design](/docs/guides/human-design), [Chinese Astrology](/docs/guides/chinese-astrology), [Feng Shui](/docs/guides/feng-shui), [Mesoamerican Astrology](/docs/guides/mesoamerican-astrology), [Vastu](/docs/guides/vastu), [Numerology](/docs/guides/numerology), [Kabbalah](/docs/guides/kabbalah), [Tarot](/docs/guides/tarot), [Biorhythm](/docs/guides/biorhythm), [Ayurveda](/docs/guides/ayurveda), [I Ching](/docs/guides/iching), [Crystals](/docs/guides/crystals), [Dreams](/docs/guides/dreams), [Angel Numbers](/docs/guides/angel-numbers)
- [AI prompts](/docs/prompts): whole-app prompts for birth charts, Vedic, tarot, numerology and dream journals.
- [Next.js](/docs/integrations/nextjs): the App Router patterns behind a server-rendered build.
- [Remote MCP](/docs/mcp): connect a chatbot to live calculations instead of wiring endpoints one at a time.
- [API reference](/api-reference): the human playground, where you can try any endpoint in the browser.
