fielddash
Documentation: https://lambdageo.github.io/fielddash/
Schema-driven dashboards for field data collection (Epicollect5), built directly from the form schema. Every question is identified by Epicollect's stable ref, and its input type (radio, checkbox, integer, location, ...) automatically dictates the filter, chart, and map representation. Modifying, adding, or reordering questions in the form does not break the dashboard, and setting up a new fieldwork survey requires only a YAML configuration file.
Ready-to-use pages:
- Overview: summary indicators, map, submissions over time, collectors.
- Highlights: curated charts configured in your YAML.
- Questions: all questions grouped by section, with search, text-field toggle, and dynamic cross-tabulation.
- Data: searchable table with CSV and Excel export.
Installation
Install it in an isolated environment rather than globally.
One environment per project (recommended). Works everywhere and is required for deployment and custom pages:
mkdir my-survey && cd my-survey
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install fielddash
fielddash init .
Nothing installed first. pipx or uv can run init once; then create the environment from the generated requirements.txt:
pipx run fielddash init my-survey # or: uvx fielddash init my-survey
cd my-survey
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
Command line only. If you never edit code in the project, pipx install fielddash (or uv tool install fielddash) is enough for init, fields and run. The streamlit_app.py generated by --deploy imports fielddash, so it needs the per-project environment above.
For development: git clone https://github.com/LambdaGeo/fielddash && cd fielddash && pip install -e ".[dev]".
Quickstart
The example project lives in the repository; it is not part of the PyPI package.
git clone https://github.com/LambdaGeo/fielddash && cd fielddash
python -m venv .venv && source .venv/bin/activate
pip install -e .
fielddash run examples/waste/project.yaml
The example uses anonymized household survey data on solid waste management (Itaqui-Bacanga, São Luís – MA) and showcases a custom project page (Recycling).
Setting Up a New Field Project
-
Scaffold the project folder:
fielddash init my-survey # project.yaml, requirements.txt, .env.example, .gitignore fielddash init my-survey --deploy # + streamlit_app.py, secrets example fielddash init my-survey --source json # offline project reading data/ (git-ignored)
Then
cp .env.example .envand fill in the project slug and the Epicollect app credentials (generated under Apps in your project's administration area):PROJECT_MY_SURVEY=project-slug MY_SURVEY_CLIENT_ID=... MY_SURVEY_CLIENT_SECRET=...
Public projects do not require credentials: simply omit
credentialsin the config. -
The generated
project.yamlstarts minimal (or write it by hand):title: "My Field Survey" source: type: epicollect project: ${PROJECT_MY_SURVEY} # slug, or the literal value credentials: MY_SURVEY
-
Inspect the form fields to select aliases, filters, and highlights:
fielddash fields project.yaml
-
Complete the configuration (all keys below are optional) and run
fielddash run project.yaml:subtitle: "Research team, institution..." fields: # alias -> ref suffix, column, or question label neighborhood: "5401ce" waste_dest: "48c35e" types: # force type (e.g. treat free text as category) neighborhood: category ignore: [created_by, "3401cb"] # hide fields (e.g. collector email) filters: [created_at, neighborhood] highlights: - {field: waste_dest, by: neighborhood, title: "Waste destination by neighborhood"} sections: # tabs on the Questions page (default: form groups) - {title: "Profile", fields: [age, gender]} map: {field: location, popup: [neighborhood]} extensions: [pages] # .py files or directories with custom pages timezone: America/Fortaleza cache_minutes: 5
(Portuguese keys from early versions —
titulo,fonte,campos, ... — still load but are deprecated and emit a warning.)
Running fielddash run folder/ will scan all .yaml files in the directory and present a project selector in the sidebar.
To work offline or test without internet access, use source: {type: json, data: ..., schema: ...} (as shown in examples/waste/project.yaml).
Using in a Custom Streamlit Script / Deployment
The dashboard can also be invoked as a Python function inside your own Streamlit app:
# streamlit_app.py
import fielddash
fielddash.dashboard("projects/") # or "projects/waste.yaml"
Relative paths are resolved relative to the current directory or the script folder. Run with:
streamlit run streamlit_app.py
Streamlit Community Cloud
- Create the project with the deploy files and try it locally:
mkdir my-survey && cd my-survey python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate pip install fielddash fielddash init . --deploy cp .env.example .env # fill in, then edit project.yaml streamlit run streamlit_app.py
- Push the folder to a GitHub repository.
.envand.streamlit/secrets.tomlare git-ignored: credentials never go to the repo. - On share.streamlit.io choose Create app, pick the repository and branch, and set
streamlit_app.pyas the main file. - Under Advanced settings → Secrets (later: Settings → Secrets) paste the content of
.streamlit/secrets.toml.example, filled in:FIELD_ACCESS_PIN = "choose-a-code" PROJECT_MY_SURVEY = "project-slug" MY_SURVEY_CLIENT_ID = "..." MY_SURVEY_CLIENT_SECRET = "..."
- Deploy, then share the app link, or
https://<your-app>.streamlit.app/?token=<code>to skip the login screen.
Notes:
- Use
source: {type: epicollect}for the cloud. Atype: jsonproject readsdata/, which is git-ignored on purpose (it may hold personal data), so it only works locally. - Without
FIELD_ACCESS_PINthe app is public: anyone with the link sees the data.
fielddash checks environment variables and .env first, then falls back to st.secrets (also resolving ${VAR} references in YAML). The data cache is shared among server sessions, so Epicollect receives at most one request per project every cache_minutes.
Restricting access
A deployed Streamlit app is public by default. Add fielddash.require_access() before fielddash.dashboard(...) (fielddash init --deploy already does) and set FIELD_ACCESS_PIN in the secrets: visitors then see a login screen, or can use a link ending in ?token=<code>. Without the variable the call does nothing.
Self-Hosted Server
fielddash run projects/ --server.port 8501 --server.headless true
(e.g., as a systemd service behind an Nginx reverse proxy with HTTPS).
Custom Pages
A project-specific page is a standard .py file listed in extensions:
from fielddash.core.registry import page
from fielddash.ui.charts import render_field
@page("Recycling", order=40)
def render(ctx):
ds = ctx.dataset
render_field(ds, ctx.df, ds.field("recycle_habit"), by=ds.field("neighborhood"))
ctx.dfprovides the data with all active sidebar filters applied.ds.field("alias")resolves the field (column, type, options) dynamically by its stable schema ref.- Additional data sources (e.g. KoboToolbox, CSV) can be registered with
@source("type").
Project Structure
fielddash/
cli.py CLI commands `fielddash init`, `run` and `fields`
scaffold.py templates and writer behind `fielddash init`
access.py `fielddash.require_access()`: optional PIN/token gate
web.py `fielddash.dashboard()`: config, cache, filters, navigation
app.py Streamlit entry point used by `fielddash run`
core/schema.py Epicollect schema parser -> list[Field], column naming, reconciliation
core/normalize.py raw entries -> typed series (ordered categories, lists, coords, datetimes)
core/config.py YAML config parser (+ ${VAR} resolution from .env and secrets)
sources/ data source plugins (@source): epicollect (API, pagination), json
ui/ dynamic filters, charts, and maps based on field types
views/ default pages (@page): Overview, Highlights, Questions, Data
examples/ example projects with anonymized datasets
tests/ pytest test suite (schema, index shifting, AppTest integration)
docs/ MkDocs site (`mkdocs serve`); docs/history/ holds the original development plan
Running Tests
pytest
Building the Documentation
pip install -e ".[docs]"
mkdocs serve # http://127.0.0.1:8000
mkdocs build --strict # what CI runs
Releasing (maintainers)
- Bump the version in
pyproject.toml,fielddash/__init__.pyandCITATION.cff. - Publish a GitHub Release:
.github/workflows/publish.ymlbuilds the package and uploads it to PyPI through Trusted Publishing (no token stored).
One-time setup on pypi.org → Publishing → Add a new pending publisher: project fielddash, owner LambdaGeo, repository fielddash, workflow publish.yml. PyPI never lets a published version be overwritten, so check with python -m build && twine check dist/* (and optionally TestPyPI) first.
Authors
- Sergio Costa (@LambdaGeo) — Universidade Federal do Maranhão (UFMA)
- André Moura Lima (@AndreMouraL) — Universidade Federal do Maranhão (UFMA)
- Ricardo Luvizotto Santos — Universidade Federal do Maranhão (UFMA)
- Marianna Basso Jorge — Universidade Federal do Maranhão (UFMA)
License
MIT — see LICENSE.
Metadata
Release files for fielddash 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fielddash-0.1.0.tar.gz | 37.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fielddash-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.5 kB
Release files / fielddash-0.1.0.tar.gz
| Download URL | fielddash-0.1.0.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb8846bde1bccbefac5a10a5ca34254381dbfa09e0027fd17f8e968f276009cb
|
|
BLAKE2b-256 checksum How to use checksums |
ca47b61f03e701c9ca169796bb2e7c50dfc5849760cf0ba8668cf190cda1ab51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / fielddash-0.1.0-py3-none-any.whl
| Download URL | fielddash-0.1.0-py3-none-any.whl |
|---|---|
| Size | 37.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ddbfb73d62c1ce4ed4eb52de098e367ef38ed429a5feed8ce3cd497307592bfe
|
|
BLAKE2b-256 checksum How to use checksums |
c73a9845696c32f2e103452ac82266639afe37ba1f2f72733e088695a036f961
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log