- Docs
- What To Build
- Daily Horoscope Widget
Build a daily horoscope widget
Ship a 12-sign horoscope page in pure HTML with no framework and no backend. Time to ship: 20 minutes.
This is the fastest end-to-end build in the Roxy catalog. No framework, no bundler, no backend. Double-click the file, it opens in the browser, clicking a sign renders a card. Perfect for wellness embeds, lifestyle apps, and landing-page widgets.
What you can build with this
- Standalone daily horoscope pages
- Wellness and meditation app daily-check-in cards
- Landing-page widgets that refresh automatically
- Weekly and monthly variants with the same render code
- Personalized forecasts by layering on
POST /astrology/transitswith a saved natal chart
What you need, 30 seconds
- A Roxy API key. Get one on the pricing page.
- A text editor and a browser. That is it.
Step 1, call your first endpoint
One GET, one sign, everything you need to render a card. Pick a language.
curl "https://roxyapi.com/api/v2/astrology/horoscope/aries/daily" \
-H "X-API-Key: $ROXY_API_KEY"
import { createRoxy } from '@roxyapi/sdk';
const roxy = createRoxy(process.env.ROXY_API_KEY!);
const { data } = await roxy.astrology.getDailyHoroscope({ path: { sign: 'aries' } });
console.log(data.overview); // paragraph forecast
console.log(data.love); // love-specific paragraph
console.log(data.luckyNumber); // 7
console.log(data.compatibleSigns); // ["Leo", "Sagittarius"]
import os
from roxy_sdk import create_roxy
roxy = create_roxy(os.environ['ROXY_API_KEY'])
horoscope = roxy.astrology.get_daily_horoscope(sign='aries')
print(horoscope['overview'])
print(horoscope['luckyNumber'])
claude mcp add-json --scope user roxy-astrology '{"type":"http","url":"https://roxyapi.com/mcp/astrology","headers":{"X-API-Key":"YOUR_KEY"}}'
Then ask Claude, "what is the daily horoscope for Aries?" The agent calls the right tool and summarizes the result. Full setup for Cursor, Claude Desktop, Antigravity, and other clients: MCP guide.
Response fields to use: sign, date, overview, love, career, health, finance, advice, luckyNumber, luckyColor, compatibleSigns[], moonPhase, energyRating (1-10).
Step 2, create the HTML file
Create horoscope.html and paste this whole block. It ships 12 buttons and renders the selected sign.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Daily Horoscope</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background: #fafafa; }
h1 { text-align: center; margin-bottom: 8px; }
.subtitle { text-align: center; color: #666; margin-bottom: 24px; }
.signs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 24px; }
.signs button { padding: 12px 4px; border: 2px solid #e0e0e0; border-radius: 12px; background: white; cursor: pointer; font-size: 14px; }
.signs button:hover { border-color: #7c3aed; background: #f5f0ff; }
.signs button.active { border-color: #7c3aed; background: #7c3aed; color: white; }
.signs .emoji { font-size: 24px; display: block; margin-bottom: 4px; }
.result { background: white; border-radius: 16px; padding: 24px; display: none; }
.result h2 { margin-bottom: 4px; }
.result .date { color: #666; font-size: 14px; margin-bottom: 16px; }
.overview { font-size: 16px; line-height: 1.6; margin-bottom: 20px; }
.cats { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.cat { background: #f9fafb; padding: 12px; border-radius: 8px; }
.cat .label { font-size: 12px; font-weight: 600; text-transform: uppercase; color: #666; }
.cat .text { font-size: 14px; line-height: 1.5; }
.lucky { text-align: center; padding: 12px; background: #f5f0ff; border-radius: 8px; font-size: 14px; }
.loading { text-align: center; padding: 40px; color: #666; }
</style>
</head>
<body>
<h1>Daily Horoscope</h1>
<p class="subtitle">Pick your sign to see the forecast for today</p>
<div class="signs" id="signs"></div>
<div id="result" class="result"></div>
<script>
const API_KEY = 'YOUR_API_KEY';
const SIGNS = [
['aries', 'Aries', '♈'], ['taurus', 'Taurus', '♉'],
['gemini', 'Gemini', '♊'], ['cancer', 'Cancer', '♋'],
['leo', 'Leo', '♌'], ['virgo', 'Virgo', '♍'],
['libra', 'Libra', '♎'], ['scorpio', 'Scorpio', '♏'],
['sagittarius', 'Sagittarius', '♐'], ['capricorn', 'Capricorn', '♑'],
['aquarius', 'Aquarius', '♒'], ['pisces', 'Pisces', '♓'],
];
const grid = document.getElementById('signs');
for (const [slug, label, glyph] of SIGNS) {
const b = document.createElement('button');
b.innerHTML = '<span class="emoji">' + glyph + '</span>' + label;
b.onclick = () => load(b, slug);
grid.appendChild(b);
}
async function load(btn, sign) {
document.querySelectorAll('.signs button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const el = document.getElementById('result');
el.style.display = 'block';
el.innerHTML = '<div class="loading">Reading the stars...</div>';
const res = await fetch('https://roxyapi.com/api/v2/astrology/horoscope/' + sign + '/daily', {
headers: { 'X-API-Key': API_KEY }
});
const data = await res.json();
el.innerHTML =
'<h2>' + data.sign + ' horoscope</h2>' +
'<div class="date">' + data.date + '</div>' +
'<div class="overview">' + data.overview + '</div>' +
'<div class="cats">' +
'<div class="cat"><div class="label">Love</div><div class="text">' + data.love + '</div></div>' +
'<div class="cat"><div class="label">Career</div><div class="text">' + data.career + '</div></div>' +
'<div class="cat"><div class="label">Health</div><div class="text">' + data.health + '</div></div>' +
'<div class="cat"><div class="label">Finance</div><div class="text">' + data.finance + '</div></div>' +
'</div>' +
'<div class="lucky">Lucky number <strong>' + data.luckyNumber + '</strong> ' +
'· Lucky color <strong>' + data.luckyColor + '</strong> ' +
'· Compatible <strong>' + data.compatibleSigns.join(', ') + '</strong></div>';
}
</script>
</body>
</html>
Replace YOUR_API_KEY. Save. Double-click to open.
The key sits in browser code here because this is a zero-infrastructure demo. Do not ship it this way to users. For anything public, proxy the call through a backend route (the Next.js guide shows the pattern). Anyone can view page source.
Step 3, deploy
Two options, both free.
Cloudflare Pages. Drag the file into a new project at pages.cloudflare.com. Global CDN, HTTPS, deploys in under a minute.
Vercel. Put the file in an empty folder, run npx vercel. Same result.
For a real app, move the API key to an environment variable and proxy through a serverless function. One file becomes two files, the client calls your function, the function calls Roxy.
Gotchas
- Sign slugs are lowercase.
ariesnotAries. The path is case-insensitive server-side but lowercase is the convention. - Weekly and monthly have extra fields. Switch the URL to
/weeklyor/monthlyanddata.week,data.luckyDays[],data.weekByWeek[],data.keyDates[]become available. - Do not ship the key in the browser for production. Proxy through a backend. The demo HTML above is for local prototyping only.
compatibleSignsis capitalized, but the path param is lowercase. Easy to trip over when templating.
What to build next
- Upgrade to weekly and monthly variants. Same shape plus extra fields. See the astrology guide.
- Auto-detect the sign from a user birthday to skip the button grid.
- Extend the UI with transit data.
POST /astrology/transitswith a saved natal chart returns personalized aspects for the day. - The dating app tutorial shows two-person compatibility on top of the same astrology surface.