# Search Quick Reference

Fast lookup for search functionality. See `search-api.md` for complete documentation.

## Import & Setup

```typescript
import { useSearch } from "@/composables/useSearch";
import type { SearchableItem, SearchResult } from "@/composables/useSearch";
```

## Basic Usage

```typescript
const { performSearch, results, clearSearch } = useSearch();

// Search templates
performSearch("docker", templates);

// Search templates + stacks
performSearch("nextjs", templates, stacks);

// Check results
console.log(results.value); // SearchResult[]

// Clear search
clearSearch();
```

## SearchResult Structure

```typescript
{
  item: SearchableItem,    // The matched template/stack
  score: number,           // Relevance score (higher = better)
  match: {                 // Fields that matched
    name: ["docker"],      // Highlighted terms per field
    tags: ["docker", "devops"]
  }
}
```

## SearchableItem

```typescript
{
  // Common fields
  id: string,              // "template-0" or "stack-0"
  name: string,            // Item name
  description: string,     // Description text
  itemType: "template" | "stack",  // Discriminator
  type?: string,           // "agent", "command", "mcp", etc
  tags?: string[],         // Keywords
  category?: string,       // Classification

  // Plus all Template/Stack fields
}
```

## Search Configuration

| Setting              | Value      | Purpose                        |
| -------------------- | ---------- | ------------------------------ |
| Min query length     | 2 chars    | No results for < 2             |
| Max results          | 8 items    | Limit results size             |
| Fuzzy (≤3 chars)     | 0.3        | More lenient for short queries |
| Fuzzy (>3 chars)     | 0.2        | Stricter for longer queries    |
| Field: name          | 3x boost   | Highest priority               |
| Field: tags          | 2x boost   | High signal                    |
| Field: category/type | 1.5x boost | Medium                         |
| Field: description   | 1x boost   | Base                           |

## Common Patterns

### Debounced Search (100ms)

```typescript
const query = ref("");
let debounceTimer: ReturnType<typeof setTimeout>;

function handleInput(q: string) {
  query.value = q;
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(() => {
    performSearch(q, templates);
  }, 100);
}
```

### Filter Results by Type

```typescript
const templates = results.value.filter((r) => r.item.itemType === "template");
const stacks = results.value.filter((r) => r.item.itemType === "stack");
```

### Get Top Result

```typescript
const topResult = results.value[0];
if (topResult) {
  console.log(`Best match: ${topResult.item.name} (score: ${topResult.score})`);
}
```

### Check Before Search

```typescript
function search(q: string) {
  if (q.length < 2) {
    clearSearch();
    return;
  }
  performSearch(q, templates);
}
```

## State API

| Ref         | Type           | Purpose                 |
| ----------- | -------------- | ----------------------- |
| query       | string         | Current search query    |
| results     | SearchResult[] | Search results array    |
| isSearching | boolean        | Search in-progress flag |

## Methods

| Method          | Signature                                                    | Purpose                    |
| --------------- | ------------------------------------------------------------ | -------------------------- |
| performSearch   | (q: string, templates: Template[], stacks?: Stack[]) => void | Execute search             |
| clearSearch     | () => void                                                   | Reset query + results      |
| initializeIndex | (templates: Template[], stacks: Stack[]) => void             | Create index (auto-called) |

## Performance Targets

- Index creation: <50ms
- Per-query search: <1ms
- Large dataset (500+): 30-52ms total
- Result limit: 8 items max

## Testing

Run tests:

```bash
npm test                # Watch mode
npm run test:run       # Single run
npm run test:coverage  # Coverage report
```

Coverage: 96.87%

## Examples

### SearchBar Component

See `src/components/vue/SearchBar.vue` - 264 lines

- Live search with dropdown
- Keyboard navigation (arrows, enter, escape)
- Click-outside to close
- "/" key to focus
- Debounced input (100ms)

### SearchBar Vue Pattern

```vue
<script setup lang="ts">
import { ref } from "vue";
import { useSearch } from "@/composables/useSearch";

const { performSearch, results } = useSearch();
const query = ref("");

function handleSearch(q: string) {
  performSearch(q, props.templates);
}
</script>

<template>
  <input v-model="query" @input="handleSearch(query)" />
  <ul v-for="result in results" :key="result.item.id">
    <li>{{ result.item.name }} ({{ result.score.toFixed(2) }})</li>
  </ul>
</template>
```

## Troubleshooting

**No results?**

- Check query length ≥ 2 chars
- Verify templates/stacks passed to performSearch
- Try exact match first (e.g., "docker" for "docker-setup")

**Slow search?**

- Check dataset size (>1000?)
- Simplify query (fewer special chars)
- Run `npm run test` to benchmark

**Wrong ranking?**

- Review field boost weights above
- Adjust tolerance for fuzzy matching
- Check `src/composables/useSearch.ts` config

## Next: Phase 2

- [ ] useCart.ts (stack building)
- [ ] Search filters (by type, category)
- [ ] Search history (recent queries)
- [ ] Advanced search (field-specific syntax)

## See Also

- **Full API:** `/docs/search-api.md`
- **Code Pattern:** `/docs/code-standards.md` → Search Composable Pattern
- **Codebase:** `/docs/codebase-summary.md` → Composables
- **Tests:** `src/__tests__/useSearch.test.ts`
