algolia-search
Algolia検索の実装に関する専門的なパターンを提供し、インデックス戦略、React InstantSearch の活用、検索結果のレレバンスチューニングまでを網羅します。検索機能の設計・最適化を行う際に活用できます。
description の原文を見る
Expert patterns for Algolia search implementation, indexing strategies, React InstantSearch, and relevance tuning
SKILL.md 本文
Algolia検索統合
Algolia検索実装、インデックス戦略、React InstantSearch、関連性チューニングの専門パターン
パターン
React InstantSearch with Hooks
Hooksを使用した最新のReact InstantSearchセットアップで、タイプアヘッド検索に対応しています。
react-instantsearch-hooks-webパッケージとalgoliasearchクライアントを使用します。 ウィジェットはclassNamesでカスタマイズできるコンポーネントです。
主要なhooks:
- useSearchBox: 検索入力の処理
- useHits: 検索結果へのアクセス
- useRefinementList: ファセットフィルタリング
- usePagination: 結果ページネーション
- useInstantSearch: 完全な状態アクセス
Code_example
// lib/algolia.ts
import algoliasearch from 'algoliasearch/lite';
export const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY! // Search-only key!
);
export const INDEX_NAME = 'products';
// components/Search.tsx
'use client';
import { InstantSearch, SearchBox, Hits, Configure } from 'react-instantsearch';
import { searchClient, INDEX_NAME } from '@/lib/algolia';
function Hit({ hit }: { hit: ProductHit }) {
return (
<article>
<h3>{hit.name}</h3>
<p>{hit.description}</p>
<span>${hit.price}</span>
</article>
);
}
export function ProductSearch() {
return (
<InstantSearch searchClient={searchClient} indexName={INDEX_NAME}>
<Configure hitsPerPage={20} />
<SearchBox
placeholder="Search products..."
classNames={{
root: 'relative',
input: 'w-full px-4 py-2 border rounded',
}}
/>
<Hits hitComponent={Hit} />
</InstantSearch>
);
}
// Custom hook usage
import { useSearchBox, useHits, useInstantSearch } from 'react-instantsearch';
function CustomSearch() {
const { query, refine } = useSearchBox();
const { hits } = useHits<ProductHit>();
const { status } = useInstantSearch();
return (
<div>
<input
value={query}
onChange={(e) => refine(e.target.value)}
placeholder="Search..."
/>
{status === 'loading' && <p>Loading...</p>}
<ul>
{hits.map((hit) => (
<li key={hit.objectID}>{hit.name}</li>
))}
</ul>
</div>
);
}
Anti_patterns
- パターン: フロントエンドコードでAdmin APIキーを使用 | 理由: 管理キーはインデックス削除を含む全制御を公開 | 修正: 制限付きの検索専用APIキーを使用
- パターン: /liteクライアントを使用しない | 理由: 完全なクライアントは検索に不要なコードを含む | 修正: algoliasearch/liteからインポートしてバンドルサイズを削減
References
- https://www.algolia.com/doc/api-reference/widgets/react
- https://www.algolia.com/doc/libraries/javascript/v5/methods/search/
Next.js サーバーサイドレンダリング
react-instantsearch-nextjsパッケージを使用したNext.jsとのSSR統合。
<InstantSearch>の代わりに<InstantSearchNext>を使用します。 Pages RouterとApp Router(実験的)の両方に対応しています。
主要な考慮事項:
- dynamic = 'force-dynamic'で新鮮な結果を取得
- routingプロップでURLの同期を処理
- 初期状態にgetServerStateを使用
Code_example
// app/search/page.tsx
import { InstantSearchNext } from 'react-instantsearch-nextjs';
import { searchClient, INDEX_NAME } from '@/lib/algolia';
import { SearchBox, Hits, RefinementList } from 'react-instantsearch';
// Force dynamic rendering for fresh search results
export const dynamic = 'force-dynamic';
export default function SearchPage() {
return (
<InstantSearchNext
searchClient={searchClient}
indexName={INDEX_NAME}
routing={{
router: {
cleanUrlOnDispose: false,
},
}}
>
<div className="flex gap-8">
<aside className="w-64">
<h3>Categories</h3>
<RefinementList attribute="category" />
<h3>Brand</h3>
<RefinementList attribute="brand" />
</aside>
<main className="flex-1">
<SearchBox placeholder="Search products..." />
<Hits hitComponent={ProductHit} />
</main>
</div>
</InstantSearchNext>
);
}
// For custom routing (URL synchronization)
import { history } from 'instantsearch.js/es/lib/routers';
import { simple } from 'instantsearch.js/es/lib/stateMappings';
<InstantSearchNext
searchClient={searchClient}
indexName={INDEX_NAME}
routing={{
router: history({
getLocation: () =>
typeof window === 'undefined'
? new URL(url) as unknown as Location
: window.location,
}),
stateMapping: simple(),
}}
>
{/* widgets */}
</InstantSearchNext>
Anti_patterns
- パターン: Next.js SSRに通常のInstantSearchコンポーネントを使用 | 理由: 通常のコンポーネントはサーバーサイドレンダリングをサポートしない | 修正: react-instantsearch-nextjsのInstantSearchNextを使用
- パターン: 検索ページに静的レンダリング | 理由: 検索結果は各リクエストで新鮮である必要がある | 修正: export const dynamic = 'force-dynamic'を設定
References
- https://www.npmjs.com/package/react-instantsearch-nextjs
- https://www.algolia.com/developers/code-exchange/instantsearch-and-next-js-starter
データ同期とインデックス処理
Algoliaをデータと同期させておくためのインデックス戦略。
3つの主要なアプローチ:
- 完全なインデックス再作成 - インデックス全体を置き換え(コスト高)
- 完全なレコード更新 - 個別レコードを置き換え
- 部分更新 - 特定の属性のみ更新
ベストプラクティス:
- レコードをバッチ処理(理想: 10MB、バッチあたり1K~10Kレコード)
- 可能な場合は段階的更新を使用
- 属性のみの変更にpartialUpdateObjectsを使用
- deleteByを避ける(計算コスト高)
Code_example
// lib/algolia-admin.ts (SERVER ONLY)
import algoliasearch from 'algoliasearch';
// Admin client - NEVER expose to frontend
const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY! // Admin key for indexing
);
const index = adminClient.initIndex('products');
// Batch indexing (recommended approach)
export async function indexProducts(products: Product[]) {
const records = products.map((p) => ({
objectID: p.id, // Required unique identifier
name: p.name,
description: p.description,
price: p.price,
category: p.category,
inStock: p.inventory > 0,
createdAt: p.createdAt.getTime(), // Use timestamps for sorting
}));
// Batch in chunks of ~1000-5000 records
const BATCH_SIZE = 1000;
for (let i = 0; i < records.length; i += BATCH_SIZE) {
const batch = records.slice(i, i + BATCH_SIZE);
await index.saveObjects(batch);
}
}
// Partial update - update only specific fields
export async function updateProductPrice(productId: string, price: number) {
await index.partialUpdateObject({
objectID: productId,
price,
updatedAt: Date.now(),
});
}
// Partial update with operations
export async function incrementViewCount(productId: string) {
await index.partialUpdateObject({
objectID: productId,
viewCount: {
_operation: 'Increment',
value: 1,
},
});
}
// Delete records (prefer this over deleteBy)
export async function deleteProducts(productIds: string[]) {
await index.deleteObjects(productIds);
}
// Full reindex with zero-downtime (atomic swap)
export async function fullReindex(products: Product[]) {
const tempIndex = adminClient.initIndex('products_temp');
// Index to temp index
await tempIndex.saveObjects(
products.map((p) => ({
objectID: p.id,
...p,
}))
);
// Copy settings from main index
await adminClient.copyIndex('products', 'products_temp', {
scope: ['settings', 'synonyms', 'rules'],
});
// Atomic swap
await adminClient.moveIndex('products_temp', 'products');
}
Anti_patterns
- パターン: 大量削除にdeleteByを使用 | 理由: deleteByは計算コストが高く、レート制限がある | 修正: objectIDsの配列でdeleteObjectsを使用
- パターン: 一度に1つのレコードをインデックス処理 | 理由: インデックスキューを作成し、プロセスを遅くする | 修正: 1K~10Kのグループでレコードをバッチ処理
- パターン: 小さな変更に完全なインデックス再作成 | 理由: 操作を浪費し、段階的更新より遅い | 修正: 属性変更にpartialUpdateObjectを使用
References
- https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/in-depth/the-different-synchronization-strategies
- https://www.algolia.com/blog/engineering/search-indexing-best-practices-for-top-performance-with-code-samples
APIキーセキュリティと制限
Algoliaの安全なAPIキー設定。
キーの種類:
- Admin APIキー: 完全な制御(インデックス処理、設定、削除)
- 検索専用APIキー: フロントエンドに安全
- セキュリティキー: ベースキーから制限付きで生成
利用可能な制限:
- インデックス: アクセス可能なインデックスを制限
- レート制限: IPごと1時間あたりのAPI呼び出しを制限
- 有効期限: 有効期限を設定
- HTTPリファラー: 特定のURLに制限
- クエリパラメータ: 検索パラメータを強制
Code_example
// NEVER do this - admin key in frontend
// const client = algoliasearch(appId, ADMIN_KEY); // WRONG!
// Correct: Use search-only key in frontend
const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);
// Server-side: Generate secured API key
// lib/algolia-secured-key.ts
import algoliasearch from 'algoliasearch';
const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY!
);
// Generate user-specific secured key
export function generateSecuredKey(userId: string) {
const searchKey = process.env.ALGOLIA_SEARCH_KEY!;
return adminClient.generateSecuredApiKey(searchKey, {
// User can only see their own data
filters: `userId:${userId}`,
// Key expires in 1 hour
validUntil: Math.floor(Date.now() / 1000) + 3600,
// Restrict to specific index
restrictIndices: ['user_documents'],
});
}
// Rate-limited key for public APIs
export async function createRateLimitedKey() {
const { key } = await adminClient.addApiKey({
acl: ['search'],
indexes: ['products'],
description: 'Public search with rate limit',
maxQueriesPerIPPerHour: 1000,
referers: ['https://mysite.com/*'],
validity: 0, // Never expires
});
return key;
}
// API endpoint to get user's secured key
// app/api/search-key/route.ts
import { auth } from '@/lib/auth';
import { generateSecuredKey } from '@/lib/algolia-secured-key';
export async function GET() {
const session = await auth();
if (!session?.user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
const securedKey = generateSecuredKey(session.user.id);
return Response.json({ key: securedKey });
}
Anti_patterns
- パターン: クライアントコードに管理APIキーをハードコード | 理由: 攻撃者に完全なインデックス制御を公開 | 修正: 制限付きの検索専用キーを使用
- パターン: すべてのユーザーに同じキーを使用 | 理由: ユーザーごとのデータアクセスを制限できない | 修正: ユーザーフィルター付きのセキュリティキーを生成
- パターン: 公開検索にレート制限がない | 理由: ボットが検索クォータを枯渇させる可能性 | 修正: APIキーにmaxQueriesPerIPPerHourを設定
References
- https://www.algolia.com/doc/guides/security/api-keys
- https://support.algolia.com/hc/en-us/articles/14339249272977-What-are-the-best-practices-to-manage-Algolia-API-keys-in-my-code-and-protect-them
カスタムランキングと関連性チューニング
関連性のための検索可能属性とカスタムランキングを設定します。
検索可能属性(順序が重要):
- 最も重要なフィールド(タイトル、名前)
- 次に重要なフィールド(説明、タグ)
- 検索不可フィールドを除外(image_url、id)
カスタムランキング:
- ビジネスメトリクスを追加(人気度、評価、日付)
- 降順にはdesc()、昇順にはasc()を使用
Code_example
// scripts/configure-index.ts
import algoliasearch from 'algoliasearch';
const adminClient = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_ADMIN_KEY!
);
const index = adminClient.initIndex('products');
async function configureIndex() {
await index.setSettings({
// Searchable attributes in order of importance
searchableAttributes: [
'name', // Most important
'brand',
'category',
'description', // Least important
],
// Attributes for faceting/filtering
attributesForFaceting: [
'category',
'brand',
'filterOnly(inStock)', // Filter only, not displayed
'searchable(tags)', // Searchable facet
],
// Custom ranking (after text relevance)
customRanking: [
'desc(popularity)', // Most popular first
'desc(rating)', // Then by rating
'desc(createdAt)', // Then by recency
],
// Typo tolerance
typoTolerance: true,
minWordSizefor1Typo: 4,
minWordSizefor2Typos: 8,
// Query settings
queryLanguages: ['en'],
removeStopWords: ['en'],
// Highlighting
attributesToHighlight: ['name', 'description'],
highlightPreTag: '<mark>',
highlightPostTag: '</mark>',
// Pagination
hitsPerPage: 20,
paginationLimitedTo: 1000,
// Distinct (deduplication)
attributeForDistinct: 'productFamily',
distinct: true,
});
// Add synonyms
await index.saveSynonyms([
{
objectID: 'phone-mobile',
type: 'synonym',
synonyms: ['phone', 'mobile', 'cell', 'smartphone'],
},
{
objectID: 'laptop-notebook',
type: 'oneWaySynonym',
input: 'laptop',
synonyms: ['notebook', 'portable computer'],
},
]);
// Add rules (query-based customization)
await index.saveRules([
{
objectID: 'boost-sale-items',
condition: {
anchoring: 'contains',
pattern: 'sale',
},
consequence: {
params: {
filters: 'onSale:true',
optionalFilters: ['featured:true'],
},
},
},
]);
console.log('Index configured successfully');
}
configureIndex();
Anti_patterns
- パターン: すべての属性を同等に検索 | 理由: 関連性を低下させ、説明内のマッチがタイトルと同じランクになる | 修正: searchableAttributesを重要度順に並べる
- パターン: カスタムランキングなし | 理由: テキストマッチのみに依存し、ビジネス価値を無視 | 修正: customRankingに人気度、評価、または最新性を追加
- パターン: 生の日付を文字列としてインデックス処理 | 理由: 日付でのソートが正しく実行されない | 修正: 日付ソート用にタイムスタンプ(getTime())を使用
References
- https://www.algolia.com/doc/guides/managing-results/relevance-overview
- https://www.algolia.com/doc/guides/managing-results/must-do/custom-ranking
ファセット検索とフィルタリング
リファインメントリスト、範囲スライダー、階層メニューを使用したファセット型ナビゲーション実装。
ウィジェットの種類:
- RefinementList: 複数選択チェックボックス
- Menu: 単一選択リスト
- HierarchicalMenu: ネストされたカテゴリ
- RangeInput/RangeSlider: 数値範囲
- ToggleRefinement: ブール値フィルター
Code_example
'use client';
import {
InstantSearch,
SearchBox,
Hits,
RefinementList,
HierarchicalMenu,
RangeInput,
ToggleRefinement,
ClearRefinements,
CurrentRefinements,
Stats,
SortBy,
} from 'react-instantsearch';
import { searchClient, INDEX_NAME } from '@/lib/algolia';
export function ProductSearch() {
return (
<InstantSearch searchClient={searchClient} indexName={INDEX_NAME}>
<div className="flex gap-8">
{/* Filters Sidebar */}
<aside className="w-64 space-y-6">
<ClearRefinements />
<CurrentRefinements />
{/* Category hierarchy */}
<div>
<h3 className="font-semibold mb-2">Categories</h3>
<HierarchicalMenu
attributes={[
'categories.lvl0',
'categories.lvl1',
'categories.lvl2',
]}
limit={10}
showMore
/>
</div>
{/* Brand filter */}
<div>
<h3 className="font-semibold mb-2">Brand</h3>
<RefinementList
attribute="brand"
searchable
searchablePlaceholder="Search brands..."
showMore
limit={5}
showMoreLimit={20}
/>
</div>
{/* Price range */}
<div>
<h3 className="font-semibold mb-2">Price</h3>
<RangeInput
attribute="price"
precision={0}
classNames={{
input: 'w-20 px-2 py-1 border rounded',
}}
/>
</div>
{/* In stock toggle */}
<ToggleRefinement
attribute="inStock"
label="In Stock Only"
on={true}
/>
{/* Rating filter */}
<div>
<h3 className="font-semibold mb-2">Rating</h3>
<RefinementList
attribute="rating"
transformItems={(items) =>
items.map((item) => ({
...item,
label: '★'.repeat(Number(item.label)),
}))
}
/>
</div>
</aside>
{/* Results */}
<main className="flex-1">
<div className="flex justify-between items-center mb-4">
<SearchBox placeholder="Search products..." />
<SortBy
items={[
{ label: 'Relevance', value: 'products' },
{ label: 'Price (Low to High)', value: 'products_price_asc' },
{ label: 'Price (High to Low)', value: 'products_price_desc' },
{ label: 'Rating', value: 'products_rating_desc' },
]}
/>
</div>
<Stats />
<Hits hitComponent={ProductHit} />
</main>
</div>
</InstantSearch>
);
}
// For sorting, create replica indices
// products_price_asc: customRanking: ['asc(price)']
// products_price_desc: customRanking: ['desc(price)']
// products_rating_desc: customRanking: ['desc(rating)']
Anti_patterns
- パターン: ファセット属性でないものをファセット処理 | 理由: attributesForFacetingで属性を宣言する必要がある | 修正: attributesForFaceting配列に属性を追加
- パターン: filterOnly()を非表示フィルターに使用しない | 理由: 表示されないフィルターでもファセット計算を無駄にする | 修正: 表示しないフィルターにはfilterOnly(attribute)を使用
References
- https://www.algolia.com/doc/guides/managing-results/refine-results/faceting
- https://www.algolia.com/doc/api-reference/widgets/refinement-list/react
クエリ提案とオートコンプリート
クエリ提案とインスタント結果でオートコンプリートを実装します。
@algolia/autocomplete-jsを使用したスタンドアロンオートコンプリート、またはSearchBoxを使用したInstantSearchとの統合。
クエリ提案にはAlgoliaが生成する別のインデックスが必要です。
Code_example
// Standalone Autocomplete
// components/Autocomplete.tsx
'use client';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';
import algoliasearch from 'algoliasearch/lite';
import { useEffect, useRef } from 'react';
import '@algolia/autocomplete-theme-classic';
const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
);
export function Autocomplete() {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!containerRef.current) return;
const search = autocomplete({
container: containerRef.current,
placeholder: 'Search for products',
openOnFocus: true,
getSources({ query }) {
if (!query) return [];
return [
// Query suggestions
{
sourceId: 'suggestions',
getItems() {
return getAlgoliaResults({
searchClient,
queries: [
{
indexName: 'products_query_suggestions',
query,
params: { hitsPerPage: 5 },
},
],
});
},
templates: {
header() {
return 'Suggestions';
},
item({ item, html }) {
return html`<span>${item.query}</span>`;
},
},
},
// Instant results
{
sourceId: 'products',
getItems() {
return getAlgoliaResults({
searchClient,
queries: [
{
indexName: 'products',
query,
params: { hitsPerPage: 8 },
},
],
});
},
templates: {
header() {
return 'Products';
},
item({ item, html }) {
return html`
<a href="/products/${item.objectID}">
<img src="${item.image}" alt="${item.name}" />
<span>${item.name}</span>
<span>$${item.price}</span>
</a>
`;
},
},
onSelect({ item, setQuery, refresh }) {
// Navigate on selection
window.location.href = `/products/${item.objectID}`;
},
},
];
},
});
return () => search.destroy();
}, []);
return <div ref={containerRef} />;
}
// Combined with InstantSearch
import { connectSearchBox } from 'react-instantsearch';
import { autocomplete } from '@algolia/autocomplete-js';
// Or use built-in Autocomplete widget
import { Autocomplete as AlgoliaAutocomplete } from 'react-instantsearch';
export function SearchWithAutocomplete() {
return (
<InstantSearch searchClient={searchClient} indexName="products">
<AlgoliaAutocomplete
placeholder="Search products..."
detachedMediaQuery="(max-width: 768px)"
/>
<Hits hitComponent={ProductHit} />
</InstantSearch>
);
}
Anti_patterns
- パターン: デバウンスなしでオートコンプリートを作成 | 理由: キーストロークのたびに検索がトリガーされ、操作が無駄になる | 修正: Algoliaオートコンプリートは自動的にデバウンスを処理
- パターン: クエリ提案インデックスなしで使用 | 理由: 一般的なクエリの検索分析を取得できない | 修正: Algoliaダッシュボードでクエリ提案を有効化
References
- https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete
- https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/query-suggestions/how-to/optimizing-query-suggestions-relevance/js
落とし穴
フロントエンドコードの管理APIキー
重大度: CRITICAL
インデックス処理のレート制限とスロットリング
重大度: HIGH
レコードサイズとインデックスの制限
重大度: MEDIUM
ネットワークで表示されるインデックス名のPII
重大度: MEDIUM
検索可能属性の順序が関連性に影響
重大度: MEDIUM
完全なインデックス再作成がすべての操作を消費
重大度: MEDIUM
キーストロークごとに検索操作として計数
重大度: MEDIUM
InstantSearchのSSRハイドレーションのミスマッチ
重大度: MEDIUM
ソート用レプリカインデックスが保存領域を増加
重大度: LOW
ファセット処理にはattributesForFaceting宣言が必須
重大度: MEDIUM
検証チェック
クライアントコードの管理APIキー
重大度: ERROR
管理APIキーをクライアント側のコードに公開してはいけません
メッセージ: 管理APIキーがクライアントに公開されています。検索専用キーを使用してください。
ハードコードされたAlgolia APIキー
重大度: ERROR
APIキーは環境変数を使用すべきです
メッセージ: Algolia認証情報がハードコードされています。環境変数を使用してください。
インデックス処理に使用された検索キー
重大度: ERROR
インデックス処理には管理キーが必要で、検索キーではありません
メッセージ: 検索キーでインデックス処理が実行されています。書き込み操作には管理キーを使用してください。
ループ内の単一レコードインデックス処理
重大度: WARNING
効率的なインデックス処理のためにレコードをバッチ処理します
メッセージ: ループ内で単一レコードをインデックス処理しています。バッチインデックス処理にはsaveObjectsを使用してください。
deleteByの削除に使用
重大度: WARNING
deleteByは高コストでレート制限があります
メッセージ: deleteByは高コストです。特定のIDでdeleteObjectsを使用することを推奨します。
頻繁な完全なインデックス再作成
重大度: WARNING
完全なインデックス再作成は変更されていないデータで操作を無駄にします
メッセージ: 完全なインデックス再作成が頻繁です。変更されていないデータは段階的な同期を検討してください。
完全なクライアントの使用 vs Lite
重大度: INFO
フロントエンドの小さなバンドルサイズにはliteクライアントを使用
メッセージ: 完全なAlgoliaクライアントがインポートされています。フロントエンドではalgoliasearch/liteを使用してください。
Next.jsの通常のInstantSearch
重大度: WARNING
SSRサポートにはreact-instantsearch-nextjsを使用
メッセージ: 通常のInstantSearchを使用しています。Next.js SSRにはInstantSearchNextを使用してください。
検索可能属性の設定がない
重大度: WARNING
関連性を向上させるため、searchableAttributesを設定してください
メッセージ: searchableAttributesが設定されていません。関連性のため属性の優先度を設定してください。
カスタムランキングの設定がない
重大度: INFO
カスタムランキングはビジネス関連性を向上させます
メッセージ: customRankingが設定されていません。ビジネスメトリクス(人気度、評価)を追加してください。
コラボレーション
デリゲーショントリガー
- ユーザーが電子商取引チェックアウトが必要 -> stripe-integration(製品検索から購入へ)
- ユーザーが検索分析が必要 -> segment-cdp(検索クエリと結果の追跡)
- ユーザーがユーザー認証が必要 -> clerk-auth(ユーザーごとのセキュリティキー)
- ユーザーがデータベース設定が必要 -> postgres-wizard(インデックス処理のソースデータ)
- ユーザーがサーバーレス展開が必要 -> aws-serverless(インデックス処理ジョブ用Lambda)
使用する場合
- ユーザーが以下を言及または暗示: 検索を追加する
- ユーザーが以下を言及または暗示: algolia
- ユーザーが以下を言及または暗示: instantsearch
- ユーザーが以下を言及または暗示: search api
- ユーザーが以下を言及または暗示: 検索機能
- ユーザーが以下を言及または暗示: typeahead
- ユーザーが以下を言及または暗示: オートコンプリート検索
- ユーザーが以下を言及または暗示: ファセット検索
- ユーザーが以下を言及または暗示: 検索インデックス
- ユーザーが以下を言及または暗示: 入力時の検索
制限事項
- このスキルは上記で説明したスコープと明確に一致する場合にのみ使用してください。
- 出力を環境固有の検証、テスト、または専門家によるレビューの代替と見なさないでください。
- 必要な入力、権限、安全境界、または成功基準が不明な場合は、停止して明確化を求めてください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- sickn33
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/sickn33/antigravity-awesome-skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。