🕓 Запис від 2026-04-14, оновлено 2026-05-09. TS / Python / PHP SDK тепер живуть на public registries —
@astroway/sdk(npm),astroway(PyPI),astroway/sdk(Packagist). Деталі в changelog.
Хочеш зробити астрологічний застосунок. З чого почати? У цьому гайді — рішення та код: від вибору API до деплою робочого продукту.
Питання архітектури
Section titled “Питання архітектури”Перш ніж писати код, визнач: обчислення на клієнті чи на сервері?
Клієнт (наприклад, Swiss Ephemeris WASM у браузері):
- Плюси: без вартості за запит, працює офлайн, повний контроль
- Мінуси: ~2 МБ WASM на кожного користувача, складне ліцензування (комерційне використання Swiss Ephemeris має обмеження), ти сам супроводжуєш обчислювальний код
Серверний API (AstroWay, Prokerala тощо):
- Плюси: без клієнтських залежностей, малий bundle застосунку, швидко на мобілі, без ліцензійного болю
- Мінуси: вартість у кредитах за запит, затримка на «холодних» запитах
Для більшості застосунків виграє серверний API. Мобільні користувачі не чекатимуть 2 МБ WASM; з ліцензійними нюансами не варто мати справу; а сучасні API безкоштовно кешують ідентичні запити (AstroWay робить 5-хвилинний кеш із заголовком X-Cache: HIT).
Вибір API
Section titled “Вибір API”Що важить:
- Точність — шукай Swiss Ephemeris «під капотом» (±1 кутова секунда). Якщо API прямо цього не каже — запитай.
- Покриття — натал + синастрія + транзити — мінімум. Прогресії й повернення — наступний рівень. Рідкісні техніки (ректифікація, Human Design) — це диференціатор.
- Якість SDK — типізовані TypeScript і Python SDK економлять години.
- Модель тарифу — credit-based масштабується краще, ніж per-request, на змішаному навантаженні.
Для цього туторіалу візьмемо AstroWay API, бо він має все чотири (705 ендпоінт, Swiss Ephemeris, типізовані SDK, credit-based).
Крок 1: Підняти backend
Section titled “Крок 1: Підняти backend”Ніколи не клич астрологічний API напряму з браузера — твій API-ключ витече. Завжди ходь через свій backend.
mkdir my-astrology-appcd my-astrology-appnpm init -ynpm install express @astroway/sdk zodnpm install -D typescript @types/express @types/node tsxСтвори src/server.ts:
import express from 'express';import { Astroway } from '@astroway/sdk';import { z } from 'zod';
const app = express();app.use(express.json());
const client = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY!,});
const BirthInput = z.object({ date: z.string(), time: z.string(), timezoneOffset: z.number(), latitude: z.number(), longitude: z.number(),});
app.post('/api/chart', async (req, res) => { const parsed = BirthInput.safeParse(req.body); if (!parsed.success) return res.status(400).json({ error: parsed.error });
try { const chart = await client.chart({ ...parsed.data, houseSystem: 'P', }); res.json(chart); } catch (err) { res.status(500).json({ error: String(err) }); }});
app.listen(3000, () => console.log('http://localhost:3000'));Запусти:
ASTROWAY_API_KEY=aw_test_... npx tsx src/server.tsПеревірка через curl:
curl -X POST http://localhost:3000/api/chart \ -H "Content-Type: application/json" \ -d '{"date":"1990-07-14","time":"14:30:00","timezoneOffset":3,"latitude":50.4501,"longitude":30.5234}'Отримуєш повну JSON-натальну карту.
Крок 2: Frontend
Section titled “Крок 2: Frontend”Підійде будь-який фреймворк. Для прикладу — React із простою формою:
import { useState } from 'react';
type Chart = { planets: { name: string; longitude: number; sign: string; house: number }[]; aspects: { planet1: string; planet2: string; type: string; orb: number }[];};
export function NatalForm() { const [chart, setChart] = useState<Chart | null>(null);
async function handleSubmit(formData: FormData) { const body = Object.fromEntries(formData.entries()); const res = await fetch('/api/chart', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ date: body.date, time: body.time + ':00', timezoneOffset: Number(body.tz), latitude: Number(body.lat), longitude: Number(body.lng), }), }); setChart(await res.json()); }
return ( <div> <form action={handleSubmit}> <input name="date" type="date" required /> <input name="time" type="time" required /> <input name="tz" type="number" placeholder="Timezone offset (наприклад 3)" required /> <input name="lat" type="number" step="0.0001" placeholder="Latitude" required /> <input name="lng" type="number" step="0.0001" placeholder="Longitude" required /> <button>Build chart</button> </form>
{chart && ( <div> <h2>Planets</h2> <ul> {chart.planets.map(p => ( <li key={p.name}>{p.name}: {p.sign} (house {p.house})</li> ))} </ul> <h2>Aspects</h2> <ul> {chart.aspects.map((a, i) => ( <li key={i}>{a.planet1} {a.type} {a.planet2} (orb {a.orb.toFixed(2)}°)</li> ))} </ul> </div> )} </div> );}Крок 3: Синастрія
Section titled “Крок 3: Синастрія”Сумісність — наступна очевидна фіча. Додай у src/server.ts:
const SynastryInput = z.object({ chart1: BirthInput, chart2: BirthInput,});
app.post('/api/synastry', async (req, res) => { const parsed = SynastryInput.safeParse(req.body); if (!parsed.success) return res.status(400).json({ error: parsed.error });
const result = await client.synastry(parsed.data); res.json({ score: result.compatibility.score, label: result.compatibility.label, aspects: result.crossAspects, });});Все. Один ендпоінт, 50 кредитів за виклик, повертає score 0–100 і cross-aspects.
Крок 4: Щоденні гороскопи
Section titled “Крок 4: Щоденні гороскопи”Для контент-engagement’у щоденні гороскопи — must have. AstroWay генерує їх із реальних даних транзитів:
app.post('/api/horoscope/daily', async (req, res) => { const parsed = BirthInput.safeParse(req.body); if (!parsed.success) return res.status(400).json({ error: parsed.error });
const horoscope = await client.horoscopeDaily(parsed.data); res.json({ text: horoscope.text, disclaimer: horoscope.disclaimer, // обов'язково зберегти в UI! });});Важливо: AI-згенерований контент містить disclaimer, який ти зобов’язаний показати користувачам (за Terms of Service). Не прибирай його.
Крок 5: Кешування
Section titled “Крок 5: Кешування”Щоденні гороскопи однакові для всіх користувачів із одного дня народження та схожими натальними картами. Кешуй агресивно:
import { LRUCache } from 'lru-cache';
const cache = new LRUCache<string, any>({ max: 1000, ttl: 86400 * 1000 });
app.post('/api/horoscope/daily', async (req, res) => { const key = JSON.stringify(req.body); const cached = cache.get(key); if (cached) return res.json(cached);
const horoscope = await client.horoscopeDaily(req.body); cache.set(key, horoscope); res.json(horoscope);});У AstroWay також є вбудоване 5-хвилинне серверне кешування (X-Cache: HIT), але для довгоживучого контенту потрібен власний кеш.
Крок 6: Деплой
Section titled “Крок 6: Деплой”Підійде будь-яка платформа. Для швидкого старту — Vercel або Railway:
# vercel.json{ "functions": { "src/server.ts": { "runtime": "@vercel/node" } } }У панелі платформи виставляй env ASTROWAY_API_KEY.
Планування бюджету
Section titled “Планування бюджету”Якщо дійшов сюди — оціни місячне споживання кредитів перед запуском:
credits/month = DAU × (avg_charts_per_user × 20 + avg_synastries × 50 + avg_horoscopes × 20) × 30Для 100 DAU з 1 картою + 1 гороскопом + 0.3 синастріями на користувача на день:
100 × (20 + 20 + 0.3 × 50) × 30 = 165 000 кредитів / місяцьЦе план Starter за $19/міс (200K кредитів).
Що далі
Section titled “Що далі”Прокачані фічі, які варто додати зі зростанням:
- Overlay транзитів —
/v1/transitsпоказує поточні позиції планет на натальній карті - Прогресії —
/v1/progressionsдля дуг психологічного розвитку - Solar return —
/v1/solar-returnна «прогноз на рік з дня народження» - Human Design — Human Design API відкриває цілий новий функціональний домен
- Астрокартографія —
/v1/acgмапить, де користувачеві варто жити
Кожна фіча важка в реалізації з нуля, але — один виклик API з AstroWay.
- Отримай безкоштовний API-ключ — 10 000 кредитів / місяць
- Повний API reference — усі 705 ендпоінт
- Birth Chart API — детальна документація ендпоінта карти
Той самий Swiss Ephemeris, що й у Solar Fire — у 4 рядках коду.
Безкоштовний ключ без картки. 5 000 викликів на місяць до першої оплати.