Best practices and advanced configuration
The patterns that keep an app solid: mobile, state, failure tolerance and cost.
Five patterns
- 1Mobile first, desktop second
Base the layout on a single column, keep tap targets ≥44px and put the primary action within thumb reach. Open the layout up on wide screens — never ship a phone tab bar to desktop.
- 2Wrap every call
Network errors, quotas, disabled features are all normal. Catch them and show one sentence in the user's language; a raw error code must never reach the screen.
- 3Keep the server the source of truth
Re-read the list after a write; if you update optimistically, roll back on failure. Two devices editing the same record is a real scenario.
- 4Never show an empty screen
Loading, empty and error states all need a design. An empty state carries an action telling the person what to do next.
- 5Keep collections small
A document caps at 20K characters; paginate large lists or split them by date. Images always live in file storage with only the URL in the record.
Fragile vs solid
- await devany.ai.ask(...) with no wrapper
- An image base64'd into the record
- A raw error code shown on screen
- A layout only ever tried on desktop
- try/catch and hide the feature when off
- devany.files.upload → a URL in the record
- Code → one sentence in the user's language
- Tested on a phone first, then wide
The resilient call pattern
async function safe(fn, onFail) {
try { return await fn(); }
catch (e) {
const m = {
ai_disabled: 'Bu özellik şu anda kapalı.',
mail_disabled: 'E-posta gönderimi kapalı.',
quota_exceeded: 'Depolama alanı dolu.',
file_too_large: 'Dosya çok büyük, daha küçük bir görsel seç.',
not_signed_in: 'Devam etmek için giriş yap.',
rate_limited: 'Çok hızlı gittik — bir dakika sonra dene.',
}[e.message] || 'Bir şeyler ters gitti, tekrar dener misin?';
onFail(m);
return null;
}
}
const summary = await safe(() => devany.ai.ask(prompt), toast);
if (summary) render(summary);Advanced configuration: which switch, where
| Where you turn it on | |
|---|---|
| In-app AI | Builder → app settings |
| Transactional email | Builder → email (from name, reply-to) |
| Webhook target | Builder → automation (Catch Hook URL) |
| Visibility / private publish | The publish screen |
| Your own domain | Publish → domain (DNS verification) |
| Spend cap (autonomous run) | When you start the run |
| Campaign sending | Management console → Campaigns |
Try it yourself: a resilience audit
Harden an existing app against three real failure scenarios.
- 1Turn in-app AI off and open the screen that uses it — does it crash or degrade politely?
- 2Go into airplane mode and try to add a record; is the message understandable?
- 3Try uploading a very large photo and watch the error.
- 4For each gap, write one sentence to the builder: "hide this section when AI is off".
- 5Repeat the pass on a phone — tap targets and horizontal overflow.
An app that stays understandable with a feature off, the network gone and a file rejected.
Key takeaways
- Every SDK call can fail; translate the code into a human sentence.
- Mobile comes first — a wide screen opens the layout up, it doesn't copy the phone one.
- Configuration switches live in the builder and publish screens, not in code.
Related topics
devany.files, devany.mail, devany.hook and devany.ai — gates, quotas and error codes.
Common situations, their causes, and quick fixes.
What costs what, how plans and AI Credit work, and how you keep costs in check.
Still stuck? Ask the assistant in the corner, or browse the FAQ.