Species External Entity
What it is
Species External Entity, machine name species_ext, turns a species name or a Catalogue of Life taxon ID into a full Drupal entity. Its taxonomy, description, photographs, conservation status and ecological relationships are gathered live from public biodiversity APIs and then mirrored locally so pages stay fast.
It ships as two modules: species_ext, the data engine, and the optional species_ext_map, a presentation layer that turns the resolved fields into maps, charts and a photo gallery. The data engine runs in production on Biodiversa, Museo Avellonia and the Quercus Project. On the Quercus Project, its species data also feeds MADDev's Ecosystems viewer.
At a glance
- Modules
species_ext, the data engine: source plugins, resolvers, the local mirror and thespecies_xentity's field types;species_ext_map, an optional presentation layer for maps, charts and a gallery- Drupal core
- 10 or 11
- Requires
entities_ext,dynamic_mirror_base,keyand Drupal core's Link module;species_ext_mapadditionally needs the Leaflet contrib module- Entity type
species_x, keyed by the Catalogue of Life taxon ID- Rendering
- Standard, BigPipe or progressive loading, so critical fields appear at once and enrichment fields stream in without blocking the page
- Status
- Live in production on Biodiversa, Museo Avellonia and the Quercus Project
What visitors and curators see
On sites that install the optional species_ext_map submodule, a species page adds a year by year GBIF occurrence density map drawn with Leaflet, a phenology histogram, a population trend chart, a photo gallery, and a lookup and search widget; it presents only what species_ext has already resolved and makes no data calls of its own. It runs on Museo Avellonia and the Quercus Project. On the Quercus Project, species pages also carry SEO markup and a pretty /species/{name} URL rather than the entity's internal path.
A curator can mark a species featured and add their own photographs through a small local entity that sits alongside the resolved data. Those additions are never overwritten by the monthly refresh from upstream.
What it adds to a Drupal site
Entity type
species_x: an external entity keyed by the Catalogue of Life taxon ID, with fields, view modes and Manage display like any other Drupal entity, even though nobody types its content in by hand.
Source plugins
One @SpeciesSource plugin per upstream, walked by weight until one resolves: a local Catalogue of Life checklist with no network call, the Catalogue of Life API, Wikipedia, GBIF, iNaturalist, the IUCN Red List, EOL and GloBI.
Routes
/admin/config/services/species-ext: enable or disable each source, set the IUCN API key and choose the rendering mode. /species-ext/lookup: a POST endpoint for autocomplete and taxon lookup. A disambiguation route handles a name that matches more than one taxon.
Drush commands
species-ext:warm, to warm one or more species immediately; species-ext:warm-queue, to drain the warming queue immediately.
Field locking
A SpeciesDmbAdapter connects species_x fields to dynamic_mirror_base, so an editor can lock a resolved field or override it locally, through the same workflow as MADDev's other external entity modules.
Data sources and licences
- Catalogue of Life: taxonomy, the accepted name, authorship and synonyms; a local checklist table also answers common lookups with no network call
- Wikipedia: a plain-language description
- GBIF: occurrence records, distribution, phenology data and a map bounding box; for
species_ext_map, a pre-rendered occurrence density tile layer that needs no GBIF key and downloads no raw occurrence data to the server - iNaturalist: a common name, a taxon summary, photographs, observation counts and recent sightings
- IUCN Red List: conservation status, population trend, threats and habitat
- EOL (Encyclopedia of Life): a description when Wikipedia has none
- GloBI (Global Biotic Interactions): the interaction web, what a species eats, is eaten by, and lives on
A species is resolved once, the first time it is featured, and materialises into a local mirror table so pages stay fast; a cron job refreshes it monthly. Outbound calls are batched and de-duplicated through the shared request_bus, and a source that times out never blanks a value already stored. GBIF, iNaturalist and IUCN Red List keys are optional, held in the key module rather than in code; without an IUCN key the module degrades cleanly rather than failing.
Design decisions
- Field-level source resolution. Each field is resolved independently from whichever upstream supplies it, rather than one API being authoritative for the whole record.
- Weighted fallback identity. Source plugins are walked by weight and the first that resolves wins. The Catalogue of Life covers just over 80% of known species, so a species missing from it still gets an identity from Wikipedia's article title, an iNaturalist ID or a GBIF taxon key.
- Materialise once, refresh monthly. A species is stored in a local mirror the first time it is featured, rather than the page firing up to seven live API calls on every view, and is then kept current by cron rather than on demand.
- Curator edits are never clobbered. A featured flag and curator photographs are stored locally and survive every upstream refresh.
- Built to be reusable. Nothing in
species_extis specific to one site; a site's own concerns stay in that project's own module.
Start a project.
Tell us about the species or biodiversity data your Drupal site needs to show.