diff --git a/.changeset/ai-search-plugin.md b/.changeset/ai-search-plugin.md new file mode 100644 index 000000000..bd0d59825 --- /dev/null +++ b/.changeset/ai-search-plugin.md @@ -0,0 +1,5 @@ +--- +"@emdash-cms/cloudflare": minor +--- + +Adds AI Search plugin with content indexing, search modal, and admin settings UI. Includes a Cloudflare-native integration using the AI Search worker binding and a standalone package using the REST API. diff --git a/demos/cloudflare/astro.config.mjs b/demos/cloudflare/astro.config.mjs index 3c7c731cc..4534e2f3d 100644 --- a/demos/cloudflare/astro.config.mjs +++ b/demos/cloudflare/astro.config.mjs @@ -10,6 +10,7 @@ import { cloudflareImages, cloudflareStream, } from "@emdash-cms/cloudflare"; +import { aiSearch } from "@emdash-cms/cloudflare/plugins"; import { formsPlugin } from "@emdash-cms/plugin-forms"; import { webhookNotifierPlugin } from "@emdash-cms/plugin-webhook-notifier"; import { defineConfig, fontProviders } from "astro/config"; @@ -72,6 +73,7 @@ export default defineConfig({ plugins: [ // Test plugin that exercises all v2 APIs formsPlugin(), + aiSearch(), ], // Sandboxed plugins (run in isolated workers) sandboxed: [webhookNotifierPlugin()], diff --git a/demos/cloudflare/emdash-env.d.ts b/demos/cloudflare/emdash-env.d.ts index ea5f02a61..abb26262f 100644 --- a/demos/cloudflare/emdash-env.d.ts +++ b/demos/cloudflare/emdash-env.d.ts @@ -10,7 +10,6 @@ export interface Page { slug: string | null; status: string; title: string; - template?: "Default" | "Full Width"; content?: PortableTextBlock[]; createdAt: Date; updatedAt: Date; diff --git a/demos/cloudflare/src/components/PostCard.astro b/demos/cloudflare/src/components/PostCard.astro index 500fbac6e..3fee6edd8 100644 --- a/demos/cloudflare/src/components/PostCard.astro +++ b/demos/cloudflare/src/components/PostCard.astro @@ -119,7 +119,7 @@ const formattedDate = date } .card-image { - aspect-ratio: 16 / 10; + aspect-ratio: 16 / 9; overflow: hidden; border-radius: var(--radius-lg); background: var(--color-surface); @@ -138,7 +138,7 @@ const formattedDate = date } .card-placeholder { - aspect-ratio: 16 / 10; + aspect-ratio: 16 / 9; border-radius: var(--radius-lg); background: var(--color-surface); margin-bottom: var(--spacing-4); diff --git a/demos/cloudflare/src/components/SearchModal.astro b/demos/cloudflare/src/components/SearchModal.astro new file mode 100644 index 000000000..39ac1ccc7 --- /dev/null +++ b/demos/cloudflare/src/components/SearchModal.astro @@ -0,0 +1,925 @@ +--- +/** + * SearchModal - A modal search component for EmDash content + * + * Opens a centered modal overlay when the trigger button is clicked or + * when the user presses Cmd/Ctrl+K. Matches the style of Cloudflare's + * AI Search snippet modal. + * + * ```astro + * --- + * import SearchModal from "emdash/ui/search-modal"; + * --- + * + * ``` + */ + +export interface Props { + /** Placeholder text for the search input */ + placeholder?: string; + /** Collections to search (defaults to all searchable collections) */ + collections?: string[]; + /** Minimum characters before searching (defaults to 2) */ + minChars?: number; + /** Debounce delay in milliseconds (defaults to 300) */ + debounce?: number; + /** Maximum results to show (defaults to 10) */ + limit?: number; + /** Keyboard shortcut key (defaults to "k", used with Cmd/Ctrl) */ + shortcut?: string; + /** + * Custom search endpoint URL. Overrides the default FTS5 search endpoint. + * Use this to point at a plugin search route, e.g. `"/_emdash/api/plugins/ai-search/query"`. + * The endpoint should accept `q`, `limit`, and `collection` query params + * and return `{ results: [{ collection, id, slug?, title?, snippet?, score }] }`. + */ + searchEndpoint?: string; +} + +const { + placeholder = "Search...", + collections, + minChars = 2, + debounce = 300, + limit = 10, + shortcut = "k", + searchEndpoint, +} = Astro.props; + +const config = { + collections: collections?.join(",") ?? "", + minChars, + debounce, + limit, + shortcut, + searchEndpoint: searchEndpoint ?? null, +}; +--- + + + + + + + + + + + + diff --git a/demos/cloudflare/src/layouts/Base.astro b/demos/cloudflare/src/layouts/Base.astro index e662077d9..df0ee59c1 100644 --- a/demos/cloudflare/src/layouts/Base.astro +++ b/demos/cloudflare/src/layouts/Base.astro @@ -8,7 +8,7 @@ import { } from "emdash/ui"; import { createPublicPageContext } from "emdash/page"; import { Font } from "astro:assets"; -import LiveSearch from "emdash/ui/search"; +import SearchModal from "../components/SearchModal.astro"; import "../styles/theme.css"; interface Props { @@ -99,14 +99,11 @@ const isLoggedIn = !!Astro.locals.user;