Сервер
Определяет структуру и поведение UI
Сервер хранит компоненты UI
Кнопки, списки, баннеры и другие элементы определяются
на бэкенде
Мгновенные обновления
Изменения вступают в силу без обновления приложения
Единый код для всех платформ
iOS, Android и Web используют один и тот же APIПерсонализация для каждого пользователя
Разные сегменты пользователей получают разный интерфейс
Как это работает?
JSON / API
Передает инструкции клиенту
Клиент
Отрисовывает интерфейс на основе полученных инструкций
Проблемы, которые решает matreshka
Время вывода новых функций на рынок
традиционный
подход
matreshka
*согласно собственной статистике, накопленной на реализованных проектах
Как используют BDUI крупные компании
Распространение технологии
Все побольше стартапов выбирают кроссплатформенные инструменты для решения задач
Востребовано на всех континентах.
Ключевые отрасли
Адаптивные рекомендации и единый опыт на всех устройствах.
Динамические обновления и мгновенные изменения интерфейса.
Пример кода на matreshka
new Card({ width: 250, outline: CardOutlineStyle.None, content: [ new Column({ align: { cross: ColumnCrossAxisAlign.SpaceBetween, }, height: 1, content: [ new Column({ content: [ new Image({ key: `${key}.image` }), new Heading({ level: 3, key: `${key}.name` }), new Text({ key: `${key}.description` }), ] }), new Column({ content: [ new Currency({ key: `${key}.price`, currency: "RUB" }), new Button({ label: new Text({ value: "Купить" }), style: ButtonStyle.Tint, }) ], }), ] }) ] })
new Heading({ level: 2, value: "Похожие товары" }), new Row({ scrollable: true, content: [ new ForEach({ key: "similarProducts", context: this.context, track: (data) => data.id, generator: ({ key }) => new Card({ width: 250, outline: CardOutlineStyle.None, content: [ new Column({ align: { cross: ColumnCrossAxisAlign.SpaceBetween, }, height: 1, content: [ new Column({ content: [ new Image({ key: `${key}.image` }), new Heading({ level: 3, key: `${key}.name` }), new Text({ key: `${key}.description` }), ] }), new Column({ content: [ new Currency({ key: `${key}.price`, currency: "RUB" }), new Button({ label: new Text({ value: "Купить" }), style: ButtonStyle.Tint, }) ], }), ] }) ] }) }), ] }),
new Heading({ level: 2, value: "Похожие товары" }), new Row({ scrollable: true, content: [ new ForEach({ key: "similarProducts", context: this.context, track: (data) => data.id, generator: ({ key }) => // Карточка товара }), ] }),
// product = { id: "1", name: { ru: "Смартфон iPhone 15 Pro", en: "iPhone 15 Pro Smartphone" }, price: 99999, image: "https://images.biggeek.ru/1/870/4506/28465-146iphone-16-pro-finish-select-202409-6-3inch-blacktitanium@2x.jpg", description: { ru: "Новейший смартфон с мощным процессором A17 Pro, камерой 48 Мп и титановым корпусом.", en: "Latest smartphone with powerful A17 Pro processor, 48MP camera and titanium body." } }; content: [ new Image({ key: `product.image` }), new Heading({ level: 3, key: `product.name.@{language}` }), new Text({ key: `product.description.@{language}` }), ]
new Card({ outline: CardOutlineStyle.None, content: [ new Row({ content: [ // Изображение товара new Column({ width: { desktop: 0.4, tablet: 1, mobile: 1, }, content: [ new Image({ key: "product.image" }) ] }), // Информация о товаре new Column({ width: { desktop: 0.6, tablet: 1, mobile: 1, }, padding: { start: true, }, content: [ new Heading({ level: 1, key: "product.name" }), new Text({ key: "product.description" }), new Row({ content: [ new Currency({ key: "product.price", currency: "RUB" }) ], padding: { top: true, bottom: true, } }), new Button({ label: new Text({ value: "Добавить в корзину" }), style: ButtonStyle.Filled, onClick: () => { // some logic } }), new Button({ label: new Text({ value: "Купить в 1 клик" }), style: ButtonStyle.Tint, onClick: () => { // some logic } }), new Button({ label: new Text({ value: "Оформить рассрочку" }), style: ButtonStyle.Tint, onClick: () => { // some logic } }) ] }) ] }), ] })
// На этапе добавления страниц в систему можно использовать условия для отображения страниц // Например, для бета-тестеров показываем новую версию, тут может быть любая логика // В данном случае, для всех пользователей, у которых в localStorage есть ключ beta-enabled со значением 1, показываем новую версию // Для всех остальных пользователей показываем старую версию matreshkaInstance.router.addPage( "/components/product-card", NewProductCardPage, async (client) => client.getStorageValue('beta-enabled') == '1'); matreshkaInstance.router.addPage( "/components/product-card", ProductCardPage );