# How to Customize the System Prompt and Citation Formatting in MiniSearch

> Learn to customize MiniSearch system prompt and citation formatting. Edit client/modules/settings.ts and client/modules/textGenerationUtilities.ts to control LLM search result appearance.

- Repository: [Victor Nogueira/minisearch](https://github.com/felladrin/minisearch)
- Tags: how-to-guide
- Published: 2026-03-01

---

**You can customize the system prompt and citation formatting in MiniSearch by editing the `systemPrompt` template in [`client/modules/settings.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts) and modifying the `getFormattedSearchResults()` function in [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts) to control how search results appear to the LLM.**

MiniSearch is an open-source AI search interface that exposes its prompt assembly logic through user-editable settings and modular utility functions. The repository `felladrin/minisearch` separates prompt templates from result formatting, allowing you to tailor both the assistant's personality and citation style without touching core generation logic.

## Where the System Prompt Template Lives

The default prompt is defined in **[`client/modules/settings.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts)** as the `systemPrompt` property of `defaultSettings`. This template uses placeholder syntax for dynamic values:

```typescript
systemPrompt: `Answer using the search results below as your primary source, supplemented by your own knowledge when needed. … 
Below are the search results fetched at {{currentDate}}.

{{searchResults}}`,

```

The template contains two key placeholders:
- **`{{searchResults}}`** — Replaced with formatted search results at runtime
- **`{{currentDate}}`** or **`{{dateTime}}`** — Replaced with the current date in `en-CA` format

Source: [`client/modules/settings.ts:19-27`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts#L19-L27)

## Runtime Prompt Assembly

When processing a query, [`client/modules/systemPrompt.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/systemPrompt.ts) interpolates the template through the `getSystemPrompt()` function:

```typescript
export function getSystemPrompt(searchResults: string) {
  const currentDate = new Intl.DateTimeFormat("en-CA", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).format(new Date());

  return getSettings()
    .systemPrompt.replace("{{searchResults}}", searchResults)
    .replace(/{{dateTime}}|{{currentDate}}/g, currentDate);
}

```

This function pulls live settings via `getSettings()`, then performs string replacement to inject the formatted results and timestamp. Any customizations made to the `systemPrompt` setting automatically flow through this interpolation chain.

Source: [`client/modules/systemPrompt.ts:8-17`](https://github.com/felladrin/minisearch/blob/main/client/modules/systemPrompt.ts#L8-L17)

## Editing the Prompt Through the UI

Users can modify the system prompt without editing source files. The **System Prompt editor** resides in [`client/components/Pages/Main/Menu/AISettings/components/SystemPromptInput.tsx`](https://github.com/felladrin/minisearch/blob/main/client/components/Pages/Main/Menu/AISettings/components/SystemPromptInput.tsx), which binds a `<Textarea>` component directly to the `systemPrompt` field:

- **Custom prompts** persist via `settingsPubSub` and override defaults immediately
- **Restore default** functionality calls `handleRestoreDefaultInstructions()` to revert to the template defined in `defaultSettings`

Source: [`SystemPromptInput.tsx:17-26`](https://github.com/felladrin/minisearch/blob/main/client/components/Pages/Main/Menu/AISettings/components/SystemPromptInput.tsx#L17-L26)

## How Citations Are Generated

The bullet list that replaces `{{searchResults}}` is constructed by `getFormattedSearchResults()` in [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts):

```typescript
export function getFormattedSearchResults(shouldIncludeUrl: boolean) {
  const searchResults = getLlmTextSearchResults();

  if (searchResults.length === 0) return "None.";

  if (shouldIncludeUrl) {
    return searchResults
      .map(([title, snippet, url]) => `• [${title}](${url}) | ${snippet}`)
      .join("\n");
  }

  return searchResults
    .map(([title, snippet]) => `• ${title} | ${snippet}`)
    .join("\n");
}

```

When `shouldIncludeUrl` is `true` (the default in the generation flow), each result renders as a markdown link `[title](url)` followed by the snippet. This formatted string becomes the value substituted for `{{searchResults}}` in the system prompt.

Source: [`textGenerationUtilities.ts:38-45`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts#L38-L45)

## Customizing Citation Formatting

You have two entry points to modify citation appearance:

**1. Edit the template description** — Update `defaultSettings.systemPrompt` (or the UI field) to instruct the LLM on alternative citation styles (e.g., footnotes, author-date, or numbered references).

**2. Override the formatter function** — Modify `getFormattedSearchResults()` in [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts) to output different markdown structures. For example, to extract domain-only citations:

```typescript
.map(([title, snippet, url]) => {
  const domain = new URL(url).hostname.replace(/^www\./, '');
  return `• ${title} (${domain}) | ${snippet}`;
})

```

### End-to-End Flow

1. **User edits** the prompt in AI Settings → updates persist via `settingsPubSub`
2. **[`textGeneration.ts`](https://github.com/felladrin/minisearch/blob/main/textGeneration.ts)** calls `getFormattedSearchResults(true)` to generate the markdown list
3. **`getSystemPrompt()`** substitutes `{{searchResults}}` and date placeholders
4. **Final string** populates the first chat message (`ChatMessage.role === "user"`) sent to the LLM

Sources: [`textGeneration.ts:12-18`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGeneration.ts#L12-L18) and [`textGenerationUtilities.ts:12-18`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts#L12-L18)

## Complete Customization Examples

### Changing the Default System Prompt

Modify [`client/modules/settings.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts) to enforce footnote-style citations:

```typescript
// client/modules/settings.ts
export const defaultSettings = {
  // …other settings,
  systemPrompt: `You are a concise assistant. Use the results below as your only source.
  
  // Custom citation rule (footnotes):
  Cite each fact with a footnote like [^1]. The footnote list will appear after the answer.
  
  Fetched on {{currentDate}}:
  
  {{searchResults}}`,
};

```

### Adding a Custom Citation Formatter

Extend [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts) to generate numbered footnotes:

```typescript
// client/modules/textGenerationUtilities.ts
export function getFormattedSearchResults(shouldIncludeUrl: boolean) {
  const searchResults = getLlmTextSearchResults();

  if (searchResults.length === 0) return "None.";

  if (shouldIncludeUrl) {
    // New footnote style
    return searchResults
      .map(([title, snippet, url], idx) => {
        const footnote = `[^${idx + 1}]`;
        return `• ${title} ${footnote} | ${snippet}`;
      })
      .join("\n");
  }

  return searchResults
    .map(([title, snippet]) => `• ${title} | ${snippet}`)
    .join("\n");
}

```

Then append footnote definitions in [`client/modules/systemPrompt.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/systemPrompt.ts):

```typescript
// client/modules/systemPrompt.ts
export function getSystemPrompt(searchResults: string) {
  const currentDate = new Intl.DateTimeFormat("en-CA", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).format(new Date());

  const promptWithResults = getSettings()
    .systemPrompt.replace("{{searchResults}}", searchResults)
    .replace(/{{dateTime}}|{{currentDate}}/g, currentDate);
    
  const footnotes = getLlmTextSearchResults()
    .map(([, , url], idx) => `[^${idx + 1}]: ${url}`)
    .join("\n");
    
  return `${promptWithResults}\n\n${footnotes}`;
}

```

## Summary

- **Template location**: The default system prompt lives in [`client/modules/settings.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts) as `defaultSettings.systemPrompt`, supporting `{{searchResults}}` and `{{currentDate}}` placeholders.
- **Runtime interpolation**: `getSystemPrompt()` in [`client/modules/systemPrompt.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/systemPrompt.ts) performs placeholder substitution using live settings.
- **UI editing**: Users can modify prompts via [`SystemPromptInput.tsx`](https://github.com/felladrin/minisearch/blob/main/SystemPromptInput.tsx), with changes persisting through `settingsPubSub`.
- **Citation formatting**: `getFormattedSearchResults()` in [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts) controls how search results appear, defaulting to markdown bullet lists with linked titles.
- **Customization paths**: Change the template text to alter instructions, or modify the formatter function to change the actual citation markup structure.

## Frequently Asked Questions

### How do I reset the system prompt to default in MiniSearch?

Click the **restore default** button in the AI Settings UI, which triggers `handleRestoreDefaultInstructions()` in [`SystemPromptInput.tsx`](https://github.com/felladrin/minisearch/blob/main/SystemPromptInput.tsx) to reset the form value to `defaultSettings.systemPrompt`. This reverts any custom text to the original template defined in [`client/modules/settings.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/settings.ts).

### Can I use different date formats in the system prompt?

Yes. Modify the `Intl.DateTimeFormat` configuration in `getSystemPrompt()` within [`client/modules/systemPrompt.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/systemPrompt.ts). The current implementation hardcodes `"en-CA"` with `year: "numeric"`, `month: "2-digit"`, and `day: "2-digit"`, but you can change the locale or options to match regional requirements.

### Where does MiniSearch inject the formatted prompt into the LLM request?

The assembled prompt is injected into the chat message array by [`client/modules/textGeneration.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGeneration.ts) (lines 12-18) and [`client/modules/textGenerationUtilities.ts`](https://github.com/felladrin/minisearch/blob/main/client/modules/textGenerationUtilities.ts) (lines 12-18). The system prompt becomes the first user message (`ChatMessage.role === "user"`) sent to the language model, combining the template, current date, and formatted search results.