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
To start the local development server:
npm installnpm run dev
Navigate to http://localhost:4321 in your browser to view the application.
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 server
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
-
For simplicity, this example uses
innerHTML
. However, in production applications, you should usecreateElement
andappendChild
methods instead ofinnerHTML
to 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.json
within thecontents
directory. -
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 withinscript
elements, 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 withinscript
elements. -
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 eachinput
event. -
Search results are displayed using the
id
field from theSearchResult
type, which corresponds to the index of the keyword in the originaltarget
array.
Additional Notes
- Search results are sorted by relevance score.
- Error handling is implemented for both index creation and search operations.