Skip to content

weed33834/FreeAPI

Repository files navigation

FreeAPI — AI API Site Directory

English | 中文 | 日本語

License: MIT React 18 TypeScript Vite 6 Tailwind CSS Zustand 5 Cloudflare Workers last commit stars

Live Demo

freeapi.pages.dev — deployed on Cloudflare Pages with Supabase authentication (GitHub OAuth + Email OTP).

A static, front-end directory of 240+ AI API sites — LinuxDo community free stations, free chat mirrors, free/paid API relays, overseas official free tiers, domestic LLM platforms, plus an open-source framework index and a blacklist of dead endpoints. Live availability probing and zh / en / ja UI, with zero backend by default.

FreeAPI collects the fragmented landscape of "free / cheap" LLM access points into a single filterable surface. Each entry is tagged by category, type (free / freemium / paid), status, supported models, and a short feature list (free, daily check-in, free quota, domestic, low-latency, Linux.do gated, etc.). Availability is probed from the browser with a cached image beacon, and an optional Cloudflare Worker upgrades probing to real /v1/models endpoint checks that bypass CORS.

The project is opinionated about not pretending: domain reachability is not API availability, and that distinction is surfaced in the UI rather than hidden.

Highlights

  • 240+ curated entries across 8 categories — counts as of the last data refresh:

    Category Slug Count Coverage
    Paid relay paidrelay 87 Commercial resellers of GPT / Claude at lower unit price
    Free chat freechat 81 Mirror / aggregator chat sites, no key required
    Blacklist blacklist 21 Confirmed dead (domain resold, SSL expired, service shut down)
    Community free linuxdo 15 LinuxDo community-run free / welfare API stations
    Overseas free tier overseas 11 OpenRouter / Groq / Gemini official free tiers
    Frameworks & nav tool 10 Open-source relay frameworks, benchmarks, index sites
    Domestic official domestic 9 PRC LLM vendor official API platforms
    Free relay freerelay 8 API forwarders offering a free quota
    Total 242
  • Live availability probing — front-end img beacon against /favicon.ico with a 1-hour localStorage cache; optional Cloudflare Worker hits /v1/models and treats 401/403 as "API online but key required".

  • Trilingual UIzh / en / ja, preference persisted to localStorage (FreeAPI-lang); site data (name / desc / tagline) stays in its source language, only framework strings are translated.

  • Mobile-first — responsive grid (2 cols on phone → 8 cols on wide screens), compact spacing, stacked toolbar.

  • Cyberpunk terminal aesthetic — fixed dark palette, monospaced data, scan-line animation.

  • No backend dependency by default — all site data is compiled into the bundle; deployable to any static host.

UI & theme

Token Hex Use
cyber.bg #0a0e14 Page background
cyber.cyan #00e5ff Primary accents, "online"
cyber.magenta #ff2e88 Free-chat category
cyber.amber #ffb020 Paid relay, "unstable"
cyber.green #34d399 "OK" status
cyber.violet #7c5cff Free relay
cyber.blue #60a5fa Domestic official
cyber.dead #ef4444 Blacklist / "dead"

Typography: Chakra Petch (display) + JetBrains Mono (monospaced data) + Noto Sans SC (body). The muted token was raised to #8b95a8 to clear WCAG AA contrast (≥ 4.6:1) against the background.

Tech stack

