Сервер
Определяет структуру и поведение UI
Сервер хранит компоненты UI
Кнопки, списки, баннеры и другие элементы определяются
на бэкенде
Мгновенные обновления
Изменения вступают в силу без обновления приложения
Единый код для всех платформ
iOS, Android и Web используют один и тот же APIПерсонализация для каждого пользователя
Разные сегменты пользователей получают разный интерфейс
Как это работает?
JSON / API
Передает инструкции клиенту
Клиент
Отрисовывает интерфейс на основе полученных инструкций
Проблемы, которые решает matreshka
Время вывода новых функций на рынок
традиционный
подход
matreshka
*согласно собственной статистике, накопленной на реализованных проектах
Как используют BDUI крупные компании
Распространение технологии
В 2024 году 34% новых мобильных стартапов выбирают 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 }) => // Карточка товара
}),
]
}),
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
}
})
]
})
]
}),
]
})
// 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}`
}),
]
// На этапе добавления страниц в систему можно использовать условия для отображения страниц
// Например, для бета-тестеров показываем новую версию, тут может быть любая логика
// В данном случае, для всех пользователей, у которых в 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
);