instantdb
InstantDBをバックエンドとして、完全に機能するアプリケーションを構築できます。React、バニラJS、またはExpoアプリケーションを作成する際に使用します。アプリ構築のリクエストで自動的に起動します。
description の原文を見る
Build complete, functional apps with InstantDB as the backend. Use when creating React/vanilla JS or expo applications. Triggers on requests for building apps.
SKILL.md 本文
InstantDBに深い専門知識を持つワールドクラスのシニアフロントエンドエンジニアとして行動してください。バックエンドとしてInstantDBを使用し、優れたビジュアルエステティクスを備えた完全で機能的なアプリを生成することが主な目標です。
InstantDB(別名Instant)について
Instantは、クライアント側のデータベース(モダンFirebase)で、ビルトインクエリ、トランザクション、認証、権限、ストレージ、リアルタイム、およびオフラインサポートを備えています。
Instant SDK
Instantはクライアント側のJavaScript SDKと管理SDKを提供します:
@instantdb/core--- バニラJS@instantdb/react--- React@instantdb/react-native--- React Native / Expo@instantdb/admin--- バックエンドスクリプト / サーバー
インストール時は、常にプロジェクトが使用しているパッケージマネージャー(npm、pnpm、bun)を確認してから、Instant SDKの最新バージョンをインストールしてください。Reactで作業する場合は、特に指定されていない限りNextとTailwindを使用してください。
Instantアプリの管理
前提条件
instant.schema.ts と instant.perms.ts を探してください。これらはスキーマと権限を定義します。
.env または別の環境ファイルでアプリIDと管理トークンを探してください。
スキーマ/権限ファイルは存在するがアプリID/管理トークンが見つからない場合は、ユーザーにそれらをどこで見つけるか、または新しいアプリを作成するかを尋ねてください。
新しいアプリを作成するには:
npx instant-cli init-without-files --title <APP_NAME>
これでアプリIDと管理トークンが出力されます。これらを環境ファイルに保存してください。
ログインしていないことに関連するエラーが発生した場合は、ユーザーに以下を実行するよう指示してください:
- https://instantdb.com で無料登録またはログイン
- 次に
npx instant-cli loginを実行してCLIを認証 - その後、初期化コマンドを再実行
アプリ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を使用する場合は、フックのルールに従うようにしてください。フックは条件付きで表示することはできません。
重要:スキーマで、フィルター処理またはソート処理する任意のフィールドにインデックスを付ける必要があります。そうしないと、フィルター処理またはソート処理を試みるときにエラーが発生します。
以下がソートの仕組みです:
ソート: order: { field: 'asc' | 'desc' }
例: $: { order: { dueDate: 'asc' } }
注: - フィールドはスキーマでインデックス付き + 型指定される必要があります
- ネストされた属性でソートできません(例:'owner.name')
重要:以下は、InstantDBクエリで使用できるすべてのフィルタリングオプションを定義する where オペレーターマップの簡潔なサマリーです。フィールド値、比較、配列、テキストパターン、および論理条件に基づいて結果を絞り込みます。
等価性: { field: value }
不等号: { field: { $ne: value } }
Nullチェック: { field: { $isNull: true | false } }
比較: $gt, $lt, $gte, $lte (インデックス付き + 型指定フィールドのみ)
セット: { field: { $in: [v1, v2] } }
部分文字列: { field: { $like: 'Get%' } } // 大文字小文字を区別
{ field: { $ilike: '%get%' } } // 大文字小文字を区別しない
論理: and: [ {...}, {...} ]
or: [ {...}, {...} ]
ネストされたフィールド: 'relation.field': value
重要:上記のオペレーターマップは、現在Instantがサポートしている where フィルターの完全なセットです。$exists、$nin、または $regex はありません。また $like と $ilike は startsWith / endsWith / includes に使用するものです。
重要:ページネーションキー(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が著者idのリスト内にある
data.ref('owner.id') == [] // オーナーがいない
エラー例
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 - デフォルトの
create、update、delete権限はfalse viewとupdateをオーバーライドできますcreateとdeleteをオーバーライドできません
$files の権限
- デフォルト権限はすべてfalse。必要に応じてオーバーライドしてアクセスを許可してください。
data.refは$files権限では機能しません。data.path.startsWith(...)またはdata.path.endsWith(...)を使用して、 パスベースのルールを書いてください。
フィールドレベルの権限
エンティティが公開されている間、特定のフィールドへのアクセスを制限します:
{
"$users": {
"allow": {
"view": "true"
},
"fields": {
"email": "auth.id == data.id"
}
}
}
注:
- フィールドルールは、そのフィールドに対するエンティティレベルの
viewをオーバーライドします - 公開エンティティの機密データ(メール、電話番号)を非表示にするのに役立ちます
ベストプラクティス
Instantの初期化時に schema を渡す
クエリとトランザクションのタイプセーフティを確保するために、Instantの初期化時に常に schema を渡してください
import schema from '@/instant.schema`
// クライアント側
import { init } from '@instantdb/react'; // または関連するInstant SDK
const clientDb = init({ appId, schema });
// バックエンド側
import { init } from '@instantdb/admin';
const adminDb = init({ appId, adminToken, schema });
id() を使用してIDを生成する
新しいエンティティのIDを生成するために常に id() を使用してください
import { id } from '@instantdb/react'; // または関連する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'>; // clientDb.useQuery({ todos: {} }) からのtodo
type PostsWithProfile = InstaQLEntity<
AppSchema,
'posts',
{ author: { avatar: {} } }
>; // clientDb.useQuery({ posts: { author: { avatar: {} } } }) からのpost
認証状態に db.useAuth または db.subscribeAuth を使用する
import { clientDb } from '@/lib/clientDb';
// React/React Nativeアプリの場合は db.useAuth を使用
function App() {
const { isLoading, user, error } = clientDb.useAuth();
if (isLoading) { return null; }
if (error) { return <Error message={error.message /}></div>; }
if (user) { return <Main />; }
return <Login />;
}
// バニラJSアプリの場合は db.subscribeAuth を使用
function App() {
renderLoading();
db.subscribeAuth((auth) => {
if (auth.error) { renderAuthError(auth.error.message); }
else if (auth.user) { renderLoggedInPage(auth.user); }
else { renderSignInPage(); }
});
}
CLIからのアドホッククエリ
npx instant-cli query '{ posts: {} }' --admin を実行してアプリをクエリします。コンテキストフラグが必須です:--admin、--as-email <email>、または --as-guest。また --app <id> もサポートしています。
Admin SDKを使用したアドホックスクリプト
バックエンド上でアドホックスクリプトを実行するには @instantdb/admin を使用してください。
以下はチャットアプリのスキーマの例であり、シードおよびリセットスクリプトが含まれています。
// instant.schema.ts
const _schema = i.schema({
entities: {
$users: i.entity({
email: i.string().unique().indexed().optional(),
}),
profiles: i.entity({
displayName: i.string(),
}),
channels: i.entity({
name: i.string().indexed(),
}),
messages: i.entity({
content: i.string(),
timestamp: i.number().indexed(),
}),
},
links: {
userProfile: {
forward: { on: "profiles", has: "one", label: "user", onDelete: "cascade" }, // 重要:`cascade` はhas-oneリンクでのみ使用できます
reverse: { on: "$users", has: "one", label: "profile" },
},
authorMessages: {
forward: { on: "messages", has: "one", label: "author", onDelete: "cascade" },
reverse: { on: "profiles", has: "many", label: "messages", },
},
channelMessages: {
forward: { on: "messages", has: "one", label: "channel", onDelete: "cascade" },
reverse: { on: "channels", has: "many", label: "messages" },
},
},
});
// scripts/seed.ts
import { id } from "@instantdb/admin";
import { adminDb } from "@/lib/adminDb";
const users: Record<string, User> = { ... }
const channels: Record<string, Channel> = { ... }
const mockMessages: Message[] = [ ... ]
function seed() {
console.log("Seeding db...");
const userTxs = Object.values(users).map(u => adminDb.tx.$users[u.id].create({}));
const profileTxs = Object.values(users).map(u => adminDb.tx.profiles[u.id].create({ displayName: u.displayName }).link({ user: u.id }));
const channelTxs = Object.values(channels).map(c => adminDb.tx.channels[c.id].create({ name: c.name }))
const messageTxs = mockMessages.map(m => {
const messageId = id();
return adminDb.tx.messages[messageId].create({
content: m.content,
timestamp: m.timestamp,
})
.link({ author: users[m.author].id })
.link({ channel: channels[m.channel].id });
})
adminDb.transact([...userTxs, ...profileTxs, ...channelTxs, ...messageTxs]);
}
seed();
// scripts/reset.ts
import { adminDb } from "@/lib/adminDb";
async function reset() {
console.log("Resetting database...");
const { $users, channels } = await adminDb.query({ $users: {}, channels: {} });
// すべてのユーザーを削除するとプロファイルとメッセージがカスケード削除されます
const userTxs = $users.map(user => adminDb.tx.$users[user.id].delete());
const channelTxs = channels.map(channel => adminDb.tx.channels[channel.id].delete());
adminDb.transact([...userTxs, ...channelTxs]);
}
reset();
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を使用する方法。
- バニラJS:バニラJSアプリでInstantを使用する方法。
- SolidJS:SolidJSアプリでInstantを使用する方法。
- Svelte:SvelteアプリでInstantを使用する方法。
- TanStack:TanStackアプリでInstantを使用する方法。
最後に
答える前に考えてください。コードが tsc --noEmit でタイプチェックを通過し、期待通りに動作することを確認してください。
忘れないでください!エステティクスは非常に重要です。すべてのアプリは素晴らしく見える必要があり、優れた機能性を持つ必要があります!
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- fivestones
- ライセンス
- MIT
- 最終更新
- 2026/4/6
Source: https://github.com/fivestones/family-organizer / ライセンス: MIT