SmallStack · Search

Find anything.

Across 8 indexed models and the bundled help documentation. Free-text query with phrase, prefix, exclusion, and boolean operators — same syntax across SQLite FTS5 and Postgres FTS.

Query is case-insensitive · stems on supported backends RETURN to search
Query
syntax
acme
Single term
acme support
Both words — implicit AND
"customer support"
Exact phrase, word-adjacent
refund*
Prefix — also matches refunding, refunded
acme OR beta
Either word
api -slow
Contains api, excludes slow

From anywhere else on the site, press Ctrl + K (or ⌘ + K) to pop up the quick search overlay — a smaller version of this page. This page itself is the deeper experience.

Shape
a result

Every hit on this page is a title, a line of context and a link. When a model deserves more, give its CRUDView a transform_hit: whatever the dict returns beyond display and subtitle travels with the hit as extra — to this page, the omnibar, /api/search/ and the MCP tool alike. The blog does exactly this, so a published post renders as an article card instead of a row.

# apps/blog/views.py
class PostCRUDView(CRUDView):
    enable_search  = True
    search_fields  = ["title", "excerpt", "body_markdown"]

    def get_search_variants(self):
        return {"default": "Article card", "compact": "Title + permalink"}

    def transform_hit(self, post, variant="default"):
        if variant == "compact":
            return {"display": post.title, "url": post.public_url}
        return {
            "display": post.title, "subtitle": post.excerpt,
            "card": "article",                    # the template switches on this
            "blog": post.blog.name, "published_at": post.published_at,
            "reading_minutes": words // 220,
            "tags": [t.name for t in post.tags.all()],
            "cover_url": post.cover_image.url,
        }

The page then branches on hit.extra.card and renders this instead of the default row:

The compact variant also becomes its own MCP tool, search_blog_posts_compact, for agents that only need a permalink. Template: templates/website/includes/search_article_card.html. Reference: search docs.

Indexed
sources Click a row to expand its schema, MCP tool, and live records.
MODEL search_blog_posts Post View all →
titleexcerptbody_markdown
display subtitle
search_blog_posts(query: str, limit: int = 10) # → ranked hits with display, snippet, url