Skip to content
ONIWC
iwc 0.1.0

Limitations

What IWC does not do today, found while building the store, the cookbook and a class-booking app written from scratch. Each entry says what to do instead. Nothing here is faked anywhere in the examples.

Capability map

Where IWC stands against the kinds of applications it is meant for. Built in means declared in .iwc files with no code; through services means an http service plus actions (no IWC-specific code, but you wire the provider's API yourself); not yet means there is no way to do it in IWC today.

AreaStatusWhat exists
Pages, components, layouts, routingBuilt inServer-rendered screens, components with props and slots, layouts with persistent slots, SPA navigation, guards, 404
Forms and validationBuilt inServer-authoritative validation shown per field; uploads
Database, relations, migrationsBuilt inSQLite / PostgreSQL, relations with onDelete, indexes, unique constraints, additive migrations, seeds
Business logic and transactionsBuilt inActions (15 step types, expressions, atomic increments, expect), one transaction per action
Record lifecyclesBuilt inWorkflows (state machines) with role- and row-scoped transitions
Background workBuilt inDurable jobs with retries, schedules (every), events with handlers
Auth, roles, ownershipBuilt inEmail + password, sessions, bearer tokens, role inheritance, owner rules, protected route areas
Multi-tenant SaaSBuilt inapp.tenancy + "tenant": true scopes every read and write to the user's tenant
Permissions and record scopesBuilt inDeclared permissions, roles and grants from the database, membership scopes (a manager sees their stores' rows), API/action guards. See access control
Several apps, one backendBuilt inMulti-app projects: per-app screens, URLs, hosts, cookies, builds; shared schemas and logic
Retries and abuseBuilt inIdempotency keys on writes, rate limits per IP, user or request value, optionally shared through the database
Security defaultsBuilt inCSRF, strict CSP with nonces, rate limits, CORS allow-list, SSRF-guarded outbound calls, sensitive fields never leave the server, field encryption at rest, secrets refused in files and builds and redacted from logs, iwc security audit. See security
CredentialsBuilt inEncrypted development vault and iwc secrets; production reads the environment
Live updatesPartialServer push (SSE) re-renders live data blocks and announces broadcast events by name. @iwc/realtime publishes to Pusher/Ably channels and authorises private ones; a widget can load their browser SDKs to subscribe
Client statePartialStores with fixed mutations (set push upsert remove increment clear) and derived sums/counts; persisted locally
Payments, refundsBuilt in@iwc/payments: Stripe, Razorpay, PayPal, Cashfree hosted checkout, status, capture, refunds, verified webhooks
Subscriptions, payouts, marketplace splitsBuilt in@iwc/payments subscriptions, listPayments for reconciliation, connected accounts and transfers (Stripe Connect, Razorpay Route, PayPal payouts), Stripe destination charges
WebhooksBuilt inrequest.rawBody + declared headers, and verifyHmacSecret with secrets declared in app.iwc (hex/base64 HMAC-SHA256, constant-time). See verifying signed webhooks
Third-party APIsThrough servicesDeclarative http services with auth headers, per-method headers (API versions), timeouts, retries with backoff, cached reads with request collapsing, simulated providers for development. No GraphQL helper (POST a query body), no pagination helper for external APIs
EmailBuilt in@iwc/mail: Resend, SendGrid, SES, Mailgun, Postmark, Brevo, SMTP; also delivers notify
SMS, WhatsApp, pushBuilt in@iwc/sms (Twilio, Vonage, Plivo), @iwc/whatsapp (Meta, Twilio), push notifications to browsers, Android and iOS (devices kept by IWC, push step, iwc push test); @iwc/push (FCM, APNs, OneSignal, Web Push)
AI modelsBuilt in@iwc/ai (Claude, OpenAI, Gemini, OpenAI-compatible): streaming to the browser, tool calling (tools can be IWC actions, run as the user), JSON-Schema output, token usage
Search, maps, videoBuilt in@iwc/search (Algolia, Meilisearch, Typesense), @iwc/maps (Google, Mapbox, OpenStreetMap; autocomplete), @iwc/video (Mux, Cloudflare Stream)
Shipping, bot protection, analyticsBuilt in@iwc/shipping (Shiprocket, Delhivery, Shippo, EasyPost; normalised tracking), @iwc/captcha (Turnstile, hCaptcha, reCAPTCHA; server check only, the page's widget is yours), @iwc/analytics (PostHog, GA4, Segment, Mixpanel; server-side)
Not yet as packagesNot yetAdyen, PayU; Blue Dart/DTDC direct (no self-serve API: use an aggregator); Cloudinary, Bunny; calendars, accounting, social media APIs; PDF generation; video calling
Phone sign-in (Firebase), refresh-token sessions, device list/revokeYesauthentication
Password reset, email verificationBuilt inauthentication
OAuth / social sign-in, multi-factorBuilt inGoogle, Microsoft, Apple, GitHub, GitLab, Discord, Facebook, LinkedIn, any OIDC with account linking; TOTP, email and SMS codes, recovery codes
Custom client-side JavaScriptBuilt inWidgets: your own code and third-party SDKs (SRI-pinned) with a CSP widened only on the pages that use them, or sandboxed in an opaque-origin frame; bundled rich-text editor, map, Stripe Payment Element, HLS video player
Installable web app (PWA), offline data and syncBuilt iniwc enable pwa / iwc enable offline: manifest, service worker, push; stored screens, queued writes sent exactly once, conflicts, sync status on the web, Android and iOS
WebSocketsBuilt in/_iwc/ws carries the live change events (web and native apps; SSE remains the fallback). Server → client only; your own messages over it are not yet supported
WebRTC, audio/video callingNot yet
Firebase and other realtime backendsThrough services + widgetsREST APIs from actions; browser SDKs in a widget
File storageBuilt inLocal disk or any S3-compatible bucket (S3, R2, MinIO…) behind the same storage.* APIs: uploads, presigned direct uploads checked on completion, signed downloads, delete, private files, per-endpoint type/size rules
CachingBuilt inPer-visitor data and API caches cleared by writes
Reports and summariesBuilt inaggregate in actions and data sources: grouped sums, counts, averages, minimums and maximums computed by the database, date buckets in the app's time zone, under the same access rules; filter bars in the URL
SpreadsheetsBuilt inCSV responses (formula-injection safe) and parseCsv() for imports; createMany for bulk inserts
Backup and restoreBuilt iniwc backup / iwc restore: one portable archive (data and uploads), consistent snapshot on PostgreSQL, restore in one transaction, SQLite ⇄ PostgreSQL
API documentationBuilt inOpenAPI 3.1 (JSON and YAML) derived from the definitions, an interactive explorer with Try it out at /_iwc/api-docs, iwc make --api docs for files; versioned endpoints (/api/v2/...)
Logs, diagnosticsBuilt inStructured logs, request log, audit of actions and transitions, /_iwc/health, iwc logs. No metrics or tracing export
DeploymentBuilt iniwc deploy to cPanel shared hosting (through cPanel's API, with rollback) or to your own Linux server over SSH (setup wizard, systemd service, nginx or Caddy with automatic HTTPS, atomic releases, rollback, logs, status), an HTTPS release host, and a zip for shared hosting. Servers need systemd; IWC installs Caddy (or certbot for nginx) on Debian, Ubuntu, Fedora and RHEL-like systems; other web servers on 80/443 need "proxy": "none". One server per target (no multi-server rollout or load balancing)
Extending the CLIBuilt inPlugins: iwc-<name> executables; x-<vendor> keys for other tools' data
InternationalisationNot yetOne language per app (head.lang); no message catalogues or locale formats
SEO and sharingBuilt inServer-rendered metadata: dynamic titles, canonical, Open Graph/Twitter, JSON-LD, robots.txt, sitemap.xml, 404 for missing records
PerformanceBuilt inPer-route runtime modules and size budgets; a benchmark against Next.js and Angular (bench/REPORT.md in the IWC repository). No critical-CSS inlining or image pipeline yet

Pages and data

MissingEffectInstead
Expressions in the browserExpressions run on the server. Elements repeated from client state (STATE. sources) and values that change in the browser can't use themUse bind for client state; client-side expressions are the next roadmap phase
Nested includesAn include can't include more (a review's author's company)A second page-data source filtered by the first, or store the value on the record
Large has-many includesOne include loads at most 5,000 rows per data block (100 per record by default)Paginate the parent, or list the children on their own page
Client-side form validationErrors appear after the server answers (quickly, but after a round trip)Server validation is authoritative anyway
Data sources inside STATE templatesA cart line can't look up live stockRead live data on the server pages (cart totals are re-checked at checkout)
Localised datesapp.iwc timeZone and localTime/localDate/weekday give local times in expressions, but the page formats (date-long, time…) still show UTC with English month namesFormat with localDate/localTime in an expression

Layout and styling

MissingNotes
Layout structure.side and sidebar sideAccepted, but have no effect. Order slots or use template
Min-width breakpointsresponsive is desktop-first (max-width). Mobile-first needs your own CSS media queries
A CSS build stepNo Sass or Tailwind compiler. Ship compiled CSS in styles/
Critical-CSS extractionA stylesheet up to performance.inlineStyles (8KB gzipped by default) is written into the first page a visitor opens. A larger one is linked whole: one extra round trip before first paint (about 600 ms on a slow mobile network, see bench/REPORT.md). IWC doesn't split out the above-the-fold rules
Inlining's server costGzipping the inlined stylesheet with every first-visit page roughly halves that response's throughput (bench/REPORT.md); navigations don't pay it. "inlineStyles": "0B" links instead
Image optimisationNo resizing, modern formats or srcset. Images load lazily unless marked "loading": "eager" or "priority"
Confirmation messagesA state change from a button ("Added") and an API button ("Done") always show IWC's status message; an app can't change the words or turn it off per button

Back end

MissingNotes
Email without @iwc/mailnotify steps are logged in development and fail (status failed in _iwc_outbox) in production until a mail integration is installed
Destructive migrationsType changes, renames and drops aren't automatic (by design)
Database CHECK constraintsField rules (min, max, enum) are enforced by IWC on every write, not by the database, so raw SQL can bypass them
Foreign keys closing a cycle on SQLiteTwo tables that point at each other get the cycle-closing foreign key on PostgreSQL only; SQLite relies on IWC's relation checks for that field
A community package registryThe @iwc/* packages are compiled into the CLI; third parties can't publish packages yet (CLI plugins and .service.iwc files are the extension points)
Live-verified providersEvery @iwc/* provider (OAuth, billing and AI streaming included) is tested against a fake of its API and published signing examples, not against live accounts; iwc integrations verify checks yours
A QR code for authenticator setupauth.mfaSetup returns the otpauth:// URL; drawing it as a QR code is up to the page (a widget can)
MySQLDatabases are SQLite or PostgreSQL. On shared hosting the zip uses SQLite in data/
Screens under reserved prefixesA route starting /api/, /assets/ or /_iwc/ is silently unreachable (no compile warning)

Development experience

MissingNotes
State-preserving hot reload for .iwc edits.css edits swap in place; other edits reload the page (scroll position and persisted client state survive; unsaved form input does not)
A language serverAutocompletion and validation come from the JSON Schemas. Cross-file checks (references, bindings) run in iwc check / iwc dev

Native apps

Android (Jetpack Compose) and iOS (SwiftUI) apps come in two kinds, and neither ever draws a web view: server-driven apps (server set) draw what the IWC server renders, with forms, records, sign-in, secure token storage, links, lock, share, photos, camera, location and push; apps built without a server compile a fixed set of screens into the app (what they render).

MissingNotes
Cashfree's in-app sheet on iOSCashfree publishes no versioned Swift package; on iOS its pay buttons use hosted checkout (Android has the sheet; Stripe and Razorpay have it on both)
Share target on iOSiOS lists apps in the share sheet only through a Share Extension, which IWC doesn't generate yet (Android and installed web apps are share targets)
Social sign-in with a second factor in appsAn account that needs MFA after a social sign-in is asked to sign in with its password in the app
Background location on iOS when closedTracking continues in the background while the app is running (the blue indicator); iOS doesn't relaunch an app the person swiped away for it
Built-without-server appsForms, records, sign-in and interactive widgets need server
An iOS app icon from SVGiOS needs a 1024 px PNG icon
Native hot reloadiwc dev --platform … rebuilds and relaunches on save (seconds), state is not kept
Building iOS off macOSApple's toolchain runs only on macOS; use a Mac or a macOS CI runner

Source: iwc/docs/limitations.md