Description
The /_emdash/api/search endpoint requires search:read permission, which means unauthenticated visitors cannot use the LiveSearch component on the frontend.
Root cause
In astro/routes/api/search/index.ts:
const denied = requirePerm(user, "search:read");
if (denied) return denied;
This returns 401 for any unauthenticated request. The same applies to /_emdash/api/search/suggest.
Impact
The LiveSearch component (which hardcodes /_emdash/api/search as its endpoint) doesn't work for public visitors. Search is a common frontend feature that should work without authentication.
Workaround
Create a custom public API route that calls the search() function directly:
// src/pages/api/search.ts
import type { APIRoute } from "astro";
import { search } from "emdash";
export const prerender = false;
export const GET: APIRoute = async ({ url }) => {
const q = url.searchParams.get("q")?.trim();
if (!q || q.length < 2) {
return new Response(JSON.stringify({ data: { items: [] } }), {
headers: { "Content-Type": "application/json" },
});
}
const result = await search(q, {
collections: url.searchParams.get("collections")?.split(","),
status: "published",
limit: Math.min(Number(url.searchParams.get("limit")) || 10, 20),
});
return new Response(JSON.stringify({ data: result }), {
headers: { "Content-Type": "application/json" },
});
};
This requires building a custom search UI since LiveSearch hardcodes the emdash API endpoint.
Suggested fix
Either:
- Make
/_emdash/api/search publicly accessible (with status: "published" enforced for unauthenticated users), or
- Add a configurable
endpoint prop to LiveSearch so themes can point it at a custom route, or
- Add search to the public API prefixes list with appropriate rate limiting
Description
The
/_emdash/api/searchendpoint requiressearch:readpermission, which means unauthenticated visitors cannot use theLiveSearchcomponent on the frontend.Root cause
In
astro/routes/api/search/index.ts:This returns 401 for any unauthenticated request. The same applies to
/_emdash/api/search/suggest.Impact
The
LiveSearchcomponent (which hardcodes/_emdash/api/searchas its endpoint) doesn't work for public visitors. Search is a common frontend feature that should work without authentication.Workaround
Create a custom public API route that calls the
search()function directly:This requires building a custom search UI since
LiveSearchhardcodes the emdash API endpoint.Suggested fix
Either:
/_emdash/api/searchpublicly accessible (withstatus: "published"enforced for unauthenticated users), orendpointprop toLiveSearchso themes can point it at a custom route, or