From c4a8402840a2002cb802cb59f1d2c89fc9113f2e Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Wed, 30 Sep 2026 11:52:00 +0100 Subject: [PATCH] Convert project docs from mkdoc to myst-sphinx --- .github/workflows/build_docs.yaml | 4 +- .gitignore | 3 ++ docs/Makefile | 20 +++++++ docs/assets/custom.css | 29 ++++++++++ docs/blog/.authors.yml | 14 ----- docs/blog/index.md | 7 +++ docs/blog/posts/pixi.md | 12 ++--- docs/blog/posts/rattler_build.md | 12 ++--- docs/blog/posts/repack_emscripten.md | 13 ++--- docs/blog/posts/rust.md | 13 ++--- docs/blog/posts/updates.md | 14 ++--- docs/conf.py | 58 ++++++++++++++++++++ docs/development/conda_build_config.md | 6 +-- docs/development/local_builds.md | 5 +- docs/index.md | 75 +++++++++++++------------- docs/make.bat | 35 ++++++++++++ docs/project/credits.md | 1 + docs/project/get_involved.md | 2 +- docs/usage/jupyterlite.md | 9 ++-- docs/usage/package_server.md | 20 +++---- docs/usage/qtapp.md | 23 ++++---- mkdocs.yml | 53 ------------------ pixi.toml | 22 ++++---- 23 files changed, 260 insertions(+), 190 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/assets/custom.css delete mode 100644 docs/blog/.authors.yml create mode 100644 docs/conf.py create mode 100644 docs/make.bat delete mode 100644 mkdocs.yml diff --git a/.github/workflows/build_docs.yaml b/.github/workflows/build_docs.yaml index 957735c0046..b728a759d88 100644 --- a/.github/workflows/build_docs.yaml +++ b/.github/workflows/build_docs.yaml @@ -38,7 +38,7 @@ jobs: # BUILD ################################################################ - name: Build docs - run: pixi run docs-build -d docs_build + run: pixi run docs-build ################################################################ # UPLOAD @@ -46,7 +46,7 @@ jobs: - name: Upload Pages artifact uses: actions/upload-pages-artifact@v5 with: - path: docs_build + path: docs/_build/html/ deploy: # only run on main branch diff --git a/.gitignore b/.gitignore index be61d0560e9..21666574a88 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ output/ # emscripten forge install emscripten_forge_emsdk_install/ + +# docs output +docs/_build diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000000..d4bb2cbb9ed --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/assets/custom.css b/docs/assets/custom.css new file mode 100644 index 00000000000..4bca75de423 --- /dev/null +++ b/docs/assets/custom.css @@ -0,0 +1,29 @@ +img.banner { + display: block; + width: 90%; + margin: 0 auto 2em; +} + +/* Smaller logo at the top of the primary sidebar */ +.navbar-brand .logo__image { + width: 50%; +} + +/* Larger site name below the logo, shrinking to stay on one line in a narrow sidebar */ +.navbar-brand { + container-type: inline-size; +} + +.navbar-brand .logo__title { + font-size: min(1.6rem, 11.5cqi); + white-space: nowrap; +} + +/* Links and selected items in orange */ +html[data-theme="light"] { + --pst-color-primary: #ff6e42; +} + +html[data-theme="dark"] { + --pst-color-primary: #ff764d; +} diff --git a/docs/blog/.authors.yml b/docs/blog/.authors.yml deleted file mode 100644 index e7aa3a39973..00000000000 --- a/docs/blog/.authors.yml +++ /dev/null @@ -1,14 +0,0 @@ -authors: - derthorsten: - name: Dr. Thorsten Beier - description: main author of emscripten-forge - avatar: https://avatars.githubusercontent.com/u/904752?v=4 # Author avatar - slug: DerThorsten # Author profile slug - url: https://github.com/DerThorsten # Author website URL - - wolfv: - name: Wolf Vollprecht - description: main author of emscripten-forge - avatar: https://avatars.githubusercontent.com/u/885054?v=4 - slug: wolfv # Author profile slug - url: https://prefix.dev # Author website URL \ No newline at end of file diff --git a/docs/blog/index.md b/docs/blog/index.md index e69de29bb2d..2855247475b 100644 --- a/docs/blog/index.md +++ b/docs/blog/index.md @@ -0,0 +1,7 @@ +# Blog + +```{postlist} +:date: "%Y-%m-%d" +:excerpts: +:expand: Read more… +``` diff --git a/docs/blog/posts/pixi.md b/docs/blog/posts/pixi.md index ac362f5c552..29700cad1cd 100644 --- a/docs/blog/posts/pixi.md +++ b/docs/blog/posts/pixi.md @@ -1,11 +1,7 @@ ---- -date: 2024-05-10 -category: - - rust - -authors: - - derthorsten ---- +```{post} 2024-05-10 +:author: derthorsten +:category: rust +``` # Local builds with `pixi` diff --git a/docs/blog/posts/rattler_build.md b/docs/blog/posts/rattler_build.md index 1a1cb92c5bd..23af5537d53 100644 --- a/docs/blog/posts/rattler_build.md +++ b/docs/blog/posts/rattler_build.md @@ -1,11 +1,7 @@ ---- -date: 2024-05-10 -category: - - rust - -authors: - - derthorsten ---- +```{post} 2024-05-10 +:author: derthorsten +:category: rust +``` # Goodby boa, welcome rattler-build diff --git a/docs/blog/posts/repack_emscripten.md b/docs/blog/posts/repack_emscripten.md index 3332facf3fa..b2b6d8ed6ac 100644 --- a/docs/blog/posts/repack_emscripten.md +++ b/docs/blog/posts/repack_emscripten.md @@ -1,12 +1,7 @@ ---- -date: 2024-05-24 -category: - - rust - -authors: - - derthorsten - - wolfv ---- +```{post} 2024-05-24 +:author: derthorsten, wolfv +:category: rust +``` # Emscripten is now a proper package diff --git a/docs/blog/posts/rust.md b/docs/blog/posts/rust.md index 2fb846c880b..2167c53e273 100644 --- a/docs/blog/posts/rust.md +++ b/docs/blog/posts/rust.md @@ -1,12 +1,7 @@ ---- -date: 2024-05-10 -category: - - rust - - python - -authors: - - derthorsten ---- +```{post} 2024-05-10 +:author: derthorsten +:category: rust, python +``` # Rust/PyO3 Support diff --git a/docs/blog/posts/updates.md b/docs/blog/posts/updates.md index 475fcd9f743..5d6cebd33c3 100644 --- a/docs/blog/posts/updates.md +++ b/docs/blog/posts/updates.md @@ -1,13 +1,7 @@ ---- -date: 2025-04-30 -category: - - server - - python - - compiler - -authors: - - derthorsten ---- +```{post} 2025-04-30 +:author: derthorsten +:category: server, python, compiler +``` # Major updates diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000000..0389e0e525c --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,58 @@ +import shutil +from pathlib import Path + +project = 'Emscripten-forge' +author = 'Emscripten-forge maintainers' +copyright = '2026' + +extensions = [ + "myst_parser", + "ablog", +] + +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# Blog: any .md file in blog/posts is a post, ordered by the date in its {post} directive +blog_post_pattern = "blog/posts/*" +blog_title = f"{project} blog" +blog_authors = { + "derthorsten": ("Dr. Thorsten Beier", "https://github.com/DerThorsten"), + "wolfv": ("Wolf Vollprecht", "https://prefix.dev"), +} +post_date_format = "%Y-%m-%d" +post_date_format_short = "%Y-%m-%d" + +_book_sidebar = ["navbar-logo.html", "icon-links.html", "search-button-field.html", "sbt-sidebar-nav.html"] +_blog_widgets = ["ablog/categories.html", "ablog/authors.html", "ablog/archives.html"] + +html_css_files = ["custom.css"] +html_static_path = ['assets'] +html_sidebars = { + "blog/posts/*": _book_sidebar[:3] + ["ablog/postcard.html"] + _book_sidebar[3:], + "blog/index": _book_sidebar + _blog_widgets, + "blog/archive": _book_sidebar + _blog_widgets, + "blog/archive/**": _book_sidebar + _blog_widgets, +} +html_theme = "sphinx_book_theme" +html_theme_options = { + "logo": { + "alt_text": "Emscripten-forge logo", + "image_dark": "assets/icon.svg", + "image_light": "assets/icon.svg", + "text": project, + }, + "navbar_persistent": [], + "repository_url": "https://github.com/emscripten-forge/recipes", + "use_repository_button": True, +} +html_title = project + + +def _copy_qtapp(app, exception): + """Copy docs/qtapp to the same place in the HTML output, unchanged.""" + if exception is None and app.builder.format == "html": + shutil.copytree(Path(app.srcdir) / "qtapp", Path(app.outdir) / "qtapp", dirs_exist_ok=True) + + +def setup(app): + app.connect("build-finished", _copy_qtapp) diff --git a/docs/development/conda_build_config.md b/docs/development/conda_build_config.md index 61534366f9e..698446999b1 100644 --- a/docs/development/conda_build_config.md +++ b/docs/development/conda_build_config.md @@ -53,9 +53,9 @@ Furthermore, this build-config specifies which compiler to use for each platform While conda-forge build configuration can be found [here](https://github.com/conda-forge/conda-forge-pinning-feedstock/blob/main/recipe/conda_build_config.yaml), we **need** to maintain our own [conda-build-config](https://github.com/emscripten-forge/recipes/blob/main/conda_build_config.yaml). In particular, we need to set up the emscripten compiler. -!!! note - The conda-build-config of emscripten-forge uses the [rattler-recipes format](https://github.com/prefix-dev/rattler-build?tab=readme-ov-file#the-recipe-format) - +```{note} +The conda-build-config of emscripten-forge uses the [rattler-recipes format](https://github.com/prefix-dev/rattler-build?tab=readme-ov-file#the-recipe-format) +``` ```yaml cxx_compiler: diff --git a/docs/development/local_builds.md b/docs/development/local_builds.md index c793362cbae..8e2a3e9e588 100644 --- a/docs/development/local_builds.md +++ b/docs/development/local_builds.md @@ -14,8 +14,9 @@ pixi run setup pixi run build-emscripten-wasm32-pkg recipes/recipes_emscripten/regex ``` -!!! note - When using [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/) (WSL), some local builds might fail due to `libatomic` not being available. For cases like this, developers are required to use a full Linux machine such as a virtual machine or cloud server. +```{note} +When using [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/) (WSL), some local builds might fail due to `libatomic` not being available. For cases like this, developers are required to use a full Linux machine such as a virtual machine or cloud server. +``` ## Local builds with `rattler-build` We recommend using the `pixi` command to build packages locally. However, if you want to use `rattler-build` directly, you can do so with the following steps: diff --git a/docs/index.md b/docs/index.md index f923f5b4286..a2c95bd61f2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,46 +1,49 @@ -Emscripten-forge Banner - -# +```{image} assets/banner.svg +:alt: Emscripten-forge banner +:class: banner dark-light +``` # Introduction - Emscripten-forge is a GitHub [organization](https://github.com/emscripten-forge)/[repository](https://github.com/emscripten-forge/recipes) containing [conda recipes](https://github.com/emscripten-forge/recipes) for the `emscripten-wasm32` platform. Conda-forge does not (yet) support the `emscripten-wasm32` platform. `emscripten-forge` fills this gap by providing a channel with conda packages for the `emscripten-wasm32` platform. The recipes repository not only stores the recipe files for multiple packages, but it also builds and uploads these packages to the `emscripten-forge` channel on [prefix.dev](https://prefix.dev/channels/emscripten-forge-4x) -!!! info "Community project" - Emscripten-forge strives to be a community project, shaped by its active individual and organizational supporters. Anyone can participate in the decision-making process openly through GitHub. See [Get Involved](project/get_involved.md) to learn how to participate as an individual or organisation. - -## - -### Development - - * [Adding packages](development/adding_packages) - * [Recipe format](development/recipe_format) - * [Local builds](development/local_builds) - * [Conda build config](development/conda_build_config) - * [Troubleshooting](development/troubleshooting) - * [Code of conduct](development/code_of_conduct) - -### Usage - - * [Installing packages](usage/installing_packages) - * [JupyterLite](usage/jupyterlite) - * [Package server](usage/package_server) - * [Experimental Qt runner](usage/qtapp) - -### Project - - * [Blog](blog) - * [Get involved](project/get_involved) - * [Related projects](project/related_projects) - * [Showcase](project/showcase) - * [FAQ](project/faq) - * [Credits](project/credits) - -## +```{admonition} Community project +Emscripten-forge strives to be a community project, shaped by its active individual and organizational supporters. Anyone can participate in the decision-making process openly through GitHub. See [Get Involved](project/get_involved.md) to learn how to participate as an individual or organisation. +``` + +```{toctree} +:caption: Development +:maxdepth: 1 +development/adding_packages +development/recipe_format +development/local_builds +development/conda_build_config +development/troubleshooting +development/code_of_conduct +``` + +```{toctree} +:caption: Usage +:maxdepth: 1 +usage/installing_packages +usage/jupyterlite +usage/package_server +usage/qtapp +``` + +```{toctree} +:caption: Project +:maxdepth: 1 +blog/index +project/get_involved +project/related_projects +project/showcase +project/faq +project/credits +``` # Acknowledgements -Special thanks to [QuantStack](https://quantstack.net/), [Bloomberg](https://www.bloomberg.com/), and [prefix.dev](https://prefix.dev/), whose support made it possible to start the project. See [Credits](project/credits.md) for the current supporters and contributors. \ No newline at end of file +Special thanks to [QuantStack](https://quantstack.net/), [Bloomberg](https://www.bloomberg.com/), and [prefix.dev](https://prefix.dev/), whose support made it possible to start the project. See [Credits](project/credits.md) for the current supporters and contributors. diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000000..32bb24529f9 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/project/credits.md b/docs/project/credits.md index f4d6e1a99f3..05a0e26d857 100644 --- a/docs/project/credits.md +++ b/docs/project/credits.md @@ -1,5 +1,6 @@ # Credits +(supporters)= ## Supporters - **[QuantStack](https://quantstack.net/)**: sponsors continued development and maintenance. diff --git a/docs/project/get_involved.md b/docs/project/get_involved.md index bf3c2d9410d..592d62cb896 100644 --- a/docs/project/get_involved.md +++ b/docs/project/get_involved.md @@ -11,4 +11,4 @@ Emscripten-forge strives to be a community project. Contributions from individua Emscripten-forge is sustained by organizational supporters that contribute engineering time, maintenance, and infrastructure. If your organization would like to support the project, reach out via [GitHub](https://github.com/emscripten-forge/recipes/issues). -Current organizational supporters are listed on the [Credits](credits.md#supporters) page. +Current organizational supporters are listed on the [Credits](#supporters) page. diff --git a/docs/usage/jupyterlite.md b/docs/usage/jupyterlite.md index f5c418b5414..0b63406c110 100644 --- a/docs/usage/jupyterlite.md +++ b/docs/usage/jupyterlite.md @@ -17,11 +17,10 @@ mamba install jupyterlite-xeus ## Usage -!!! note - - Emscripten-forge provides xeus kernels for multiple languages, this document focuses on the Python kernel, namely `xeus-python`. - While the other kernels can also be installed as described below, adding custom packages is only supported for the `xeus-python` kernel - at the moment. +```{note} +Emscripten-forge provides xeus kernels for multiple languages, this document focuses on the Python kernel, namely `xeus-python`. +While the other kernels can also be installed as described below, adding custom packages is only supported for the `xeus-python` kernel at the moment. +``` ### From environment file diff --git a/docs/usage/package_server.md b/docs/usage/package_server.md index fe9dec4186a..0a4ae1edb5b 100644 --- a/docs/usage/package_server.md +++ b/docs/usage/package_server.md @@ -2,13 +2,13 @@ Emscripten-forge packages are hosted on [prefix.dev](https://prefix.dev/channels/emscripten-forge-4x). -!!! note - - To use emscripten-forge conda packages, you need to add the `emscripten-forge` channel to your conda configuration or use the `--channel` flag when installing packages, ie: - - ```bash - micromamba create -n myenv --platform=emscripten-wasm32 \ - -c https://prefix.dev/channels/emscripten-forge-4x \ - -c conda-forge \ - python numpy - ``` +````{note} +To use emscripten-forge conda packages, you need to add the `emscripten-forge` channel to your conda configuration or use the `--channel` flag when installing packages, ie: + +```bash +micromamba create -n myenv --platform=emscripten-wasm32 \ + -c https://prefix.dev/channels/emscripten-forge-4x \ + -c conda-forge \ + python numpy +``` +```` diff --git a/docs/usage/qtapp.md b/docs/usage/qtapp.md index b1a9092d0f2..eb4191bb6fd 100644 --- a/docs/usage/qtapp.md +++ b/docs/usage/qtapp.md @@ -1,18 +1,19 @@ -# Experimental Qt runner (`/qtapp/`) +# Experimental Qt runner -!!! warning "Experimental" +```{admonition} Experimental - The purpose of this page is to demonstrate that packaging certain - Qt applications for the browser via emscripten-forge is - manageable. Expect rough edges; contributions welcome. Work on - continued enhancements is ongoing. +The purpose of this page is to demonstrate that packaging certain +Qt applications for the browser via emscripten-forge is +manageable. Expect rough edges; contributions welcome. Work on +continued enhancements is ongoing. +``` A small in-browser runner for Qt6-wasm packages published to the [emscripten-forge-4x-experimental](https://prefix.dev/channels/emscripten-forge-4x-experimental) channel. Given the URL of a `.tar.bz2` package (or a locally-picked file), it fetches, unpacks, and boots the Qt app entirely client-side. -**Try it**: [/qtapp/](/qtapp/) +**Try it**: /qtapp/ ## Available apps @@ -20,16 +21,16 @@ Currently on the [emscripten-forge-4x-experimental](https://prefix.dev/channels/emscripten-forge-4x-experimental) channel: -- **[qt-calculator](/qtapp/?pkg=https%3A%2F%2Frepo.prefix.dev%2Femscripten-forge-4x-experimental%2Femscripten-wasm32%2Fqt-calculator-experimental-6.11.2-hc780342_1.tar.bz2)** — +- **qt-calculator** — Qt's own upstream calculator example ([recipe](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/qt-calculator-experimental)). -- **[qhexedit2](/qtapp/?pkg=https%3A%2F%2Frepo.prefix.dev%2Femscripten-forge-4x-experimental%2Femscripten-wasm32%2Fqhexedit2-experimental-0.9.0-hc780342_0.tar.bz2)** — +- **qhexedit2** — QHexEdit2 hex editor: open a file, view/edit bytes in hex + ASCII, save via browser download ([recipe](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/qhexedit2-experimental)). -- **[sqlitebrowser](/qtapp/?pkg=https%3A%2F%2Frepo.prefix.dev%2Femscripten-forge-4x-experimental%2Femscripten-wasm32%2Fsqlitebrowser-experimental-3.13.99-h8b281d3_3.tar.bz2)** — +- **sqlitebrowser** — DB Browser for SQLite: create tables, run queries, download `.sqlite` files ([recipe](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/sqlitebrowser-experimental)). -- **[regina](/qtapp/?pkg=https%3A%2F%2Fprefix.dev%2Femscripten-forge-4x-experimental%2Femscripten-wasm32%2Fregina-7.4.1-h99d6908_1.tar.bz2)** - +- **regina** - Regina is a software package for low-dimensional topologists, with a focus on 3-manifold and 4-manifold triangulations, knots and links, normal surfaces, and angle structures ([recipe](https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/regina)). diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index ae27c4e0542..00000000000 --- a/mkdocs.yml +++ /dev/null @@ -1,53 +0,0 @@ -site_name: Emscripten-forge -theme: - name: material - logo: assets/icon_light.svg - features: - - navigation.instant - palette: - - # Palette toggle for automatic mode - - media: "(prefers-color-scheme)" - toggle: - icon: material/brightness-auto - name: Switch to light mode - - # Palette toggle for light mode - - media: "(prefers-color-scheme: light)" - scheme: default - primary: deep orange - toggle: - icon: material/brightness-7 - name: Switch to dark mode - - # Palette toggle for dark mode - - media: "(prefers-color-scheme: dark)" - scheme: slate - primary: deep orange - toggle: - icon: material/brightness-4 - name: Switch to system preference - - - -markdown_extensions: - - admonition - - pymdownx.highlight: - anchor_linenums: true - line_spans: __span - pygments_lang_class: true - - pymdownx.inlinehilite - - pymdownx.snippets - - pymdownx.superfences - - - - -plugins: - - search - - - git-committers: - repository: emscripten-forge/recipes - branch: main - - - blog \ No newline at end of file diff --git a/pixi.toml b/pixi.toml index aae5563e61c..3b6f9af47d0 100644 --- a/pixi.toml +++ b/pixi.toml @@ -106,20 +106,24 @@ cmd = [ ############################################ # documentation feature / tasks ############################################ + + [feature.feature_documentation] [feature.feature_documentation.dependencies] -python = "3.11.*" -mkdocs = ">=1.6.0" -mkdocs-material = ">=9.5.2" -pip = "*" -mkdocs-git-committers-plugin-2 = "*" +ablog = "<1" +myst-parser = "<6" +python = "3.14.*" +sphinx = "<10" +sphinx-book-theme = "*" -[feature.feature_documentation.tasks.docs-serve] -cmd = ["mkdocs", "serve"] - [feature.feature_documentation.tasks.docs-build] -cmd = ["mkdocs", "build"] +cmd = ["make", "html"] +cwd = "docs" + +[feature.feature_documentation.tasks.docs-serve] +cmd = ["python", "-m", "http.server", "--directory", "_build/html", "8000"] +cwd = "docs" ############################################ # environments