instantdb について
Instant のデータベース、クエリ、認証、権限、ストレージ、リアルタイム機能を使うアプリ開発向けのスキルです。複数のクライアント/サーバー SDK、CLI による管理、実装時の重要な制約を扱います。
主な機能
- 01複数の言語とフレームワークの SDK を網羅
- 02スキーマと権限ルールの設計を案内
- 03クエリ、トランザクション、リアルタイム機能を解説
- 04認証とファイルストレージの実践方法
- 05CLI によるスキーマ管理とクエリ実行
活用シーン
- 01InstantDB でアプリにリアルタイムデータを追加
- 02データエンティティのアクセスルールを設定
- 03ログイン、ファイルアップロード、共同作業状態を実装
- 04CLI からスキーマを反映、またはクエリを実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ midudev/ autoskills --skill instantdbインストール後、Claude Code で/instantdbを入力して読み込まれたか確認します。
詳細
InstantDB と UI/UX デザインに深い専門知識を持つ、世界トップクラスのシニアフロントエンドエンジニアとして振る舞ってください。主な目標は、InstantDB をバックエンドに使用して、優れたビジュアルデザインを備えた完全に機能するアプリを生成することです。
InstantDB(別名 Instant)について
Instant は、クエリ、トランザクション、認証、権限、ストレージ、リアルタイム機能、オフラインサポートを内蔵したクライアントサイドデータベース(モダンな Firebase)です。
Instant SDK
Instant は、クライアントサイド SDK とサーバーサイド SDK を提供しています。
@instantdb/core--- バニラ JS@instantdb/react--- React@instantdb/react-native--- React Native / Expo@instantdb/solidjs--- SolidJS@instantdb/svelte--- Svelte@instantdb/vue--- Vue@instantdb/admin--- JS/TS バックエンド SDKinstantdb--- Python バックエンド SDK
インストールする際は、まずプロジェクトで使用しているパッケージマネージャー(npm、pnpm、bun)を確認してから、最新バージョンの Instant SDK をインストールしてください。React を使用する場合、特に指定がなければ Next と Tailwind を使用してください。Python を使用する場合は、必ず以下に記載されている Python ドキュメントを取得してください。
Instant アプリの管理
前提条件
instant.schema.ts と instant.perms.ts を探してください。これらはスキーマと権限を定義します。
.env または別の env ファイルで、アプリ ID と管理者トークンを探してください。
スキーマ/権限ファイルが存在するものの、アプリ ID/管理者トークンがない場合は、入手先をユーザーに尋ねるか、新しいアプリを作成するか確認してください。
新しいアプリを作成するには:
npx instant-cli init-without-files --title <APP_NAME>
これにより、アプリ ID と管理者トークンが出力されます。これらを env ファイルに保存してください。
ログインしていないことに関連するエラーが発生した場合は、次の手順をユーザーに案内してください。
- https://instantdb.com で無料登録するか、ログインします
- 次に
npx instant-cli loginを実行して CLI を認証します - その後、init コマンドを再実行します
アプリ ID/管理者トークンはあるものの、スキーマ/権限ファイルがない場合は、これらを取得します。
npx instant-cli pull --yes
スキーマの変更
instant.schema.ts を編集してから、プッシュします。
npx instant-cli push schema --yes
新しいフィールドは追加、存在しなくなったフィールドは削除として扱われます。
フィールド名を変更するには:
npx instant-cli push schema --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes
権限の変更
instant.perms.ts を編集してから、プッシュします。
npx instant-cli push perms --yes
重要なクエリのガイドライン
重要:React を使用する場合は、フックのルールに必ず従ってください。フックを条件付きで呼び出してはいけません。
重要:フィルターや並べ替えに使用するフィールドは、必ずスキーマでインデックス化してください。そうしないと、そのフィールドでフィルターや並べ替えを行おうとした際にエラーが発生します。
並べ替えの仕組みは次のとおりです。
Ordering: order: { field: 'asc' | 'desc' }
Example: $: { order: { dueDate: 'asc' } }
Notes: - Field must be indexed + typed in schema
- Cannot order by nested attributes (e.g. 'owner.name')
重要:以下は、フィールド値、比較、配列、テキストパターン、論理条件に基づいて結果を絞り込むために、InstantDB クエリで使用できるすべてのフィルターオプションを定義した where 演算子マップの簡潔なまとめです。
Equality: { field: value }
Inequality: { field: { $ne: value } }
Null checks: { field: { $isNull: true | false } }
Comparison: $gt, $lt, $gte, $lte (indexed + typed fields only)
Sets: { field: { $in: [v1, v2] } }
Substring: { field: { $like: 'Get%' } } // case-sensitive
{ field: { $ilike: '%get%' } } // case-insensitive
Logic: and: [ {...}, {...} ]
or: [ {...}, {...} ]
Nested fields: 'relation.field': value
重要:上記の演算子マップは、現時点で Instant がサポートする where フィルターのすべてです。$exists、$nin、$regex はありません。また、startsWith/endsWith/includes には $like と $ilike を使用します。
重要:ページネーションキー(limit、offset、first、after、last、before)は、トップレベルの名前空間でのみ機能します。ネストされたリレーションでは使用しないでください。使用するとエラーが発生します。
重要:InstantDB の仕組みがわからない場合は、ドキュメントで関連する URL を取得して確認してください。
重要な権限のガイドライン
以下は、InstantDB の権限を記述する際の重要なガイドラインです。
data.ref
- リンクされた属性には
data.ref("<path.to.attr>")を使用します。 - 常にリストを返します。
- 属性で終わる必要があります。
正しい例
auth.id in data.ref('post.author.id') // auth.id in list of author ids
data.ref('owner.id') == [] // there is no owner
エラーになる例
auth.id in data.post.author.id
auth.id in data.ref('author')
data.ref('admins.id') == auth.id
auth.id == data.ref('owner.id')
data.ref('owner.id') == null
data.ref('owner.id').length > 0
auth.ref
data.refと同じですが、パスは$userで始まる必要があります。- リストを返します。
正しい例
'admin' in auth.ref('$user.role.type')
auth.ref('$user.role.type')[0] == 'admin'
エラーになる例
auth.ref('role.type')
auth.ref('$user.role.type') == 'admin'
サポート対象外
newData.ref('x')
data.ref(someVar + '.members.id')
$users の権限
- デフォルトの
view権限はauth.id == data.idです - デフォルトの
updateおよびdelete権限は false です - デフォルトの
create権限は true です(誰でもサインアップできます) view、update、createは上書きできますdeleteは上書きできませんcreateルールは認証のサインアップフロー中に実行されます(transact経由ではありません)。サインアップの制限やextraFieldsの検証に使用します。extraFieldsを使うには、明示的なcreateルールが必要です。設定しない場合、未検証の書き込みを防ぐためサインアップはブロックされます。
$files の権限
- デフォルトではすべての権限が false です。アクセスを許可するには、必要に応じて上書きしてください。
$filesの権限ではdata.refは機能しません。- パスに基づくルールを記述するには、
data.path.startsWith(...)またはdata.path.endsWith(...)を使用します。
フィールドレベルの権限
エンティティを公開したまま、特定のフィールドへのアクセスを制限します。
{
"$users": {
"allow": {
"view": "true"
},
"fields": {
"email": "auth.id == data.id"
}
}
}
注意事項:
- フィールドのルールは、そのフィールドに対するエンティティレベルの
viewを上書きします - 公開エンティティ上の機密データ(メールアドレス、電話番号など)を非表示にするのに便利です
重要なストレージのガイドライン
重要:アプリで画像やファイルを表示する場合は、Instant Storage を使用してください。エンティティの属性に URL を文字列として保存しないでください。これにはシードスクリプトも含まれます。ファイルのサポートを装うために、プレースホルダー画像の URL(例:picsum.photos)を文字列属性として使用しないでください。
アップロードすると $files エンティティが自動的に作成されます。スキーマを通じてデータに関連付けてから、リレーションシップ経由でクエリし、URL を取得します。
重要:Storage を使用する場合は、必ずスキーマのエンティティに $files を含めてください。
重要:$files エンティティは db.storage.uploadFile 経由でのみ作成できます。db.transact 経由で $files を作成することはできず、トランザクション経由で url を設定することもできません。
entities: {
$files: i.entity({
path: i.string().unique().indexed(),
url: i.string(),
}),
posts: i.entity({
caption: i.string(),
}),
},
links: {
postImage: {
forward: { on: "posts", has: "one", label: "image" },
reverse: { on: "$files", has: "many", label: "posts" },
},
}
// Upload and link the returned file ID to your entity
const postId = id();
const { data } = await db.storage.uploadFile(`posts/${postId}/${file.name}`, file);
db.transact(
db.tx.posts[postId].update({ caption }).link({ image: data.id })
);
// Query through the relationship to get the URL
const { data } = db.useQuery({ posts: { image: {} } });
<img src={post.image.url} />
重要な Rooms のガイドライン
重要:プレゼンスとトピックのフックは db.rooms にあり、最初の引数としてルームを受け取ります。ルームオブジェクト自体には usePresence メソッドも publishPresence メソッドもありません。
Rooms は、プレゼンス(カーソル位置、オンライン中のユーザー)とトピック(リアルタイムのリアクション)という、2 種類のエフェメラルなプリミティブを提供します。永続化する必要のないデータにのみ使用してください。transact 経由で永続化されたデータは、すでにサブスクライブ中のすべてのクライアントにリアルタイムで同期されるため、意図的にエフェメラルにするデータに限って Rooms を使用してください。
プレゼンス
各ピアは、ルーム内の他のすべてのピアが読み取れるプレゼンスオブジェクトを公開します。接続中は保持され、切断時に自動的にクリーンアップされます。
const room = db.room('chat', 'main');
const { user, peers, publishPresence } = db.rooms.usePresence(room, {
initialPresence: { x: 0, y: 0 },
});
// peers is keyed by peerId, not an array. Use Object.values(peers) to iterate
publishPresence({ x: 50, y: 50 });
トピック
トピックのペイロードは保持されません。ピアが確認できるのは、リッスン中に発生したイベントのみです。
const room = db.room('chat', 'main');
const publishEmoji = db.rooms.usePublishTopic(room, 'emoji');
publishEmoji({ name: 'fire' });
db.rooms.useTopicEffect(room, 'emoji', (payload) => {
animateEmoji(payload.name);
});
ベストプラクティス
Instant の初期化時に schema を渡す
クエリとトランザクションの型安全性を確保するため、Instant の初期化時には必ず schema を渡してください。
import schema from '@/instant.schema';
// On client
import { init } from '@instantdb/react'; // or your relevant Instant SDK
const clientDb = init({ appId, schema });
// On backend
import { init } from '@instantdb/admin';
const adminDb = init({ appId, adminToken, schema });
ID の生成には id() を使用する
新しいエンティティの ID は必ず id() で生成してください。
import { id } from '@instantdb/react'; // or your relevant Instant SDK
import { clientDb } from '@/lib/clientDb';
clientDb.transact(clientDb.tx.todos[id()].create({ title: 'New Todo' }));
データモデルには Instant のユーティリティ型を使用する
データモデルの型付けには、必ず Instant のユーティリティ型を使用してください。
import { AppSchema } from '@/instant.schema';
type Todo = InstaQLEntity<AppSchema, 'todos'>; // todo from clientDb.useQuery({ todos: {} })
type PostsWithProfile = InstaQLEntity<
AppSchema,
'posts',
{ author: { avatar: {} } }
>; // post from clientDb.useQuery({ posts: { author: { avatar: {} } } })
認証状態には db.useAuth または db.subscribeAuth を使用する
import { clientDb } from '@/lib/clientDb';
// For react/react-native apps use db.useAuth
function App() {
const { isLoading, user, error } = clientDb.useAuth();
if (isLoading) {
return null;
}
if (error) {
return <Error message={error.message} />;
}
if (user) {
return <Main />;
}
return <Login />;
}
// For vanilla JS apps use db.subscribeAuth
function App() {
renderLoading();
db.subscribeAuth((auth) => {
if (auth.error) {
renderAuthError(auth.error.message);
} else if (auth.user) {
renderLoggedInPage(auth.user);
} else {
renderSignInPage();
}
});
}
extraFields を使ってサインアップ時にカスタムプロパティを設定する
サインインメソッドには extraFields を渡すことで、ユーザー作成時にカスタムの $users プロパティをアトミックに書き込めます。
フィールドはスキーマ内の $users で、オプションの attrs として定義する必要があります。
新規ユーザーのデータを作成するには、created ブール値を使用します。
// Set properties at signup
const { user, created } = await db.auth.signInWithMagicCode({
email,
code,
extraFields: { nickname, createdAt: Date.now() },
});
// Scaffold data for new users
if (created) {
db.transact([
db.tx.settings[id()]
.update({ theme: 'light', notifications: true })
.link({ user: user.id }),
]);
}
CLI からのアドホッククエリ
npx instant-cli query '{ posts: {} }' --admin を実行して、アプリにクエリを実行します。コンテキストフラグが必須です:--admin、--as-email <email>、または --as-guest。--app <id> にも対応しています。
Instant ドキュメント
以下は Instant のドキュメントへのリンクです。InstantDB のさまざまな機能の使い方について、詳しく説明しています。各行は次の形式です。
- トピック:トピックの説明。
トピックの URL を取得して、詳しい情報を確認してください。
- よくある間違い:Instant を使用する際によくある間違い
- Instant の初期化:Instant をアプリに統合する方法です。
- データのモデリング:Instant のスキーマでデータをモデル化する方法です。
- データの書き込み:InstaML を使って Instant でデータを書き込む方法です。
- データの読み取り:InstaQL を使って Instant でデータを読み取る方法です。
- バックエンドでの Instant の利用:Admin SDK を使ってサーバー上で Instant を利用する方法です。
- パターン:InstantDB を使用する際によくあるパターンです。
- 認証:Instant アプリにマジックコード認証を追加する方法です。
- ゲスト認証:Instant アプリにゲスト認証を追加する方法です。
- その他の認証:Instant がサポートするその他の認証方法です。
- ユーザーの管理:Instant アプリでユーザーを管理する方法です。
- プレゼンス、カーソル、アクティビティ:Instant アプリにプレゼンスやカーソルなどの一時的な機能を追加する方法です。
- Instant CLI:Instant CLI を使ってスキーマを管理する方法です。
- ストレージ:Instant でファイルをアップロードして配信する方法です。
- ストリーム:Instant でストリームを使用する方法です。
- Stripe 決済:Stripe 決済を Instant に統合する方法です。
- React Native:React Native アプリで Instant を使用する方法です。
- Vanilla JS:Vanilla JS アプリで Instant を使用する方法です。
- SolidJS:SolidJS アプリで Instant を使用する方法です。
- Svelte:Svelte アプリで Instant を使用する方法です。
- Vue:Vue アプリで Instant を使用する方法です。
- TanStack:TanStack アプリで Instant を使用する方法です。
- Python:Python で Instant を使用する方法です。
最後に
回答する前によく考えてください。コードが型チェック tsc --noEmit を通過し、期待どおりに動作することを確認してください。
忘れないでください!見た目は非常に重要です。すべてのアプリは素晴らしい見た目と優れた機能を備えている必要があります!