atoolo/citygov-bundle
CityGov is Sitepark's information management system for municipal and district administration websites and intranet employee portals, bundling all relevant city information and official services into one platform. This Symfony bundle integrates CityGov features into atoolo-based PHP applications.
This is a Symfony bundle, not a Laravel package. There is no ServiceProvider, no config/citygov.php, no Eloquent integration, and no facade. If you are a Laravel developer, the realistic "getting started" path is one of two routes:
Http::post(...).Minimal steps once you're inside a Symfony app:
composer require atoolo/citygov-bundle
config/bundles.php (it will appear under the Atoolo\CityGov namespace).DocumentEnricher, ContentCollector, GraphQL search features). Most of your debugging will happen there.https://sitepark.github.io/atoolo-docs/develop/bundles/citygov/ — that should be your first tab open.OnlineServiceFeature. That exercises the whole pipeline (content collection → enrichment → indexing → GraphQL expose) and confirms your Solr config before you touch person search.Because the bundle is a set of Symfony services and GraphQL schema extensions, the day-to-day patterns are event-driven and schema-driven rather than controller-driven.
Content collection + document enrichment The bundle contributes index documents (one per content item; per alternative title if configured). The pattern is:
ContentCollector gathers raw content.DocumentEnricher (citygov-specific) fills fields like sp_meta_string_leikanumber, startletter, phone number, full-text content.GraphQL as your public contract
CityGov exposes OnlineServiceFeature (with an OnlineService list), teaser online-service features, and CityGov person search/suggest. This is where a Laravel backend should integrate: treat the bundle's GraphQL schema as the API surface and consume it from Laravel with Lighthouse or a plain HTTP client. Do not try to reuse the PHP classes — the value is the schema, not the code.
Person search & suggest (v1.5+ / v1.6+) Sort criteria were added in 1.6.0. Pattern: define your person index fields, expose search + suggest resolvers, and drive employee-directory UIs. From Laravel, this is just another GraphQL query with arguments — no coupling required.
Online service links via LinkFactory
v1.5.0 switched online-service link generation to the shared LinkFactory, so URLs are resolved consistently across the bundle. If you generate links yourself in Laravel, mirror this — don't hardcode link templates, or your URLs will drift from what the Symfony side produces.
Integration tip for Laravel teams: keep the Symfony app as a read/index service (Solr + GraphQL) and keep writes/UI in Laravel. This gives you the bundle's search features without importing Symfony's request lifecycle into your codebase.
AppServiceProvider — the services are wired via Symfony DI and will not resolve.atoolo/search-bundle. Release 1.5.0 explicitly bumped to ^1.14.0. Treat them as a pair and pin both; mismatched versions are the most likely cause of runtime DI errors.startletter. There is a specific fix ensuring indexing works without umlauts. If you build A–Z navigation in a Laravel frontend off a facet, normalize yourself — don't assume the index value matches the display letter.add config to archive settings chore). Documents that never "disappear" from search are usually an archive-config issue, not an indexing one.sp_meta_string_leikanumber, phone, startletter), then the enricher pipeline. If a field is wrong, it's almost always the enricher, not GraphQL.LinkFactory — in that order of frequency. Adding enrichers is the cleanest way to inject your own fields without forking the bundle.How can I help you explore Laravel packages today?