{doc.title}
{doc.content.substring(0, 200)}...
{new Date(doc.date).toLocaleDateString()}
Indx Search interface components for React. Provides ready-to-use filter panels, search inputs, faceted navigation, and sorting components. Built on @indxsearch/systm.
npm install @indxsearch/intrfaceA powerful, flexible React search UI library for Indx Search with IndxCloudApi.
- 🔍 Full-text search with fuzzy matching and typo tolerance
- 🎯 Faceted filtering - Value filters (exact match) and range filters (numeric)
- 📊 Real-time facet counts - Dynamic aggregations that update with search
- 📱 Mobile-responsive - Built-in responsive design
- ⚡ Debounced searches - Optimized performance
- 🎨 Customizable rendering - Full control over result display
- 🔒 Secure authentication - Session-based authentication with automatic login
| Package | Version |
|---------|---------|
| IndxCloudApi | 1.0.2 |
| React | ^19.0.0 |
| React DOM | ^19.0.0 |
| Node.js | >=16.0.0 |
> Note: This library is designed specifically for IndxCloudApi version 1.0.2. Different API versions may have incompatible changes.
``bash`
npm install @indxsearch/intrface @indxsearch/systm @indxsearch/pixl
> Note: TypeScript type definitions for IndxCloudApi are automatically included via the @indxsearch/indx-types dependency.
Create a .env.local file in your project root:
Option A: Using Bearer Token (Recommended for Production)
`bash`
VITE_INDX_URL=https://your-indx-server.com
VITE_INDX_TOKEN=your-jwt-bearer-token-here
Option B: Using Email/Password (Quick Start)
`bash`
VITE_INDX_URL=https://your-indx-server.com
VITE_INDX_EMAIL=your@email.com
VITE_INDX_PASSWORD=yourpassword
For local development:
`bash`
VITE_INDX_URL=http://localhost:5001Then add either token or email/password as shown above
Security Notes:
- Never commit .env.local to version control
- Store credentials/tokens securely in environment variables
- For production deployments, prefer bearer token authentication
Import the CSS file in your app entry point:
`typescript`
import '@indxsearch/intrface/styles.css';
`typescript
import { SearchProvider, SearchInput, SearchResults } from '@indxsearch/intrface';
export default function SearchPage() {
return (
email={import.meta.env.VITE_INDX_EMAIL}
password={import.meta.env.VITE_INDX_PASSWORD}
dataset="products"
>
resultsPerPage={10}
>
{(item) => (
{item.description}
Using different datasets on different pages:
`typescript
// products page
{/ ... /}
// articles page
{/ ... /}
`Authentication
The library supports two authentication methods: bearer token and email/password login.
$3
Use a pre-authenticated JWT bearer token. This is ideal when you have a backend that generates tokens for your users.
Environment setup:
`bash
VITE_INDX_URL=https://your-indx-server.com
VITE_INDX_TOKEN=your-jwt-bearer-token-here
`Usage:
`typescript
url={import.meta.env.VITE_INDX_URL}
preAuthenticatedToken={import.meta.env.VITE_INDX_TOKEN}
dataset="products"
>
{/ Your search UI /}
`When to use:
- ✅ Production applications with backend authentication
- ✅ When you have existing token infrastructure
- ✅ For better security (tokens can have expiration, limited scope)
- ✅ When you want to avoid storing passwords client-side
$3
Automatically logs in when the app initializes using email and password.
Environment setup:
`bash
VITE_INDX_URL=https://your-indx-server.com
VITE_INDX_EMAIL=your@email.com
VITE_INDX_PASSWORD=yourpassword
`Usage:
`typescript
url={import.meta.env.VITE_INDX_URL}
email={import.meta.env.VITE_INDX_EMAIL}
password={import.meta.env.VITE_INDX_PASSWORD}
dataset="products"
>
{/ Your search UI /}
`How it works:
1. You provide email and password to
SearchProvider
2. On mount, the library automatically calls the Login API endpoint
3. A fresh session token is obtained and used for all subsequent requests
4. No manual token management requiredWhen to use:
- ✅ Quick prototyping and development
- ✅ Demo applications
- ✅ When you don't have token infrastructure yet
Security Best Practices:
- Store credentials/tokens in environment variables (
.env.local)
- Never commit .env.local to version control
- Use secure HTTPS connections in production
- For production, prefer bearer token authenticationError Handling
The library includes comprehensive error handling with helpful console messages:
$3
The SearchProvider automatically validates:
- ✅ Authentication (bearer token or email/password)
- ✅ Login success and token retrieval (when using email/password)
- ✅ Dataset existence and status
- ✅ Dataset readiness (indexing complete)
- ✅ Empty dataset warnings
- ✅ Network connectivity
All errors include:
- Clear error messages
- Specific problem identification
- Actionable fix suggestions
- Example commands to resolve issues
$3
Wrap your search interface with
SearchErrorBoundary for graceful error handling:`typescript
import { SearchErrorBoundary, SearchProvider } from '@indxsearch/intrface';
{/ Your search UI /}
`Custom error UI:
`typescript
fallback={(error, reset) => (
Search Error
{error.message}
)}
>
{children}
`$3
All errors show in the browser console with emoji indicators:
- ✅ = Success
- 🔍 = Checking something
- ⚠️ = Warning (non-critical)
- ❌ = Error (needs fixing)
- 💡 = Helpful suggestion
Example:
`
[Auth] ❌ Dataset "products" not found (404)
[Auth] 💡 Available datasets can be checked with: curl -X GET ...
[Auth] 💡 Make sure you spelled the dataset name correctly
`Adding Filters
$3
`typescript
import { ValueFilterPanel } from '@indxsearch/intrface';
{/ Simple checkbox list /}
field="category"
label="Category"
/>
{/ Button-style filters /}
field="brand"
label="Brand"
displayType="button"
layout="grid"
/>
{renderItem}
`$3
`typescript
import { RangeFilterPanel } from '@indxsearch/intrface'; field="price"
label="Price Range"
min={0}
max={1000}
/>
`$3
`typescript
import { ActiveFiltersPanel } from '@indxsearch/intrface';
`Full Example with Filters
`typescript
import {
SearchProvider,
SearchInput,
SearchResults,
ValueFilterPanel,
RangeFilterPanel,
ActiveFiltersPanel,
SortByPanel,
} from '@indxsearch/intrface';export default function AdvancedSearch() {
return (
url={import.meta.env.VITE_INDX_URL}
email={import.meta.env.VITE_INDX_EMAIL}
password={import.meta.env.VITE_INDX_PASSWORD}
dataset="products"
allowEmptySearch={true}
enableFacets={true}
maxResults={20}
>
{/ Sidebar with filters /}
{/ Main content /}
fields={['name', 'description', 'price', 'category', 'brand']}
resultsPerPage={20}
>
{(item) => (
{item.name}
{item.description}
${item.price} • {item.category}
)}
);
}
`API Reference
$3
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
|
url | string | ✅ | - | INDX server URL |
| preAuthenticatedToken | string | ⚠️ | - | Bearer token for authentication (either this OR email/password) |
| email | string | ⚠️ | - | User email for authentication (either this OR token) |
| password | string | ⚠️ | - | User password for authentication (either this OR token) |
| dataset | string | ✅ | - | Dataset name |
| allowEmptySearch | boolean | ❌ | false | Show results without query |
| enableFacets | boolean | ❌ | true | Enable faceted search |
| enableCoverage | boolean | ❌ | true | Enable coverage-based fuzzy matching |
| maxResults | number | ❌ | 10 | Max results per search |
| facetDebounceDelayMillis | number | ❌ | 500 | Debounce delay for facet updates (ms) |
| coverageDepth | number | ❌ | 500 | Search depth for fuzzy matching |
| removeDuplicates | boolean | ❌ | true | Remove duplicate results |
| initialCoverageSetup | Partial | ❌ | {} | Override default coverage settings |
| enableDebugLogs | boolean | ❌ | false | Enable detailed console logging |$3
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
placeholder | string | 'Search...' | Input placeholder text |
| showClear | boolean | true | Show clear button |
| showFocus | boolean | false | Show focus ring |
| inputSize | 'micro' \| 'default' | 'default' | Input size |$3
| Prop | Type | Required | Description |
|------|------|----------|-------------|
|
fields | string[] | ✅ | Document fields to fetch |
| resultsPerPage | number | ✅ | Results per page |
| children | (item: any) => ReactNode | ✅ | Render function for each result |$3
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
field | string | ✅ | Field name to filter on |
| label | string | ❌ | Display label |
| displayType | 'checkbox' \| 'button' | 'checkbox' | Filter UI style |
| layout | 'list' \| 'grid' | 'list' | Layout style |
| limit | number | undefined | Max filters to show |
| startCollapsed | boolean | false | Start collapsed |
| showCount | boolean | true | Show facet counts |$3
| Prop | Type | Required | Description |
|------|------|----------|-------------|
|
field | string | ✅ | Field name to filter on |
| label | string | ❌ | Display label |
| min | number | ❌ | Minimum value |
| max | number | ❌ | Maximum value |Troubleshooting
$3
Problem: Authentication credentials are invalid
Solutions:
1. Verify your email and password are correct
2. Check that the credentials match your INDX account
3. Ensure the INDX server URL is correct
4. Check browser console for detailed error messages
$3
Problem: Authentication failed or token is invalid
Solutions:
1. If using bearer token: Verify the token is valid and not expired. Generate a new token if needed.
2. If using email/password: Refresh the page to get a new session token (automatic login)
3. Check that the token/credentials are correctly set in your environment variables
4. Verify the server is running and accessible
5. Check server logs for authentication issues
$3
Problem: Cannot connect to INDX server
Solutions:
1. Verify the server URL is correct
2. Check if the server is running (for local:
http://localhost:5001)
3. Ensure CORS is configured on the server
4. Check browser console for detailed error$3
Problem: Empty results even with data
Solutions:
1. Verify dataset name is correct
2. Check if dataset is indexed (use GetStatus endpoint)
3. Ensure fields are configured as indexable/facetable
4. Try
allowEmptySearch={true} to see all results$3
Problem: Filters don't update results
Solutions:
1. Ensure fields are configured as filterable/facetable in your dataset
2. Check browser console for errors
3. Verify field names match your dataset
Examples
$3
`typescript
{(product) => (
name={product.name}
price={product.price}
image={product.image}
/>
)}
`$3
`typescript
{(doc) => (
{doc.title}
{doc.content.substring(0, 200)}...
{new Date(doc.date).toLocaleDateString()}
)}
``- Documentation: docs.indx.co