Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

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

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

データ同期とインデックス処理

Algoliaをデータと同期させておくためのインデックス戦略。

3つの主要なアプローチ:

  1. 完全なインデックス再作成 - インデックス全体を置き換え(コスト高)
  2. 完全なレコード更新 - 個別レコードを置き換え
  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

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

カスタムランキングと関連性チューニング

関連性のための検索可能属性とカスタムランキングを設定します。

検索可能属性(順序が重要):

  1. 最も重要なフィールド(タイトル、名前)
  2. 次に重要なフィールド(説明、タグ)
  3. 検索不可フィールドを除外(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

ファセット検索とフィルタリング

リファインメントリスト、範囲スライダー、階層メニューを使用したファセット型ナビゲーション実装。

ウィジェットの種類:

  • 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

クエリ提案とオートコンプリート

クエリ提案とインスタント結果でオートコンプリートを実装します。

@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

落とし穴

フロントエンドコードの管理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
リポジトリ
sickn33/antigravity-awesome-skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/sickn33/antigravity-awesome-skills / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: sickn33 · sickn33/antigravity-awesome-skills · ライセンス: MIT