nowo-tech / search-kit-bundle
Global header search (command palette) for Symfony: a magnifier that stretches into a field, grouped permission-aware results from your own providers, Ctrl/⌘K, keyboard navigation, recents, UX Icons and theme tokens.
Package info
github.com/nowo-tech/SearchKitBundle
Type:symfony-bundle
pkg:composer/nowo-tech/search-kit-bundle
Requires
- php: >=8.3 <8.6
- psr/log: ^3.0
- symfony/asset: ^7.4 || ^8.0
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/form: ^7.4 || ^8.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/options-resolver: ^7.4 || ^8.0
- symfony/rate-limiter: ^7.4 || ^8.0
- symfony/routing: ^7.4 || ^8.0
- symfony/security-bundle: ^7.4 || ^8.0
- symfony/translation: ^7.4 || ^8.0
- symfony/translation-contracts: ^3.5
- symfony/twig-bundle: ^7.4 || ^8.0
- twig/extra-bundle: ^3.12
- twig/string-extra: ^3.12
- twig/twig: ^3.12
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- igor-php/igor-php: ^0.9.7
- nowo-tech/phpstan-frankenphp: ^1.1
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- rector/rector: ^2.0
- symfony/browser-kit: ^7.4 || ^8.0
- symfony/css-selector: ^7.4 || ^8.0
- symfony/ux-icons: ^2.25 || ^3.0
- symfony/yaml: ^7.4 || ^8.0
- vincentlanglet/twig-cs-fixer: ^3.0
Suggests
- nowo-tech/dashboard-menu-bundle: Built-in Pages group: menu entries the user can see (menu_pages)
- symfony/ux-icons: Kind and item icons from your icon set (icon_set: ux_icon); without it the built-in SVG is used
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-16 17:28:29 UTC
README
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Search Kit Bundle — a global header search (command palette) for Symfony: a magnifier that stretches into a field, grouped permission-aware results from your own providers, Ctrl/⌘ K, keyboard navigation, recents, UX Icons and theme tokens.
📋 Compatible with Symfony 7.4+ and 8.0–8.1+ — PHP 8.3+ (Symfony 8.x requires PHP 8.4+).
This bundle is FrankenPHP worker mode friendly. See docs/FRANKENPHP-WORKER-AUDIT.md.
Features
- Header magnifier that stretches into a field in place (no modal), results in a dropdown under it; full-width field and dropdown on phones
- Your groups, your rules: implement
SearchProviderInterfaceonce per group (Projects, Issues, Users, …) — autoconfigured, ordered by priority; the kit never decides what a user may see - Pages group out of the box from DashboardMenuBundle menus (permission-filtered tree, breadcrumbs, deduplicated by URL)
- Scope chip:
SearchScopeResolverInterfacestarts the search inside the current project / team / space; Backspace removes it - Keyboard first: Ctrl/⌘ K anywhere,
/outside fields, ↑ ↓ across groups, Enter, Ctrl/⌘ Enter for a new tab, Esc or a click outside to fold - Accessible: ARIA combobox + listbox,
aria-activedescendant, live result count,prefers-reduced-motion - Recents (per browser,
localStorage, text only — never HTML) and configurable quick actions while the query is empty - Safe rendering: user text is escaped and highlighted with
<mark>through DOM nodes; only same-site paths or http(s) URLs are ever navigated - Debounced, aborted requests; JSON endpoint rate limited per user,
Cache-Control: no-store, private, 429{"error": "rate_limited"} - Overridable Twig blocks, theme tokens (
--nowo-search-*, light / dark), Symfony UX Icons with a built-in SVG fallback - Framework-agnostic browser module (auto-mounted IIFE), an optional Stimulus wrapper and
nowo-search:state/nowo-search:navigateevents (morphing icons, Turbo) - FrankenPHP worker mode friendly; 7 locales (en, es, fr, de, it, pt, nl)
Installation
composer require nowo-tech/search-kit-bundle
With Symfony Flex, the recipe registers the bundle and creates config/packages/nowo_search_kit.yaml and config/routes/nowo_search_kit.yaml (prefix /search). Without Flex, see docs/INSTALLATION.md.
// config/bundles.php return [ Nowo\SearchKitBundle\NowoSearchKitBundle::class => ['all' => true], ];
Quick start
- Import the routes and publish the assets (
bin/console assets:install):
# config/routes/nowo_search_kit.yaml nowo_search_kit: resource: '@NowoSearchKitBundle/Resources/config/routes.php' prefix: /search trailing_slash_on_root: false
- Add one provider per group — it returns only what the user may open:
use Nowo\SearchKitBundle\Contract\SearchProviderInterface; use Nowo\SearchKitBundle\Model\SearchGroup; use Nowo\SearchKitBundle\Model\SearchItem; use Nowo\SearchKitBundle\Model\SearchQuery; use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem; #[AsTaggedItem(priority: 50)] final readonly class ProjectSearchProvider implements SearchProviderInterface { public function __construct(private ProjectRepository $projects) { } public function search(SearchQuery $query): ?SearchGroup { $rows = $this->projects->searchVisibleTo($query->user, $query->text, $query->limit); return new SearchGroup('projects', 'Projects', array_map( static fn (Project $p): SearchItem => new SearchItem($p->getName(), '/projects/' . $p->getId(), $p->getSlug(), 'tabler:folder'), $rows, )); } }
- Render the search in your signed-in header:
{{ include('@NowoSearchKitBundle/search.html.twig') }}
Full guide: docs/INSTALLATION.md · options: docs/CONFIGURATION.md · providers, scope, templates, theme, JS: docs/USAGE.md.
Requirements
- PHP
>=8.3 <8.6(8.3 floor: typed class constants) - Symfony 7.4, 8.0, and 8.1+
- SecurityBundle, TwigBundle, Form, Asset, RateLimiter (installed with the bundle)
- Optional:
symfony/ux-icons(icons from your set; built-in SVG otherwise),nowo-tech/dashboard-menu-bundle(Pages group)
Version information
| Version | PHP | Symfony | Status |
|---|---|---|---|
| 1.x | 8.3 – 8.5 | 7.4, 8.0, 8.1+ | Supported (bug and security fixes) |
Demo
A Symfony 8.1 demo runs on FrankenPHP (worker mode by default); it needs no database:
make -C demo up
# Demo started at: http://localhost:8157
Sign in as alice (admin) or bob (password password), press Ctrl/⌘ K and type shop, api or doc. See docs/DEMO-FRANKENPHP.md.
Playwright end-to-end tests and the README screenshots (WebP under docs/images/demo/): make -C demo/symfony8 test-e2e
and make -C demo/symfony8 demo-screenshots (see docs/CONTRIBUTING.md).
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- Architecture
- PSR evaluation
- Coverage policy
- Demo FrankenPHP
- FrankenPHP worker audit
- GitHub CI
- GitHub About
Tests and coverage
- Tests: PHPUnit (unit, integration, functional), Vitest (TypeScript), Playwright (demo e2e)
- PHP: 100%
- TS/JS: 97.57%
- Python: N/A
PHP line coverage: 100% of includable src/ (gate ≥ 99%; strict gate make test-coverage-100). TypeScript coverage is the minimum of statements / branches / functions / lines (REQ-TEST-009): statements, functions and lines 100%, branches 97.57% (defensive fallbacks); Vitest thresholds 100 / 95 (branches), make gate ≥ 90%.
make test
make test-coverage
make test-ts
make qa
License
MIT © 2026 Héctor Franco Aceituno / Nowo.tech

