Labs · продукт целиком
Сайт и приложение из одного ядра. Одна сборка, единый стандарт.
Сайт, который читают ваши клиенты, и приложение, которое носят ваши сотрудники, — это не два проекта, а два лица одной системы. Мы строим их на одном измеренном ядре, поэтому они никогда не разъезжаются, и за всё целиком отвечает одна рука.
Сайт и приложение читают одну и ту же истину. Измените её один раз — и оба меняются вместе.
Четыре цифры платформы, построенной как одно целое.
Те самые четыре части, которые делают это реальным. Читайте по порядку: истина, два лица, которые ей подчиняются, и шлюз, который не пропустит медленное ни на одном из них.
// MatchTop · the core — one definition both surfaces obey. // Written once. The portal and the field app read the same truth — they cannot drift. type Case = { id: Uuid, status: "open" | "review" | "closed", locale: Locale, // one language list, honoured by both surfaces updated: Instant, // stamped at the edge — one clock for web and app } service Portal { get case(id) -> Case list cases(for: Holder) -> Case[] }
<!-- the web surface · server-rendered at the edge, zero JS to read a case --> <article class="case" lang="{{ case.locale }}"> <h1>{{ t("case.title", case.id) }}</h1> <p class="status status--{{ case.status }}">{{ t("status." + case.status) }}</p> <time datetime="{{ case.updated }}">{{ t.date(case.updated) }}</time> </article> // same Case. same locale list. no bundle to boot before the page can be read.
// the app surface · the same contract, compiled. A wrong field will not build. #[derive(Deserialize)] struct Case { id: Uuid, status: Status, // an enum, not a loose string — the compiler holds the line locale: Locale, updated: Instant, } impl Case { /// Works offline: the last truth we fetched is still the same shape. fn is_open(&self) -> bool { matches!(self.status, Status::Open | Status::Review) } }
"""MatchTop · the gate — one standard over both surfaces. Standard library only. It runs in your pipeline, and it can say no to either face.""" import sys BUDGET = {"first_paint_ms": 100, "js_kb": 0, "a11y": "AA"} # promised, so measured def gate(surface: str, got: dict) -> None: fails = [k for k, limit in BUDGET.items() if _worse(got[k], limit)] # every promise is a test if fails: print(f"HELD · {surface} · " + ", ".join(fails)) sys.exit(1) # neither the site nor the app ships below the line print(f"GREEN · {surface} · measured, and worthy of your name on it")
Почему один дом на всё целое сильнее двух подрядчиков, сшитых по шву.
Это не скидка за покупку двух вещей сразу. Это другая форма: одна система с двумя лицами, а не две системы, склеенные скотчем. Подрядчик, который продаёт сайт и отдаёт приложение на субподряд, не может передать вам общее ядро — у него его нет. Именно эту часть не перебить ценой.
Ещё до первой строки кода — как хранится ваша работа. Эта часть не обсуждается.
NDA здесь — норма, а не дополнительная услуга. То, что вы передаёте, читает один инженер и больше никто — ничего не продаётся, не передаётся и не разглашается.
Учётные данные и записи остаются в вашем доме, по принципу минимальных привилегий. Мы не держим копий, которые нам не нужны, и ничто не покидает вашу зону контроля без вашего слова.
То, что работает в вашем доме, вы можете читать и проверять — никакого чёрного ящика, которому нужно верить не глядя. Машинное отделение остаётся нашим; то, что вы эксплуатируете, — ваше.
Продукт целиком — в двух строках. Мы читаем их сами и отвечаем сами — за этим окном нет очереди.
Оно уже на экране в Цюрихе — не в очереди и не в тикете. Инженер, который это построит, читает его и отвечает сам.
·