Integrations
Everything Baselyra talks to, and nothing it does not.
Every integration on this page is implemented in the
repository and configured by environment variables. A provider whose credentials are not set is
not merely hidden — it is not offered, so a client that renders
“continue with” buttons from GET /auth/v1/providers only ever draws
buttons that work.
Sign-in providers
Seven, each with its own quirks handled
The differences between OAuth providers are not cosmetic, and a client that pretends one shape fits all is broken for about half of them. Each provider is a descriptor — where its authorize and token endpoints are, whether it accepts PKCE, what its userinfo call needs, and how to read a profile out of the answer — never a branch buried in shared code.
OIDC. PKCE, and the address is used only when Google says it is verified.
The public email on /user is usually null, so the address comes from a second call to /user/emails.
OIDC userinfo. Does not accept PKCE, so no challenge is sent.
Returns nothing unless a fields list is named on the request.
Graph host reads the token from the query string, not a header.
Spells the credential client_key and nests the user under data.user.
No OIDC endpoint: identity from /whoami, profile from account.json, address from email.json.
# A provider appears the moment both halves are set.
BASELYRA_OAUTH_GOOGLE_CLIENT_ID=…
BASELYRA_OAUTH_GOOGLE_CLIENT_SECRET=…
BASELYRA_OAUTH_GITHUB_CLIENT_ID=…
BASELYRA_OAUTH_GITHUB_CLIENT_SECRET=…
# Where a completed sign-in may be sent back to. An origin that is
# not on this list is refused outright rather than redirected to,
# which is the difference between an allow-list and an open redirect.
BASELYRA_OAUTH_REDIRECT_ALLOWLIST=https://app.example.com,https://staging.example.com
// Which providers this instance actually has credentials for
const res = await fetch(`${BASE}/auth/v1/providers`);
const { providers } = await res.json();
// [{ id: 'google', name: 'Google', url: '…/authorize?provider=google' }]
// Send the browser there. The callback comes back to your site with
// the tokens in the URL fragment, so they never reach a server log
// or a Referer header the way a query string would.
location.href = provider.url + '&redirect_to=' + encodeURIComponent(SITE);
DELETE … RETURNING, so a replayed callback finds nothing however fast it comes
back. That is a property of the statement, not of a check a second request could race past.
SMS
Six ways to deliver a one-time code
Phone sign-in sends a six-digit code and verifies it against a hash bound to that number. The
sending is one fetch per provider, with no SDK: credentials arrive keyed by the
environment variable name you set, so a missing one names itself in the error rather than being
translated through a mapping table nobody reads.
Form-encoded Messages resource. SMS_FROM may be a number or a messaging service SID; the right field is chosen for you.
JSON, key and secret in the body.
JSON, AccessKey authorization.
SigV4 signed by hand, because calling SNS without the AWS SDK has no other correct form.
JSON over basic auth with the auth id and token.
A signed POST to a URL you own, for a provider Baselyra does not carry or an internal gateway.
SMS_PROVIDER=twilio
SMS_FROM=+15550100
TWILIO_ACCOUNT_SID=…
TWILIO_AUTH_TOKEN=…
# Spend is bounded before a message is paid for, not after.
SMS_OTP_COOLDOWN=60
SMS_MAX_PER_NUMBER_PER_HOUR=5
SMS_DEFAULT_COUNTRY=44
POST /auth/v1/otp {"phone": "+15550100"}
// → 200 always. "If that number can receive messages, a code is on its way."
POST /auth/v1/verify {"phone": "+15550100", "token": "482913"}
// → { access_token, refresh_token, user }
Email and models
One SMTP host, one optional model
SMTP, via nodemailer
Any host: Postmark, SES, Fastmail, Mailgun, a relay on the same box. Confirmation, magic link, one-time code, recovery, email change and invitation templates are editable in the Studio with a live preview and a test send that reports the server’s own error rather than a generic failure.
Leave SMTP_HOST empty and mail is printed to the
log instead of sent — correct on a laptop, never in production.
DeepSeek
The only model provider wired in, over an OpenAI-compatible chat-completions call. It powers
natural language to SQL, query explanation, ask-your-database and a chat relay your own users
can call. Unset the key and every AI route answers 503 ai_disabled; the Studio
hides its panels rather than showing a control that would fail.
Clients
One published client, and four documented ones
Being honest about this matters more than the count. @baselyra/client is a real
package with types, a session that renews itself and one multiplexed socket. The others are
single files in the documentation and the examples directory — complete, tested by hand
against a running instance, and yours to paste into a project.
JavaScript / TypeScript
published Zero dependencies. Runs unchanged in
browsers, Node 22, Deno, Bun and React Native. Supply a generated
Database type and rows come back typed; leave it off and they are open records.
No call ever rejects for an HTTP status — failures arrive as error next to
a null data, including a dead network, where status is 0.
Dart / Flutter
single file Auth, the query builder, storage and realtime, needing
only http and web_socket_channel. Failures throw, because Dart’s
error channel is exceptions and a widget should not carry a branch it never wanted. The socket
heartbeats, because a suspended phone comes back with a connection that claims to be open and
carries nothing.
PHP
single file PHP 8.1+, ext-curl and
ext-json. The client is immutable: withToken() returns a new one, so
a request handler cannot leave a shared instance authenticated as the previous visitor.
Python
documented A worked guide using httpx, including the
server-side pattern: forward the user’s token and let policies decide, rather than
reaching for the service key because it is easier.
Plain HTTP
always There is no protocol here that a language needs a library
for: JSON over HTTP, one WebSocket, standard status codes and a single error shape. Go, Rust,
Ruby, Elixir, Swift, Kotlin — all of it is curl with a different syntax.
Framework guides
Complete, not sketches: Next.js App Router with server components and route handlers, React with Vite, Angular, React Native and Expo, Flutter and PHP. Each covers which key goes where, because that is the mistake that costs people their data.
App Router, server components, route handlers, middleware.
Vite, and React Native / Expo with a storage adapter.
A typed service, signals, and an HTTP interceptor.
The Dart client, plus a runnable example app.
Not integrated
What Baselyra does not talk to
Apple, Discord, Twitter, GitLab, Bitbucket, Slack…
Seven providers is seven, not thirty. If sign-in with Apple is a requirement, Supabase and Appwrite both carry far more providers than this and that is a real reason to pick one.
OpenAI, Anthropic, Gemini, Ollama
DeepSeek is the only model provider wired in. The relay is one fetch against an
OpenAI-compatible endpoint, so pointing it elsewhere is a small change — but nothing
ships pointing elsewhere today.
S3, Cloudflare R2, imgproxy, a CDN
Storage is the local disk of the host running the app, and files come back exactly as they were uploaded. Put a CDN in front of the public object routes yourself if you need one.