Jigx Mobile Development Kit - SDK for building Jigx applications
npm install @jigx/mdk

A comprehensive TypeScript MDK (Mobile Development Kit) for building mobile-first applications with the Jigx platform. This SDK provides a fluent API for creating offline-capable, data-driven mobile applications using Jigx's unique document-based architecture.
The style of the MDK follows that of a CDK, i.e., a declarative SDK. It compiles to Jigx's YAML configuration format.
Jigx is a mobile-first application platform that enables developers to build offline-capable, enterprise-grade mobile applications. This SDK provides a TypeScript-based fluent API that compiles to Jigx's YAML configuration format.
- Mobile-First Architecture: All UI patterns optimized for mobile devices with bottom-action buttons and touch-friendly interfaces
- Document-Based Storage: SQLite + JSON architecture for flexible, offline-capable data management
- Expression System: Powerful JSONata-based expressions for dynamic data binding and transformations
- Builder Pattern API: Intuitive fluent API with full TypeScript type safety and IntelliSense support
``bashUsing npm
npm install @jigx/mdk
Quick Start
`typescript
import { application } from '@jigx/mdk'const app = application('my-app', 'My Mobile App')
// Create a customer list screen
const listScreen = app.addScreen.list('customer-list', 'Customers')
.data('=@ctx.datasources.customers')
// Add list items
listScreen.addControl.listItem('customer-item')
.title('=@ctx.current.item.name')
.subtitle('=@ctx.current.item.email')
.onPress.goto('customer-detail')
.parameter('customerId', '=@ctx.current.item.id')
// Add bottom action button (mobile-first pattern)
listScreen.bottomPanel.buttons(1)
.add.goto('Add Customer', 'customer-form')
.style({ isPrimary: true })
// Build the application
const application = app.build()
`Core Concepts
$3
All UI patterns are optimized for mobile devices:
- Action buttons ALWAYS at screen bottom (max 3 visible)
- Touch-optimized controls and layouts
- Offline-first data synchronization$3
`typescript
// All data stored as JSON documents
const datasource = app.addDatasource.sqlite('customers', 'dynamic')
.entity('default/customers')
.query()
`$3
`typescript
// Dynamic values with JSONata expressions
import { CTX } from '@jigx/mdk'// Access datasources
CTX.datasources.expr('users') // '=@ctx.datasources.users'
// Access component state
CTX.components.expr('email', 'value') // '=@ctx.components.email.state.value'
// Access navigation parameters
CTX.screen.inputs.expr('customerId') // '=@ctx.jig.inputs.customerId'
`Screen Types
$3
`typescript
const listScreen = app.addScreen.list('products', 'Product Catalog')
.data('=@ctx.datasources.products')
.onRefresh.syncEntities()
.entity('products')
`$3
`typescript
const formScreen = app.addScreen.default('user-form', 'User Registration')// Add form fields
formScreen.addControl.textField('name')
.label('Full Name')
.required(true)
formScreen.addControl.emailField('email')
.label('Email Address')
.required(true)
// Bottom action buttons
const buttons = formScreen.bottomPanel.buttons(2)
buttons.add.goto('Cancel', 'home')
buttons.add.executeEntity('Save')
.style({ isPrimary: true })
.dynamicData('users', 'create')
.data({
name: '=@ctx.components.name.state.value',
email: '=@ctx.components.email.state.value'
})
`$3
`typescript
const calendarScreen = app.addScreen.calendar('events', 'Event Calendar')
.data('=@ctx.datasources.events')
.dateField('=@ctx.current.item.date')
.titleField('=@ctx.current.item.title')
`$3
`typescript
const tableScreen = app.addScreen.table('inventory', 'Inventory')
.data('=@ctx.datasources.inventory')tableScreen.addColumn('product', 'Product').width(200)
tableScreen.addColumn('quantity', 'Qty').width(80)
tableScreen.addColumn('price', 'Price').format('currency')
`Data Providers
$3
`typescript
app.addDatasource.sqlite('shared-data', 'dynamic')
.entity('default/customers')
.query(SELECT id, data FROM [default/customers])
`$3
`typescript
app.addDatasource.sqlite('preferences', 'local')
.entity('user-preferences')
.query(SELECT id, data FROM [user-preferences])
`$3
`typescript
const apiFunction = app.addFunction.rest('get-users', 'GET', 'https://api.example.com/users')
apiFunction.params.header('Authorization', 'Bearer =@ctx.solution.state.token')
`$3
`typescript
const sqlFunction = app.addFunction.sql('get-customer', 'customer-db')
.sql('SELECT * FROM customers WHERE id = @customerId')
sqlFunction.params.input('customerId', 'string')
`Critical Jigx Patterns
$3
`typescript
// WRONG - No inline buttons!
screen.addControl.button('save')// WRONG - Direct column access
.query('SELECT name FROM users')
// WRONG - Too many visible buttons
screen.bottomPanel.buttons(4)
`$3
`typescript
// CORRECT - Buttons at screen bottom
screen.bottomPanel.buttons(2)
.add.executeEntity('Save')// CORRECT - Use json_extract
.query(
SELECT json_extract(data, '$.name') as name FROM users)// CORRECT - Max 3 visible buttons
screen.bottomPanel.buttons(3)
`Component Examples
$3
`typescript
// Text input
screen.addControl.textField('name')
.label('Name')
.placeholder('Enter your name')
.required(true)// Dropdown
screen.addControl.dropdown('category')
.label('Category')
.datasource('=@ctx.datasources.categories')
.title('=@ctx.current.item.name')
.value('=@ctx.current.item.id')
// Date picker
screen.addControl.datePicker('startDate')
.label('Start Date')
.minimumDate('=@now()')
`$3
`typescript
// List item with swipe actions
const listItem = screen.addControl.listItem('product-item')
.title('=@ctx.current.item.name')
.subtitle('=$currency(@ctx.current.item.price)')
.image('=@ctx.current.item.imageUrl')// Swipe actions
listItem.swipeable.leftActions
.addAction.goto('Edit', 'edit-product')
.parameter('productId', '=@ctx.current.item.id')
listItem.swipeable.rightActions
.addAction.executeEntity('Delete')
.dynamicData('products', 'delete')
.data({ id: '=@ctx.current.item.id' })
`$3
`typescript
// Line chart
screen.addControl.lineChart('sales-chart')
.data('=@ctx.datasources.sales')
.xAxis('date')
.yAxis('revenue')
.height(300)// Pie chart
screen.addControl.pieChart('category-distribution')
.data('=@ctx.datasources.categories')
.labelField('name')
.valueField('count')
`State Management
$3
`typescript
// Set state
action.setState('currentUser')
.value({ id: '123', name: 'John' })// Access state
CTX.application.state.expr('currentUser.name')
`$3
`typescript
// Set screen state
action.setScreenState('selectedTab')
.value('products')// Access screen state
'=@ctx.jig.state.selectedTab'
`$3
`typescript
// Access component value
'=@ctx.components.email.state.value'// Check if valid
'=@ctx.components.email.state.isValid'
`Advanced Patterns
$3
`typescript
// Master list
const list = app.addScreen.list('orders', 'Orders')
.data('=@ctx.datasources.orders')list.addControl.listItem('order-item')
.title('=@ctx.current.item.orderNumber')
.subtitle('=$currency(@ctx.current.item.total)')
.onPress.goto('order-detail')
.parameter('orderId', '=@ctx.current.item.id')
.parameter('returnScreen', 'orders')
// Detail screen
const detail = app.addScreen.default('order-detail', 'Order Details')
// Add datasource for single order
detail.addDatasource.sqlite('order', 'dynamic')
.entity('default/orders')
.query(
)
.parameter('orderId', '=@ctx.jig.inputs.orderId')// Back navigation
detail.bottomPanel.buttons(1)
.add.goto('Back', '=@ctx.jig.inputs.returnScreen')
`$3
`typescript
// Initial sync on app load
app.onLoad.actionList('sequential')
.actions.syncEntities()
.dynamic()
.entity('users')
.entity('products')
.entity('orders')// Pull-to-refresh on screen
screen.onRefresh.syncEntities()
.dynamic()
.entity('orders')
.onSuccess.notification('Success', 'Orders refreshed')
.onError.notification('Error', 'Sync failed')
`$3
`typescript
const form = app.addScreen.default('product-form', 'New Product')// Form fields with validation
form.addControl.textField('name')
.label('Product Name')
.required(true)
.minLength(3)
.maxLength(50)
form.addControl.numberField('price')
.label('Price')
.required(true)
.minimum(0)
.format('currency')
form.addControl.dropdown('category')
.label('Category')
.required(true)
.datasource('=@ctx.datasources.categories')
.title('=@ctx.current.item.name')
.value('=@ctx.current.item.id')
// Conditional visibility
form.addControl.textField('discount')
.label('Discount Code')
.isVisible('=@ctx.components.price.state.value > 100')
// Form submission with validation
const buttons = form.bottomPanel.buttons(2)
buttons.add.goto('Cancel', 'products')
buttons.add.actionList('Save', 'sequential')
.style({ isPrimary: true })
.actions.executeEntity()
.dynamicData('products', 'create')
.data({
name: '=@ctx.components.name.state.value',
price: '=@ctx.components.price.state.value',
category: '=@ctx.components.category.state.selected.value',
discount: '=@ctx.components.discount.state.value'
})
.actions.syncEntities()
.entity('products')
.actions.goto('products')
``The SDK is organized into modular components:
- Application SDK: Main application builder and configuration
- Screen SDK: All screen types and layouts
- Component SDK: UI components and controls
- Action SDK: User interactions and navigation
- Datasource SDK: Data management and queries
- Function SDK: Business logic and integrations
- Database SDK: Database connection configurations
- Widget SDK: Home screen widgets
- Official Jigx Documentation
- Jigx SDK Guide - Comprehensive guide with examples and patterns
- SDK API Reference
- Migration Guide
- Best Practices
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.