Skip to main content

Overview

This guide will walk you through creating a basic search interface using Interface X components. By the end, you’ll have a working search box with query suggestions and results display.
Before starting, make sure you’ve completed the Installation guide.

What You’ll Build

In this quickstart, you’ll create a search interface with:
  • A search input field with auto-suggestions
  • Query suggestions as users type
  • A results list that displays search results
  • Clear search functionality

Step-by-Step Guide

1

Set up the X Plugin

First, install the X Plugin in your Vue application. Create or update your main.ts file:
main.ts
import { createApp } from 'vue';
import { XInstaller } from '@empathyco/x-components';
import { platformAdapter } from '@empathyco/x-adapter-platform';
import App from './App.vue';

// Configure the X Installer
const installer = new XInstaller({
  adapter: platformAdapter,
  domElement: '#app',
  rootComponent: App,
});

// Initialize with your search configuration
await installer.init({
  instance: 'empathy',
  lang: 'en',
  env: 'staging',
  scope: 'your-catalog-scope',
});
This sets up the X Plugin with the Platform Adapter for connecting to your search API.
2

Create the Search Interface Component

Create a new Vue component for your search interface. This component will include the search box and results:
SearchInterface.vue
<template>
  <div class="search-interface">
    <!-- Search Input Container -->
    <div class="search-box">
      <div class="search-input-group">
        <SearchInput
          :instant="true"
          :instant-debounce-in-ms="500"
          :max-length="64"
          :autofocus="true"
          aria-label="Search for products"
        />
        <ClearSearchInput aria-label="Clear search">
          Clear
        </ClearSearchInput>
        <SearchButton aria-label="Search">
          Search
        </SearchButton>
      </div>

      <!-- Query Suggestions -->
      <QuerySuggestions
        :max-items-to-render="5"
        class="suggestions-list"
      >
        <template #suggestion-content="{ suggestion }">
          <span class="suggestion-text">{{ suggestion.query }}</span>
        </template>
      </QuerySuggestions>
    </div>

    <!-- Search Results -->
    <div class="results-section">
      <ResultsList>
        <template #result="{ item }">
          <article class="result-card">
            <img
              v-if="item.images?.[0]"
              :src="item.images[0]"
              :alt="item.name"
              class="result-image"
            />
            <div class="result-info">
              <h3 class="result-title">{{ item.name }}</h3>
              <p v-if="item.price" class="result-price">
                {{ item.price.value }} {{ item.price.currency }}
              </p>
            </div>
          </article>
        </template>
      </ResultsList>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  SearchInput,
  ClearSearchInput,
  SearchButton,
  QuerySuggestions,
  ResultsList,
} from '@empathyco/x-components';
</script>
3

Import Required Components

The components used in this example come from different X Modules:
// From search-box module
import { SearchInput } from '@empathyco/x-components';
import { ClearSearchInput } from '@empathyco/x-components';
import { SearchButton } from '@empathyco/x-components';

// From query-suggestions module
import { QuerySuggestions } from '@empathyco/x-components';

// From search module
import { ResultsList } from '@empathyco/x-components';
All components are exported from the main @empathyco/x-components package for easy importing.
4

Add Basic Styling

Add some basic CSS to make your search interface look presentable:
styles.css
.search-interface {
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem;
}

.search-box {
  margin-bottom: 2rem;
}

.search-input-group {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.search-input-group input {
  flex: 1;
  padding: 0.75rem 1rem;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  font-size: 1rem;
}

.search-input-group button {
  padding: 0.75rem 1.5rem;
  background: #0066cc;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: 600;
}

.suggestions-list {
  list-style: none;
  padding: 0;
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  margin-top: 0.5rem;
}

.suggestion-text {
  display: block;
  padding: 0.75rem 1rem;
  cursor: pointer;
  transition: background 0.2s;
}

.suggestion-text:hover {
  background: #f5f5f5;
}

.results-section {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1.5rem;
}

.result-card {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1rem;
  transition: box-shadow 0.2s;
}

.result-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.result-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 1rem;
}