Layer Choice
Framework React 18 + TypeScript
Build Vite 6
Styling Tailwind CSS 3 (dark-mode class)
State Zustand 5 (persist-free; filter state is in-memory)
Auth Supabase (GitHub OAuth + Email OTP via Resend)
Routing react-router-dom 7 via hash routing (#/blacklist)
Icons lucide-react
Probing Front-end img beacon + optional Cloudflare Worker

Architecture

flowchart LR
  subgraph Bundle["Static bundle (dist/)"]
    A[React UI] --> S[sites.ts<br/>242 entries]
    A --> F[useFilterStore<br/>Zustand]
    A --> H[useSiteHealth]
  end
  H -->|img beacon /favicon.ico| B[(Browser localStorage<br/>1h TTL cache)]
  H -.->|optional, when HEALTH_API set| W[(Cloudflare Worker<br/>/v1/models probe)]
  W --> C[(Cache API<br/>5 min)]
  A --> R{hash route}
  R -->|#/blacklist| BL[Blacklist page]
  R -->|default| HM[Home page]
Loading

Quick start

# install (pnpm recommended; npm works too)
pnpm install

# dev server at http://localhost:5173
pnpm dev

# type-check + production build → dist/
pnpm check && pnpm build

# lint
pnpm lint

Requires Node 18+ and a recent pnpm.

Environment variables (create a .env file — never commit it):

VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key

Without these, login is disabled and the site works as a read-only directory.

Project structure

freeapi/
├── src/
│   ├── components/
│   │   ├── Hero.tsx            # header, category stat cards, live badge
│   │   ├── Toolbar.tsx         # search / model / sort / type / status filters
│   │   ├── SiteGrid.tsx        # grouped + flat grid rendering
│   │   ├── SiteCard.tsx        # single entry card + feature tags
│   │   ├── DetailDrawer.tsx    # per-site detail drawer
│   │   ├── AuthModal.tsx       # GitHub OAuth + Email OTP login modal
│   │   ├── UserMenu.tsx        # user dropdown with profile link & logout
│   │   ├── LangSwitcher.tsx    # zh / en / ja switcher
│   │   └── Empty.tsx
│   ├── data/sites.ts           # canonical site list + category/type/status meta
│   │                           #   + deriveFeatures() auto-tagging
│   ├── i18n/
│   │   ├── translations.ts     # zh / en / ja dictionary + format()
│   │   └── useI18n.ts          # zustand store + useT() + translateFeature()
│   ├── store/
│   │   ├── useFilterStore.ts   # filter state + derived visible sites + live status
│   │   ├── useAuthStore.ts     # Supabase session + user + OTP timer
│   │   └── useFavoritesStore.ts# favorites (site IDs) persisted to localStorage
│   ├── hooks/
│   │   ├── useSiteHealth.ts    # beacon probing + batched recheck
│   │   └── useTheme.ts
│   ├── pages/
│   │   ├── Home.tsx
│   │   ├── Blacklist.tsx       # #/blacklist
│   │   └── Profile.tsx         # #/me — saved favorites, user info
│   ├── App.tsx                 # hash router
│   └── main.tsx
├── api/                        # optional Cloudflare Worker probe backend
│   ├── health.worker.js
│   ├── sites.json              # generated by scripts/export-sites.mjs
│   └── wrangler.toml
├── scripts/                    # site export / verification scripts
└── public/

Data model

All entries live in src/data/sites.ts:

interface Site {
  id: string;
  name: string;
  url: string;
  category: 'linuxdo' | 'freechat' | 'freerelay' | 'paidrelay'
          | 'overseas' | 'domestic' | 'tool' | 'blacklist';
  type: 'free' | 'freemium' | 'paid';
  status: 'ok' | 'unstable' | 'unknown' | 'dead';
  models: string[];
  desc: string;
  tagline?: string;          // one-line positioning under the name
  features?: string[];        // explicit tags; auto-derived if absent
  apiBase?: string;
  billing?: string;
  register?: string;
  payment?: string;
  note?: string;
  blacklistReason?: string;   // only for category === 'blacklist'
}

When features is omitted, deriveFeatures() infers tags from type / billing / note / register / desc (e.g. type === 'free'免费, mention of "签到" → 签到). Tag → colour mapping lives in FEATURE_COLOR inside SiteCard.tsx and DetailDrawer.tsx.

Internationalisation

  • Three locales: zh / en / ja, dictionary in src/i18n/translations.ts.
  • useT() for component strings; translate() for non-hook contexts.
  • Site data (name / desc / tagline) is kept in its source language — only framework UI is translated.
  • Feature tags translate via translateFeature() keyed as feat.<source-label>.
  • Language choice persists to localStorage under FreeAPI-lang; missing keys fall back to Chinese.

Live health check

The front-end probe is deliberately honest about its limits: an img beacon against /favicon.ico can only confirm that the domain responds, not that the API serves. Relay home pages almost always return 200, so "domain up" ≠ "API usable". The UI labels this distinction rather than masking it.

sequenceDiagram
  participant U as User opens app
  participant F as useSiteHealth
  participant LS as localStorage cache
  participant Net as Network (img beacon)
  U->>F: mount
  F->>LS: read FreeAPI:live-status
  alt cache fresh (< 1h)
    F-->>U: render cached status instantly
  else stale
    F->>Net: batched probe (6 sites / 400ms gap)
    Net-->>F: onload/onerror → up | timeout → unknown
    F->>LS: write updated entries
    F-->>U: progressive UI update + progress bar
  end
Loading

For accurate probing, deploy the optional Cloudflare Worker — it calls /v1/models without a key and interprets 401/403 as "API online" (key required), 5xx/timeout as "down". The front-end auto-switches to Worker mode when HEALTH_API is set in src/hooks/useSiteHealth.ts, and falls back to the beacon if the Worker is unreachable.

# 1. export the site manifest from sites.ts
node scripts/export-sites.mjs        # → api/sites.json

# 2. deploy the worker
cd api && npx wrangler deploy

# 3. fill the workers.dev URL into src/hooks/useSiteHealth.ts → HEALTH_API

See api/README.md for the full deploy guide, cost estimate, and troubleshooting matrix.

Worker API reference

Endpoint Method Returns
/ GET {"ok":true,"sites":N,"version":"1.0.0"}
/api/sites GET {total, sites:[{id,url,apiBase,category}]}
/api/health?id=X GET {id,status,latency,checkedAt,detail}
/api/health?batch=all GET {total,results:[...],checkedAt}
/api/health?batch=linuxdo GET same shape, scoped to a category

Status semantics: up = 2xx/3xx/4xx (4xx means the API is online but a key is required); down = 5xx or network error; unknown = probe fault. Cache TTL is 300 s (Cache API); per-IP rate limit is 60 req/min (429 on excess).

User system

FreeAPI supports optional login via Supabase:

  • GitHub OAuth — one-click sign-in with your GitHub account
  • Email OTP — enter your email, receive a 6-digit code, no password needed (powered by Resend)

Once logged in, you can favorite sites (star icon on each card) and view them later on the Profile page (#/me). Favorites are persisted to localStorage per account.

Auth state is managed in useAuthStore (Zustand) and session is synced with Supabase in real-time. The UI adapts: unauthenticated users see a "Login" button; logged-in users see their avatar with a dropdown to navigate to Profile or sign out.

Deployment

The front-end is deployed to Cloudflare Pages. Cloudflare Pages connects directly to the GitHub repository and auto-builds on every push to main:

  1. Cloudflare detects the push and runs pnpm install + pnpm build
  2. VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set as environment variables in the Cloudflare Pages dashboard
  3. The built dist/ is deployed to https://freeapi.pages.dev/

GitHub Actions (.github/workflows/deploy.yml) runs CI checks (lint + build) on every push and pull request to ensure the build passes before Cloudflare deploys.

The site is served from https://freeapi.pages.dev/. public/_redirects provides SPA fallback (/* → /index.html 200) and public/_headers adds security headers + asset caching.

For self-hosting: pnpm build produces dist/, uploadable to any static host (Vercel, Netlify, GitHub Pages).

Contributing

Site additions, status corrections, and translation fixes are all welcome. Add entries to src/data/sites.ts following the schema above; fill tagline and features where possible since deriveFeatures() only covers the common cases. When adding a new feature tag, also extend feat.<label> in all three languages and update FEATURE_COLOR in both SiteCard.tsx and DetailDrawer.tsx. See CONTRIBUTING.md for the full workflow and submission norms.

The project does not list sites that violate applicable law or ship malware / phishing / crypto-mining payloads. Dead sites are moved to blacklist with a recorded reason rather than silently deleted.

License

MIT © 2026 weed

About

AI API Site Directory - 240+ entries, live probing, zh/en/ja, Supabase Auth

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages