← Craftable
Describe it. Your app can do it.
Every app Craftable builds can use the phone's camera, microphone, speakers, Bluetooth and location, talk to any AI with your own key, take UPI and Razorpay payments, sign people in, run chat rooms and save data. You don't press anything: write "a voice notes app", "a tuition app with UPI fees", "a chatbot with my OpenAI key" and the builder wires it in.
What works, honestly
📷 Camera — photos and videoWorks on Android, iPhone and desktop browsers, in published apps, the installable app and the Android APK. Craftable asks permission once per app.
🎙️ Microphone — voice notes, speech to textVoice notes work everywhere a camera does. Speech-to-text uses the browser's built-in recogniser: Chrome/Edge and Safari yes, Firefox no.
🔊 Speakers — text to speech, soundsWorks everywhere. Voices depend on the phone (Hindi and other Indian voices are on most Android phones).
🟦 Bluetooth (Bluetooth Low Energy)Works in Chrome/Edge on Android, Windows, Mac and ChromeOS — fitness bands, heart-rate monitors, ESP32/Arduino boards. Not on iPhone/iPad, not in the Android APK, not classic Bluetooth speakers/headphones. Apps say so instead of breaking.
📍 Location · 📳 vibration · 🔔 notifications · 📋 clipboard · ↗️ shareWorks. Vibration is Android only (iPhones don't allow it). Notifications show while the app is open; push notifications when the app is closed are not included.
🤖 AI with your own keyWorks with any OpenAI-compatible API — OpenAI, Google Gemini, Groq, OpenRouter, DeepSeek, Together, Mistral, a local server reachable over https. List models, streaming chat, or call any endpoint. The key stays on the person's device and passes through Craftable's relay, which never stores or logs it and only talks to https addresses.
💸 UPIWorks: a "Pay with UPI app" button on phones and a QR code on computers, for any UPI ID. UPI links can't tell the app whether money arrived — apps show "check your UPI app", never "payment verified".
💳 RazorpayWorks with the owner's public Key ID (never the secret). Payments are marked verified only when the owner has connected Razorpay in Craftable's Integrations, which checks the signature on the server; otherwise the app shows it as unconfirmed.
🔐 Login — email, Google, GitHubEmail + password works instantly (accounts are per app; passwords are hashed). Google needs the owner's OAuth Client ID; GitHub needs the owner's GitHub OAuth app Client ID with Device Flow switched on. No secrets are ever put in an app.
💬 Chat roomsWorks: rooms, names, photos, an iMessage- or WhatsApp-style look; new messages arrive within a few seconds. Share buttons open WhatsApp, SMS or email on the person's phone. Sending real SMS or WhatsApp messages from the app itself needs a paid provider (like Twilio or WhatsApp Business) and isn't included.
🗂️ DataWorks: a key-value store per app (shared, or private per signed-in user), plus Craftable's existing database and forms.
Owner values the builder will ask you for
- UPI ID (like
yourname@okaxis) for UPI payments.
- Razorpay Key ID (
rzp_live_… or rzp_test_…) — the public one, never the Key Secret.
- Google OAuth Client ID — Google Cloud Console → Credentials → OAuth client (Web). Add
https://craftable.sites.tab.bot under Authorised JavaScript origins.
- GitHub Client ID — GitHub → Settings → Developer settings → OAuth Apps → New. Tick Enable Device Flow. Only the Client ID goes in the app.
Until you give them, the app shows a friendly "not set up yet" message instead of a broken button.
For developers
Apps hosted on Craftable get everything automatically. An exported app can add one line:
<script src="https://craftable.sites.tab.bot/sdk/craftable.js" data-app="YOUR_PROJECT_ID"></script>
const photo = await Craftable.camera.photo(); // { dataUrl, blob, width, height }
const note = await Craftable.mic.record(); // { blob, url, duration }
await Craftable.speak('Namaste!', { lang: 'hi-IN' });
const dev = await Craftable.bluetooth.connect({ filters: [{ services: ['heart_rate'] }] });
const here = await Craftable.location.get(); // { lat, lng, accuracy }
await Craftable.ai.settings(); // person enters base URL + key
const reply = await Craftable.ai.chat({ messages, onToken: t => … });
await Craftable.upi.pay({ upiId: 'you@okaxis', name: 'Shop', amount: 199 }); // never "verified"
Craftable.auth.ui('#login', { google: { clientId }, github: { clientId } });
Craftable.chat.ui('#chat', { room: 'family', theme: 'whatsapp' });
await Craftable.kv.set('scores/ravi', { score: 10 });
Published apps run in a locked sandbox; the Craftable page around them asks permission per app and does the camera, mic, location and Bluetooth work, so one app can never read another's data. Every call returns a promise and fails with a clear, friendly message (no camera, permission denied, not supported on iPhone…).