.result-title {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.result-price {
  color: #0066cc;
  font-weight: 600;
}
5

Test Your Search Interface

Start your development server and test the search functionality:
npm run dev
Try the following interactions:
  1. Type in the search box - You should see query suggestions appear
  2. Click a suggestion - The search should execute automatically
  3. View results - Product results should display in a grid
  4. Clear the search - Click the Clear button to reset

Understanding the Components

SearchInput

The SearchInput component provides the main search field with built-in features:
  • instant: When true, automatically triggers search as you type
  • instant-debounce-in-ms: Delay in milliseconds before triggering instant search (prevents excessive API calls)
  • max-length: Maximum character limit for the search query
  • autofocus: Automatically focus the input when the component mounts
<SearchInput
  :instant="true"
  :instant-debounce-in-ms="500"
  :max-length="64"
  :autofocus="true"
/>

QuerySuggestions

Displays query suggestions based on what the user types:
<QuerySuggestions :max-items-to-render="5">
  <template #suggestion-content="{ suggestion }">
    {{ suggestion.query }}
  </template>
</QuerySuggestions>

ResultsList

Renders search results with customizable item templates:
<ResultsList>
  <template #result="{ item }">
    <!-- Your custom result card -->
  </template>
</ResultsList>

Component State Management

Interface X uses Vuex for state management. Each component automatically connects to the appropriate store module:
  • SearchInputsearchBox module
  • QuerySuggestionsquerySuggestions module
  • ResultsListsearch module
You can access state using the useState composable:
import { useState } from '@empathyco/x-components';

const { query, results, totalResults } = useState('search');

Event System

Interface X components communicate through an event bus. Common events include:
  • UserAcceptedAQuery - User submitted a search query
  • UserIsTypingAQuery - User is typing in the search box
  • UserClickedAResult - User clicked on a search result
  • UserClearedQuery - User cleared the search
You can listen to events using the use$x composable:
import { use$x } from '@empathyco/x-components';

const $x = use$x();

$x.on('UserAcceptedAQuery').subscribe(({ query }) => {
  console.log('User searched for:', query);
});

Next Steps

Now that you have a basic search interface working, explore these features:

Add Facets & Filters

Let users refine search results with filters

Popular Searches

Display trending searches to inspire users

Recommendations

Show personalized product recommendations

History Queries

Display user’s recent search history

Advanced Configuration

Configure Multiple Modules

You can configure specific X Modules during installation:
const installer = new XInstaller({
  adapter: platformAdapter,
  xModules: {
    facets: {
      config: {
        filtersStrategyForRequest: 'leaves-only',
      },
    },
    search: {
      config: {
        pageSize: 24,
      },
    },
  },
});

Custom Adapter Configuration

If you’re using a custom search API, create your own adapter:
import { endpointAdapterFactory } from '@empathyco/x-adapter';

const customAdapter = {
  search: endpointAdapterFactory({
    endpoint: 'https://your-api.com/search',
    requestMapper: (request) => ({
      q: request.query,
      rows: request.rows,
    }),
    responseMapper: (response) => ({
      results: response.products,
      totalResults: response.total,
    }),
  }),
};

Troubleshooting

Ensure:
  1. Your search API supports query suggestions
  2. The adapter is correctly configured
  3. You’re typing at least 2-3 characters
  4. Check browser console for API errors
Common issues:
  1. Verify your scope and instance configuration
  2. Check network tab for API responses
  3. Ensure results data matches expected format
  4. Try a known working query first
Interface X components come with minimal styling. Options:
  1. Add your own CSS (as shown above)
  2. Install @empathyco/x-tailwindcss for the design system
  3. Use CSS frameworks like Tailwind or Bootstrap
For more examples, check out the X Archetype - a complete reference implementation showing all Interface X capabilities.

Build docs developers (and LLMs) love