Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
コンパウンドプロダクトの画面を Schema-Driven UI で描く
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Masayuki Takahashi
November 02, 2026
38
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
コンパウンドプロダクトの画面を Schema-Driven UI で描く
Masayuki Takahashi
November 02, 2026
More Decks by Masayuki Takahashi
See All by Masayuki Takahashi
グローバルなコンパウンドプロダクトのためのフロントエンドアーキテクチャ設計 #MOSHTech
mozu1206
2
140
デザイナーと協業しているNuxtプロジェクトを、ChromaticによるVRTでさらに改善した話
mozu1206
0
1k
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
610
The SEO identity crisis: Don't let AI make you average
varn
0
620
Everyday Curiosity
cassininazir
0
380
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
480
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
750
Statistics for Hackers
jakevdp
799
230k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
350
My Coaching Mixtape
mlcsv
0
370
Transcript
コンパウンドプロダクトの画面を Schema-Driven UI で描く Dress Code株式会社 / Product & Technology
もず(高橋 正幸)
自己紹介 • 業務 ◦ ◦ HR領域のプロダクト開発エンジニア プロダクト全体のUIUX改善 • 経歴 ◦
◦ ◦ 2021/04 ASP事業会社 2022/04 株式会社HRBrain 2025/10 Dress Code株式会社 • 技術 ◦ ◦ ユーザー体験とか考えるのが好き フロント専任からフルスタックに挑戦中 もず(@mozu1206) • 趣味 ◦ コーヒー / スプラトゥーン CONFIDENTIAL | © Dress Code Inc . All rights reserved. 2
会社概要 Company Name / 会社名 Dress Code 株式会社 CEO /
代表取締役 江尻 祐樹 Date of establishment / 設立年月 2024年9月(正式創業 2025年4月) Location / 所在地 東京都中央区築地2-1-4 銀座PREX East 8F Member / メンバー数 56名 Pre Seed&Seed Round Number of companies Number of countries 14.1億円 250+社 5カ国 資金調達を実施 が利用中 で事業を展開 CONFIDENTIAL | © Dress Code Inc . All rights reserved. 3
CONFIDENTIAL Copyright © DressCode Inc. All rights reserved. 4
CONFIDENTIAL | © Dress Code Inc . All rights reserved.
5
下記登壇内容の具体を今日は話します CONFIDENTIAL | © Dress Code Inc . All rights
reserved. 6
誰が書いても、同じ形になる仕組みが要る 人が書きやすいだけでなく、AI が間違えずに複製できること CONFIDENTIAL | © Dress Code Inc .
All rights reserved. 7
解決策として、 Schema-Driven UI を取り入れた 画面の定義のSSoTを、Backend に 1 つ置く CONFIDENTIAL |
© Dress Code Inc . All rights reserved. 8
Schema-Driven UI とは 一般の呼び名 私たちの呼び方 Server-Driven UI Schema-Driven UI サーバーがデータだけでなく画面の形まで返し、クライアントは
それを描く スキーマ(zod の契約)を正とし、Backend はそれに従って 返し、Frontend はそれに従って描く 採用例: Airbnb(Ghost Platform)、Lyft ねらい: 誰が書いても同じ形になる ねらい: アプリのリリースを待たずに画面を変える 参考: Airbnb Tech Blog「A Deep Dive into Airbnb’s Server-Driven UI System」(2021、medium.com/airbnb-engineering) Lyft Engineering「The Journey to Server Driven UI At Lyft Bikes and Scooters」(eng.lyft.com) 仕組みは Server-Driven UI。スキーマを正とするから Schema-Driven UI CONFIDENTIAL | © Dress Code Inc . All rights reserved. 9
1/2 一覧画面 カラム定義を、Backend が返す CONFIDENTIAL | © Dress Code Inc
. All rights reserved. 10
これまで 1 カラムを 1 つ足すたびに、3 か所を揃えていた Frontend 2 Backend 3
Frontend カラム定義を足す 返すデータを足す セルを選ぶ 見出し・順番・ソート可否 クエリと DTO に項目を増やす 日付は DateCell、人は PersonCell </ routes/<<./columns.tsx(Frontend) const columns = [ { id: 'name', header: '氏名', cell: PersonCell, enableSorting: true }, { id: 'joinedAt', header: '入社日', cell: DateCell, enableSorting: true }, ] 普通のやり方。ただ、揃えるのは書き手の注意力まかせで、書き手が増えるほどズレる CONFIDENTIAL | © Dress Code Inc . All rights reserved. 11
いま Backend が、カラム定義とセルの種類まで返す Backend 一覧画面 名前 種別 状態 担当者 購入日
ノート PC 001 PC 貸出中 山田 太郎 2025/04/01 カラム定義 見出し・順番・ソート可否 返すデータ モニター 014 周辺機器 在庫 - 2025/06/12 スマホ 007 モバイル 貸出中 佐藤 花子 2024/11/20 ノート PC 023 PC 修理中 鈴木 一郎 2023/09/05 キーボード 102 周辺機器 在庫 - 2026/01/15 行ごとの値 セルの種類 cellType Frontend タブレット 003 モバイル 貸出中 高橋 健 2025/02/28 cellType に部品を当てて描くだけ 一覧画面のイメージ(データは架空)。見出し・順番・セルの種類は Backend が返す 3 か所が Backend の 1 か所に集まった。カラム定義はフロントが触らない CONFIDENTIAL | © Dress Code Inc . All rights reserved. 12
カラムは Backend が決め、Frontend は写すだけ Backend:カラムを定義する Frontend:写して部品を当てる </ カラム定義(Backend) export const
COLUMNS = { name: { cellType: CellType.PERSON_NAME, sortable: true, sortKey: 'NAME', pinned: ColumnPin.LEFT, minWidth: '240px', }, </ <<. }; </ カラム定義を写す(Frontend) export function buildDynamicColumns(columns) { return columns.map((col) <> ({ id: col.fieldKey, accessorFn: (r) <> r.fieldValues[col.fieldKey], enableSorting: col.sortable, cell: getCellRenderer(col), })); } </ cellType から部品を引く STATIC_RENDERERS.get(col.cellType) <? FallbackCell fieldKey ごとの if はない。cellType で部品を引くだけ CONFIDENTIAL | © Dress Code Inc . All rights reserved. 13
一覧画面のフロントは、カラム以外だけを書く Frontend:ある一覧画面 この画面で </ 一覧画面のコンポーネント(Frontend、46 行) const { data, isPending,
tableProps } = useListDynamicTable({ search, navigate, </ 行クリックの遷移はフロントから渡す onNavigateToDetail: (id) <> navigate({ to: '/items/$id', params: { id } }), }); 書かない return <DynamicDataTable data={data} isPending={isPending} {<<.tableProps} <>; 検索条件と URL の同期、行クリックの遷移先(Backend は行の id だけ返す)、カラムの表示切替ボタン(右端の操 作カラム) カラムの見出し・順番・幅、セルの選び方、翻訳キー。 Backend が返す 書く 画面ごとに書くのは、その画面だけの振る舞い。データのカラム定義は 1 行も書かない CONFIDENTIAL | © Dress Code Inc . All rights reserved. 14
カラムの追加が、Backend の PR 1 本で終わる </ カラム定義 + ItemCount: {
+ cellType: CellType.TEXT, sortable: false, minWidth: '100px', + }, </ 行の値への変換 + ItemCount: (row) <> String(row.itemCount), </ 一覧を取ってくるクエリ - select: { name: true }, + select: { name: true, items: true }, + itemCount: r._count.items, </ 契約 + itemCount: z.number(), 5 ファイル Backend の変更(テストを除く) 0行 Frontend の変更 取ってくる、返すを 1 つ増やして、カラムとセルを選ぶ。それで終わり CONFIDENTIAL | © Dress Code Inc . All rights reserved. 15
知らない値が来ても、フロントは止まらない Backend:契約 配り方 </ 契約(Backend) const ColumnSchema = z.object({ fieldKey:
z.string(), fieldName: z.string(), cellType: z.string(), </ enum にしない sortable: z.boolean(), pinned: z.string().nullable(), }); Backend の契約ファイルに zod で書く enum にしない理由 enum で縛ると、Backend と Frontend を同時にデプロイしないと壊れる。 書く側(Backend)は CellType の定数で縛る。ゆるいのは配る型だけ。 知らない値は FallbackCell で描く ビルドで集めて型にし、GitHub Packages へ publish Frontend は契約に沿った型で受け取る 契約の正本は Backend に 1 つ。型はゆるく配って、描く側で守る CONFIDENTIAL | © Dress Code Inc . All rights reserved. 16
フロントは、届いたカラムをそのまま描くだけ これまで:カラム定義はフロント いま:カラム定義は Backend const allColumns = [<<.]; </ カラム定義はフロント
</ 権限を見て、カラムを間引く const columns = allColumns.filter((col) <> canView(user, col.fieldKey), ); </ 並び替え・絞り込みでも、同じ判定をもう一度 </ カラム定義は Backend から届く const columns = buildDynamicColumns(schema.columns); </ 権限の判定は、フロントにはない 見せないカラムは、Backend が最初から返さない カラム定義も、値も、そのカラムでの並び替え・絞り込みの条件も、まとめて外して返す 出す・出さないはフロントで考えない。届いたものを、そのまま描く CONFIDENTIAL | © Dress Code Inc . All rights reserved. 17
合う部品がないときだけ、フロントで作る Backend Frontend カラム定義と値を返す 新しいセルを作って登録する いつもどおりカラム定義に足し、新しい cellType を指定する 全 cellType
に描画があるかを、テストで確かめる 部品をどう作り、どんな契約で配るか。それが dresscode-ui 詳しくは山口さんの「契約で守るコンパウンドプロダクトのデザインシステム」へ CONFIDENTIAL | © Dress Code Inc . All rights reserved. 18
2/2 詳細画面 属性の定義も、Backend が返す CONFIDENTIAL | © Dress Code Inc
. All rights reserved. 19
詳細画面は、セクションに属性が並ぶだけ 詳細画面 セクション 名前 colspan 3 種別 colspan 6 説明
電話番号 colspan 3 colspan 3 状態 詳細画面のイメージ。valueType は一覧の cellType、colspan は幅 colspan 3 </ 属性の定義(Backend) Name: b.define({ attributeKey: AttributeKey.NAME, valueType: ValueType.TEXT, colspan: 3, }), Category: b.define({ <<. colspan: 3 }), Description: b.define({ <<. colspan: 6 }), </ 詳細画面のセクション(Frontend) <FormSection label={section.name}> <AttributeRenderer attributes={section.attributes} attributeRenderInterceptor={<<.} <> </FormSection> valueType ごとの分岐は共通部品に集め、画面側はその画面だけの上書きを書く CONFIDENTIAL | © Dress Code Inc . All rights reserved. 20
まとめ ・同じことを 2 か所に書くと、いつか必ずずれる ・正本は、その情報をいちばん知っている場所に置く(今回は Backend) ・受け取る側は、知らない値でも止まらずに描けるようにしておく 揃えるのは、 人ではなく仕組みに任せる CONFIDENTIAL
| © Dress Code Inc . All rights reserved. 21
宣伝 CONFIDENTIAL | © Dress Code Inc . All rights
reserved. 22
技術発信に力を入れています!! • Dress Code イベント登壇情報まとめ Dress Code Advent Calendar 2026/07
CONFIDENTIAL | © Dress Code Inc . All rights reserved. 23
年末に社内イベントやります! CONFIDENTIAL | © Dress Code Inc . All rights
reserved. 24
Thank you for your attention. We are Hiring! CONFIDENTIAL |
© Dress Code Inc . All rights reserved. 25