Skip to content

feat: HTML landing page#70

Merged
turban merged 13 commits intomainfrom
landing-page
May 7, 2026
Merged

feat: HTML landing page#70
turban merged 13 commits intomainfrom
landing-page

Conversation

@turban
Copy link
Copy Markdown
Contributor

@turban turban commented May 7, 2026

Closes #68.

Screenshot 2026-05-07 at 13 59 28

What

`GET /` now returns an HTML landing page. `GET /?f=json` or a request with `Accept: application/json` returns the existing JSON `RootResponse` — the same content negotiation pattern used by TiTiler and OGC APIs.

Landing page content

  • Instance status — configured extent (name, id, bbox, country code) or a setup prompt if none is configured
  • Datasets table — all ingested datasets with variable, period type, temporal coverage, and publication status; a setup prompt if nothing has been ingested yet
  • Navigation links
  • Version badge in the header showing the current package version (`0.1.0a1`)

Implementation

  • Template at `src/climate_api/templates/landing_page.html` — self-contained HTML/CSS, no external CDN dependencies, bundled as package data and loaded via `importlib.resources`
  • `src/climate_api/system/templates.py` owns all root-resource representations: template loading/caching, content negotiation (`wants_json`), HTML rendering (`render_landing`), JSON navigation document (`root_json`), cached app version, and the OpenAPI `responses` schema constant. `routes.py` contains only the route handlers.
  • Content negotiation respects RFC 7231 q-values: `Accept: application/json, text/html` → JSON; `Accept: text/html;q=1.0, application/json;q=0.9` → HTML
  • Version resolved once at import time via `importlib.metadata.version("climate-api")` with a `PackageNotFoundError` fallback
  • Exception handling in `render_landing` distinguishes expected config gaps (`ValueError` from extent) from unexpected errors (logged via `_log.exception`)
  • All template links use `{{ base }}` prefix so the page works correctly behind a reverse proxy subpath
  • `jinja2` added as an explicit dependency (was already a transitive dep via Starlette)

GET / now returns an HTML landing page showing the configured extent,
ingested datasets with their temporal coverage and publication status,
and navigation links to /maps, /docs, /ogcapi/, and /stac/catalog.json.

GET /?f=json or Accept: application/json returns the existing JSON
RootResponse, following the TiTiler / OGC API content negotiation pattern.

The HTML template is self-contained (no external CDN) and is bundled as
package data under src/climate_api/data/templates/index.html, loaded via
importlib.resources so it works in both dev and pip-installed deployments.
Jinja2 is added as an explicit dependency (was already a transitive dep
via Starlette).
@turban turban marked this pull request as draft May 7, 2026 10:13
turban added 5 commits May 7, 2026 12:52
routes.py now only contains route handlers. Template loading, format
negotiation (wants_json), and page rendering live in templates.py —
a shared home for all server-rendered HTML pages, ready for the
management UI (issue #72) to add to without touching routes.py.
data/ holds static data assets (YAML configs, pygeoapi base config).
Templates are code-adjacent rendering artifacts and belong in their
own top-level templates/ directory, consistent with Flask/Django convention.
@turban turban changed the title feat: HTML landing page on / with ?f=json JSON fallback feat: HTML landing page May 7, 2026
@turban turban requested a review from Copilot May 7, 2026 11:07

This comment was marked as resolved.

turban added 4 commits May 7, 2026 13:16
- Cache app version at import time instead of per-request metadata lookup
- Add PackageNotFoundError fallback for editable/dev installs
- Declare explicit responses dict on GET / for accurate OpenAPI docs
- Fix get_template docstring (data/templates/ -> templates/)
- Narrow exception handling in render_landing; log unexpected errors
- Pass base URL into template; prefix all hardcoded absolute links
- Add OGC API link to Explore section

This comment was marked as resolved.

@turban turban requested a review from abyot May 7, 2026 12:02
@turban turban marked this pull request as ready for review May 7, 2026 12:32
@turban turban merged commit 9ca261b into main May 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTML landing page on /

3 participants