Basic Integration Guide for Astro
This guide demonstrates how to integrate staticseek into a Astro application. You can find the complete implementation in our GitHub repository and see it in action at our live demo.
Getting Started
Section titled “Getting Started”To start the local development server:
npm installnpm run devNavigate to http://localhost:4321 in your browser to view the application.
Deployment
Section titled “Deployment”This example is optimized for static file deployment. To generate and deploy the static files:
npm installnpm run build# Upload the generated "dist" directory to your HTTP serverBasic Usage of staticseek with Astro
Section titled “Basic Usage of staticseek with Astro”The following code (src/pages/index.astro) demonstrates the most basic usage of staticseek in a Single Page Application (SPA). This application extracts and displays matching keywords from a predefined array. For input queries of two or fewer characters, an exact match search is performed. For queries of three or more characters, a fuzzy search allowing one character mistake is executed.
---import { getEntry } from "astro:content";import Html from "../layout/html.astro";
const entry = await getEntry("contents", "sentences");if (!entry) throw new Error("No data found");---<Html> <section> <div class="input-area"> <div>search</div> <input type="text" name="search" id="search" placeholder="Enter the following keywords" /> </div> <ul class="search-result" data-target={JSON.stringify(entry.data)}> </ul> </section></Html>
<script> import { createIndex, LinearIndex, search, StaticSeekError } from "staticseek";
const search_result_element = document.querySelector<HTMLUListElement>(".search-result"); if(!search_result_element) throw new Error("No search result element found"); const target_string = search_result_element.dataset.target; const target = JSON.parse(target_string ?? "") as string[];
const index = createIndex(LinearIndex, target); if(index instanceof StaticSeekError) throw index;
const search_input = document.querySelector<HTMLInputElement>("#search"); search_input?.addEventListener("input", async (e) => { const query = search_input.value; const result = await search(index, query); if(result instanceof StaticSeekError) throw result;
search_result_element.innerHTML = '<li><div class="sentence">sentence</div><div>score</div></li>';
if(query.length === 0) { for(const r of target) { const li = document.createElement("li"); li.innerHTML = `<div class="sentence">${r}</div><div></div>`; search_result_element.appendChild(li); }; } else { for(const r of result) { const li = document.createElement("li"); li.innerHTML = `<div class="sentence">${target[r.id]}</div><div class="score">${r.score.toFixed(4)}</div>`; search_result_element.appendChild(li); }; } }); search_input?.dispatchEvent(new Event("input"));</script>import { defineCollection, z } from "astro:content";import { glob } from "astro/loaders";
const contents = defineCollection({ loader: glob({ pattern: "./[^_]*.json", base: "contents" }), schema: z.array(z.string()),});
export const collections = { contents };[ "The sun sets behind the quiet mountain.", "She found an old book in the dusty attic.", "A gentle breeze rustled through the tall trees.", ... "A black cat sat on the fence, watching the street.", "The carpenter sanded the surface of the wooden table.", "She blew a kiss to her loved one from afar.", "The puppy fell asleep curled up in a soft blanket."]Implementation Details
Section titled “Implementation Details”-
For simplicity, this example uses
innerHTML. However, in production applications, you should usecreateElementandappendChildmethods instead ofinnerHTMLto mitigate security risks associated with direct HTML injection. -
While staticseek operates on the client side, code written in the Astro component’s component script section only executes once during deployment. Therefore, staticseek is implemented within a script element in the component template.
-
This example retrieves search target data from Astro’s Content Collections. The content collection directory structure and data schema are defined in
src/content.config.ts. The sample uses thegetEntry()function to fetch data fromsentences.jsonwithin thecontentsdirectory. -
JavaScript objects retrieved via
getEntry()can only be used within the component script section and HTML descriptions in the component template section. To use JavaScript objects withinscriptelements, we leverage HTML data attributes. These data attributes allow you to specify custom attributes on HTML elements, enabling the transfer of JavaScript objects as stringified data that can be retrieved and parsed withinscriptelements. -
When passing JavaScript objects through data attributes, the objects are bundled as attribute values in the final HTML file. Therefore, passing large objects can significantly increase the HTML file size, potentially slowing down browser loading times. When using this approach, carefully consider the size of the objects being transferred to maintain optimal performance.
-
The search index is created by passing the keyword array to
createIndex. -
The search query is input via a text field (
input:text), and searches are executed on eachinputevent. -
Search results are displayed using the
idfield from theSearchResulttype, which corresponds to the index of the keyword in the originaltargetarray.
Additional Notes
Section titled “Additional Notes”- Search results are sorted by relevance score.
- Error handling is implemented for both index creation and search operations.