diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 000000000..c3c82dc2d --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,70 @@ +name: Deploy documentation to Github Pages + +on: + push: + branches: ["main"] + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +# Default to bash +defaults: + run: + shell: bash + +jobs: + # Build job + build: + runs-on: ubuntu-latest + env: + HUGO_VERSION: 0.156.0 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # fetch all history for .GitInfo and .Lastmod + submodules: recursive + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: '1.26' + - name: Setup Pages + id: pages + uses: actions/configure-pages@v4 + - name: Setup Hugo + run: | + wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ + && sudo dpkg -i ${{ runner.temp }}/hugo.deb + - name: Build with Hugo + env: + # For maximum backward compatibility with Hugo modules + HUGO_ENVIRONMENT: production + HUGO_ENV: production + run: | + hugo --gc --minify --baseURL "${{ steps.pages.outputs.base_url }}/" + working-directory: docs + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./docs/public + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/mkdocs-gh-pages.yaml b/.github/workflows/mkdocs-gh-pages.yaml deleted file mode 100644 index 83db33335..000000000 --- a/.github/workflows/mkdocs-gh-pages.yaml +++ /dev/null @@ -1,46 +0,0 @@ -name: Deploy MkDocs documentation - -on: - push: - branches: - - main - - f/mkdocs - workflow_dispatch: - -jobs: - deploy: - runs-on: ubuntu-latest - env: - ENABLED_HTMLPROOFER: ${{ vars.ENABLED_HTMLPROOFER || 'False' }} - steps: - - name: Checkout reflect-cpp repo - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - - name: Install Hatch - uses: pypa/hatch@install - with: - version: 1.12.0 - - - name: Set git credentials - run: | - git config --global user.name "${{ github.actor }}" - git config --global user.email "${{ github.actor }}@users.noreply.github.com" - - - name: Fetch latest commit from gh-pages - run: | - git fetch origin gh-pages --depth=1 - - - name: Deploy MkDocs documentation - run: hatch run default:mkdocs gh-deploy - - - - - - - diff --git a/.gitignore b/.gitignore index cc3a29265..f0dd1b30c 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,8 @@ !.github/**/*.yml !.github/**/*.yaml !benchmarks/**/*.json +!docs/**/*.yaml +!docs/**/*.mod # clangd compile_flags.txt @@ -95,6 +97,8 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +docs/public/ +*.lock # Docs site/ diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 6b9b59e93..000000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -rfl.getml.com \ No newline at end of file diff --git a/docs/assets/images/reflectcpp.png b/docs/assets/images/reflectcpp.png deleted file mode 100644 index c1ef00156..000000000 Binary files a/docs/assets/images/reflectcpp.png and /dev/null differ diff --git a/docs/assets/images/rfl-favicon-square.png b/docs/assets/images/rfl-favicon-square.png deleted file mode 100644 index ab5c67f5e..000000000 Binary files a/docs/assets/images/rfl-favicon-square.png and /dev/null differ diff --git a/docs/assets/images/rfl-favicon.png b/docs/assets/images/rfl-favicon.png deleted file mode 100644 index 475715403..000000000 Binary files a/docs/assets/images/rfl-favicon.png and /dev/null differ diff --git a/docs/assets/images/rfl-robot.jpg b/docs/assets/images/rfl-robot.jpg deleted file mode 100644 index fe8802618..000000000 Binary files a/docs/assets/images/rfl-robot.jpg and /dev/null differ diff --git a/docs/assets/images/rfl.png b/docs/assets/images/rfl.png deleted file mode 100644 index 5b546459d..000000000 Binary files a/docs/assets/images/rfl.png and /dev/null differ diff --git a/docs/assets/stylesheets/tweaks.css b/docs/assets/stylesheets/tweaks.css deleted file mode 100644 index 38fdaa749..000000000 --- a/docs/assets/stylesheets/tweaks.css +++ /dev/null @@ -1,81 +0,0 @@ -[data-md-color-primary=getml] { - --md-primary-fg-color: hsl(255 55% 60% / 1); - --md-primary-fg-color--light: hsl(255 47% 63% / 1); - --md-primary-fg-color--dark: hsl(255 52% 47% / 1); - --md-primary-bg-color: #fff; - --md-primary-bg-color--light: #ffffffb3; -} - -[data-md-color-accent=getml] { - --md-accent-fg-color: hsl(255 100% 65% / 1); - --md-accent-fg-color--transparent: hsl(255.84deg 100% 65.1% / 10.2%); - --md-accent-bg-color: #fff; - --md-accent-bg-color--light: #ffffffb3; -} - -[data-md-color-scheme="default"] > * { - --md-default-fg-color--contrast: #0e0e0e; -} - -[data-md-color-scheme="slate"] > * { - --md-default-fg-color--contrast: #f6f6f6; - /* --md-default-bg-color: hsl(216deg 27.78% 7.06%); */ -} - -[data-md-color-scheme="slate"] { - --md-hue: 230; -} - -.md-typeset blockquote { - color: var(--md-code-fg-color); - background-color: var(--md-code-bg-color--light); -} - -/* .md-typeset h1#reflect-cpp { - color: var(--md-primary-bg-color); -} */ - -.md-typeset h1, .md-typeset h2, .md-typeset h3 { - color: var(--md-default-fg-color--contrast); - font-weight: bold; -} - -.user-list { - display: flex; - flex-wrap: wrap; - margin-bottom: 2rem; -} - -.user-list-center { - justify-content: space-evenly; -} - -.user { - margin: 1em; - min-width: 7em; -} - -.user .avatar-wrapper { - width: 80px; - height: 80px; - margin: 10px auto; - overflow: hidden; - border-radius: 50%; - position: relative; -} - -.user .avatar-wrapper img { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} - -.user .title { - text-align: center; -} - -.user .count { - font-size: 80%; - text-align: center; -} \ No newline at end of file diff --git a/docs/content/_index.md b/docs/content/_index.md new file mode 100644 index 000000000..056abfd96 --- /dev/null +++ b/docs/content/_index.md @@ -0,0 +1,79 @@ +# Documentation + +## The basics + +{{< cards >}} + {{< card link="install" title="Installation" icon="book-open" subtitle="How to install reflect-cpp using vcpkg, conan, cmake or direct inclusion.">}} + {{< card link="supported_formats" title="Supported formats" icon="book-open" subtitle="What formats are supported by reflect-cpp, such as JSON, XML, msgpack, etc.">}} + {{< card link="structs" title="Structs" icon="book-open" subtitle="Recaps the motivating example in the README.">}} + {{< card link="optional_fields" title="Optional fields" icon="book-open" subtitle="For defining fields that might be absent in your serialized format.">}} + {{< card link="flatten_structs" title="Struct flattening" icon="book-open" subtitle="For making struct A inherit the fields of struct B.">}} + {{< card link="processors" title="Processors" icon="book-open" subtitle="For modifying structs before serialization and deserialization.">}} + {{< card link="field_syntax" title="The rfl::Field-syntax" icon="book-open" subtitle="An alternative syntax that allows for powerful functionalities.">}} + {{< card link="literals" title="String literals" icon="book-open" subtitle="For representing strings that can only assume a limited number of enumerated values.">}} + {{< card link="enums" title="Enums" icon="book-open" subtitle="How reflect-cpp handles C++ enums.">}} + {{< card link="variants_and_tagged_unions" title="std::variant and rfl::TaggedUnion" icon="book-open" subtitle="For structs that can be one of several formats.">}} + {{< card link="rfl_ref" title="rfl::Box and rfl::Ref" icon="book-open" subtitle="For defining recursive structures.">}} + {{< card link="timestamps" title="rfl::Timestamp and std::chrono::duration" icon="book-open" subtitle="For serializing and deserializing timestamps and durations.">}} + {{< card link="rfl_skip" title="rfl::Skip" icon="book-open" subtitle="For skipping fields during serialization and/or deserialization.">}} + {{< card link="commented" title="rfl::Commented" icon="book-open" subtitle="For adding comments to your serialized format.">}} + {{< card link="result" title="rfl::Result" icon="book-open" subtitle="For error handling without exceptions.">}} + {{< card link="standard_containers" title="Standard containers" icon="book-open" subtitle="How reflect-cpp treats containers in the standard library.">}} + {{< card link="expected" title="std::expected" icon="book-open" subtitle="For serializing and deserializing std::expected, the C++-23 result type.">}} + {{< card link="c_arrays_and_inheritance" title="C arrays and inheritance" icon="book-open" subtitle="How reflect-cpp handles C arrays and inheritance.">}} + {{< card link="bytestring" title="rfl::Bytestring" icon="book-open" subtitle="How reflect-cpp handles binary strings for formats that support them.">}} + {{< card link="number_systems" title="rfl::Binary, rfl::Hex and rfl::Oct" icon="book-open" subtitle="For expressing numbers in different formats.">}} + {{< card link="default_val" title="Default values" icon="book-open" subtitle="For defining default values for fields that might be absent.">}} + {{< card link="atomic" title="Atomic types" icon="book-open" subtitle="For serializing and deserializing atomic types.">}} +{{< /cards >}} + +## Validation + +{{< cards >}} + {{< card link="patterns" title="Regex patterns" icon="book-open" subtitle="For requiring that strings follow user-defined regex patterns.">}} + {{< card link="validating_numbers" title="Validating numbers" icon="book-open" subtitle="For imposing constraints on numbers.">}} + {{< card link="composing_validators" title="Composing validators" icon="book-open" subtitle="For defining more complex validators using operators.">}} + {{< card link="size_validation" title="Size validation" icon="book-open" subtitle="For imposing size constraints on containers.">}} + {{< card link="json_schema" title="JSON schema" icon="book-open" subtitle="For validating your schema before you send it to your C++ backend.">}} +{{< /cards >}} + +## Generic elements + +{{< cards >}} + {{< card link="object" title="rfl::Object" icon="book-open" subtitle="A map-like type representing an object with unknown field names.">}} + {{< card link="generic" title="rfl::Generic" icon="book-open" subtitle="A catch-all type that can represent almost anything.">}} + {{< card link="extra_fields" title="rfl::ExtraFields" icon="book-open" subtitle="For adding extra fields with unknown names.">}} +{{< /cards >}} + +## Custom classes + +{{< cards >}} + {{< card link="custom_classes" title="Custom classes" icon="book-open" subtitle="For custom classes with private fields.">}} + {{< card link="custom_parser" title="Custom parsers for your classes" icon="book-open" subtitle="For custom classes that you want to leave untouched.">}} +{{< /cards >}} + +## Useful helper functions and classes + +{{< cards >}} + {{< card link="replace" title="rfl::replace" icon="book-open" subtitle="For replacing one or several fields in a struct.">}} + {{< card link="as" title="rfl::as" icon="book-open" subtitle="For casting structs as other structs.">}} + {{< card link="named_tuple" title="rfl::NamedTuple" icon="book-open" subtitle="For structural typing.">}} + {{< card link="rfl_tuple" title="rfl::Tuple" icon="book-open" subtitle="An alternative to std::tuple that compiles more quickly.">}} + {{< card link="to_view" title="rfl::to_view" icon="book-open" subtitle="For accessing fields of a struct by index or name.">}} +{{< /cards >}} + +## Advanced topics + +{{< cards >}} + {{< card link="supported_formats/supporting_your_own_format" title="Supporting your own format" icon="book-open" subtitle="For supporting your own serialization and deserialization formats.">}} + {{< card link="backwards_compatability" title="Maintaining backwards compatibility" icon="book-open" subtitle="Instructions for ensuring backwards-compatible APIs.">}} + {{< card link="benchmarks" title="Benchmarks" icon="book-open" subtitle="Extensive benchmarks of popular serialization libraries.">}} +{{< /cards >}} + +## Contributing + +{{< cards >}} + {{< card link="contributing" title="How to contribute" icon="book-open" subtitle="How to contribute to reflect-cpp.">}} + {{< card link="build_docs" title="Build the documentation" icon="book-open" subtitle="How to build the documentation locally.">}} +{{< /cards >}} + diff --git a/docs/as.md b/docs/content/as.md similarity index 100% rename from docs/as.md rename to docs/content/as.md diff --git a/docs/atomic.md b/docs/content/atomic.md similarity index 100% rename from docs/atomic.md rename to docs/content/atomic.md diff --git a/docs/backwards_compatability.md b/docs/content/backwards_compatability.md similarity index 100% rename from docs/backwards_compatability.md rename to docs/content/backwards_compatability.md diff --git a/docs/benchmarks.md b/docs/content/benchmarks.md similarity index 100% rename from docs/benchmarks.md rename to docs/content/benchmarks.md diff --git a/docs/content/build_docs.md b/docs/content/build_docs.md new file mode 100644 index 000000000..43c604f10 --- /dev/null +++ b/docs/content/build_docs.md @@ -0,0 +1,122 @@ +# Building and Viewing the Documentation + +The documentation is built with [Hugo](https://gohugo.io/) using the [Hextra](https://github.com/imfing/hextra) theme. + +## Prerequisites + +- [Hugo Extended](https://gohugo.io/installation/) (version 0.124 or later) + +On macOS: + +```bash +brew install hugo +``` + +On Windows (via winget): + +```bash +winget install Hugo.Hugo +``` + +On Linux, follow the [official installation guide](https://gohugo.io/installation/). + +## Building and Viewing + +```bash +cd docs + +# Install dependencies +hugo mod tidy + +# Start the development server +hugo server --disableFastRender -p 1313 +``` + +The documentation will be available at [http://localhost:1313](http://localhost:1313). + +Hugo watches for file changes and automatically re-renders the site. Simply refresh your browser to see updates. + +## Build production version + +To build the production version, run the following: + +```bash +hugo --gc --minify --baseURL +``` + +## Editing Hugo Configuration + +The file `docs/hugo.yaml` controls the site's theme, navigation menu, and display options. + +### Theme Module + +Hugo loads the Hextra theme as a module dependency: + +```yaml +module: + imports: + - path: github.com/imfing/hextra +``` + +Do not remove this block; it is required for the theme to load. + +### Markup Settings + +Under `markup:` you can configure Markdown rendering: + +- `goldmark.renderer.unsafe: true` — allows raw HTML in markdown content (e.g., custom `
` elements). Set to `false` to strip unsafe tags. +- `highlight.noClasses: false` — enables Hextra's syntax highlighting styles. Change to `true` to output plain `
` without class attributes.
+
+### Navigation Menu
+
+The `menu.main:` section defines the top navigation bar. Each entry has:
+
+| Field     | Description                                                  |
+| --------- | ------------------------------------------------------------ |
+| `name`    | Label shown in the navbar                                    |
+| `pageRef` | Path to a page within `docs/content/` (use `/` for the root) |
+| `url`     | External URL (overrides `pageRef`)                           |
+| `weight`  | Sort order; lower values appear first                        |
+| `params`  | Extra options, e.g. `type: search` for the search button or `icon: github` for an icon |
+
+To add a new menu item:
+
+```yaml
+menu:
+  main:
+    - name: New Section
+      pageRef: /new_section
+      weight: 7
+```
+
+Ensure the corresponding page file exists under `docs/content/new_section/`.
+
+### Display Parameters
+
+Under `params:` you can control visual aspects:
+
+- `navbar.displayTitle` — show the site title in the navbar
+- `navbar.displayLogo` — show the logo in the navbar
+- `footer.displayCopyright` — show a copyright notice in the footer
+- `footer.displayPoweredBy` — show "Powered by Hugo & Hextra" in the footer
+
+All params support `true` or `false` toggles. Refer to the [Hextra documentation](https://imfing.github.io/hextra) for the full list of available options.
+
+## CI/CD: GitHub Pages Deployment
+
+The file `.github/workflows/docs.yaml` automates building and deploying the documentation to [GitHub Pages](https://getml.github.io/reflect-cpp/). It runs on every push to the `main` branch.
+
+### How It Works
+
+The workflow has two jobs:
+
+1. **`build`** — checks out the repo, installs Go and Hugo (v0.156.0), runs `hugo --gc --minify --baseURL` in the `docs/` directory, and uploads the `docs/public/` output as an artifact.
+2. **`deploy`** — takes the uploaded artifact and deploys it to GitHub Pages.
+
+### Concurrency Policy
+
+The workflow uses `concurrency.group: "pages"` to prevent overlapping deployments. In-progress builds are allowed to complete rather than being cancelled, ensuring production pages are never partially deployed.
+
+### Manual Trigger
+
+To trigger a manual deploy, go to **Actions > Deploy documentation to Github Pages** on the repository's GitHub page and click **Run workflow**.
diff --git a/docs/bytestring.md b/docs/content/bytestring.md
similarity index 100%
rename from docs/bytestring.md
rename to docs/content/bytestring.md
diff --git a/docs/c_arrays_and_inheritance.md b/docs/content/c_arrays_and_inheritance.md
similarity index 82%
rename from docs/c_arrays_and_inheritance.md
rename to docs/content/c_arrays_and_inheritance.md
index ed347f6d3..2d8f6c2b9 100644
--- a/docs/c_arrays_and_inheritance.md
+++ b/docs/content/c_arrays_and_inheritance.md
@@ -1,23 +1,22 @@
-# C Arrays and inheritance 
+# C Arrays and inheritance
 
 reflect-cpp supports fixed-size C arrays and some forms of inheritance, but only as an opt-in.
 
-We have made this design decision, because checking for C arrays and inheritance 
+We have made this design decision, because checking for C arrays and inheritance
 requires a disproportionate amount of compile time and we believe it is
 more important to reduce compile time than to support things out-of-the-box
-that most people won't need anyway. Since there are good alternatives for 
-both of these problems, it is recommended to avoid using C arrays or 
+that most people won't need anyway. Since there are good alternatives for
+both of these problems, it is recommended to avoid using C arrays or
 inheritance altogether.
 
 Note that C arrays are not the same thing as `std::array`. `std::array` is always
 supported and is the recommended alternative.
 
-!!! note "C++-26 reflection"
-
-    If you compile reflect-cpp with C++-26 reflection (see [C++26 reflection](cpp26_reflection.md)),
-    then none of the restrictions in this section apply: fixed-size C arrays and inheritance are
-    supported out of the box, no flag is required, and the fields may be spread out over
-    multiple structs.
+> [!NOTE]
+> If you compile reflect-cpp with C++-26 reflection (see [C++26 reflection](../cpp26_reflection)),
+> then none of the restrictions in this section apply: fixed-size C arrays and inheritance are
+> supported out of the box, no flag is required, and the fields may be spread out over
+> multiple structs.
 
 If you want support for these, you will have to pass the flag `-D REFLECT_CPP_C_ARRAYS_OR_INHERITANCE`
 during compilation.
@@ -28,8 +27,8 @@ Suppose you have a struct like this:
 
 ```cpp
 struct Person{
-    std::string first_name;  
-    std::string last_name; 
+    std::string first_name;
+    std::string last_name;
     int post_code[5];
 };
 ```
@@ -39,8 +38,8 @@ is to simply replace the C array with `std::array`, like this:
 
 ```cpp
 struct Person{
-    std::string first_name;  
-    std::string last_name; 
+    std::string first_name;
+    std::string last_name;
     std::array post_code;
 };
 ```
@@ -55,7 +54,7 @@ reflect-cpp supports some form of inheritance. Because we use structured binding
 retrieve the fields of a struct, there are limitations on what we can do when it comes
 to inheritance:
 
-*Every non-static data member of E must be a direct member of E or the same base class of E.* 
+*Every non-static data member of E must be a direct member of E or the same base class of E.*
 ([https://en.cppreference.com/w/cpp/language/structured_binding](https://en.cppreference.com/w/cpp/language/structured_binding))
 
 In other words, all of the fields must be inside the same struct.
@@ -105,7 +104,7 @@ struct Base {
 };
 
 struct Derived {
-  rfl::Flatten base; 
+  rfl::Flatten base;
   int y;
 };
 ```
@@ -115,5 +114,5 @@ more information.
 
 If for any reason you want to use inheritance patterns like the ones
 described above, you will make have to make sure that all of the fields
-are inside the same struct and also you will also have to pass the 
+are inside the same struct and also you will also have to pass the
 compile time flag mentioned above.
diff --git a/docs/commented.md b/docs/content/commented.md
similarity index 100%
rename from docs/commented.md
rename to docs/content/commented.md
diff --git a/docs/composing_validators.md b/docs/content/composing_validators.md
similarity index 100%
rename from docs/composing_validators.md
rename to docs/content/composing_validators.md
diff --git a/docs/contributing.md b/docs/content/contributing.md
similarity index 71%
rename from docs/contributing.md
rename to docs/content/contributing.md
index 3707d3b67..e9317f04c 100644
--- a/docs/contributing.md
+++ b/docs/content/contributing.md
@@ -1,11 +1,5 @@
----
-hide:
-    - navigation
----
-
 # How to contribute
 
-
 ## Setup
 
 Make sure includes are relative.
@@ -22,13 +16,15 @@ over
 ```
 For further details and reasoning, please refer to [#30](https://github.com/getml/reflect-cpp/issues/30).
 
+Headers should be self-contained. This will be checked by the CI.
+
 ## Compiling and running the tests
 
 reflect-cpp uses vcpkg for dependency management, including
 gtest, which is required for the tests.
 
 ```bash
-# bootstrap vcpkg if you haven't done so already 
+# bootstrap vcpkg if you haven't done so already
 git submodule update --init
 ./vcpkg/bootstrap-vcpkg.sh # Linux, macOS
 ./vcpkg/bootstrap-vcpkg.bat # Windows
@@ -56,7 +52,7 @@ To run the tests, do the following:
 To compile the tests with serialization formats other than JSON, do the following:
 
 ```bash
-cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_BSON=ON -DREFLECTCPP_CBOR=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_MSGPACK=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_TOML=ON -DREFLECTCPP_UBJSON=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
+cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_ALL_FORMATS=ON -DCMAKE_BUILD_TYPE=Release
 cmake --build build -j 4 # gcc, clang
 cmake --build build --config Release -j 4 # MSVC
 ```
@@ -67,10 +63,7 @@ To run the tests, do the following:
 ./build/tests/bson/reflect-cpp-bson-tests
 ./build/tests/cbor/reflect-cpp-cbor-tests
 ./build/tests/flexbuffers/reflect-cpp-flexbuffers-tests
-./build/tests/msgpack/reflect-cpp-msgpack-tests
-./build/tests/json/reflect-cpp-json-tests
-./build/tests/toml/reflect-cpp-toml-tests
-./build/tests/ubjson/reflect-cpp-ubjson-tests
-./build/tests/xml/reflect-cpp-xml-tests
-./build/tests/yaml/reflect-cpp-yaml-tests
-```
\ No newline at end of file
+...
+```
+
+Please make sure that the tests pass before submitting a pull request. Your changes should be covered by the tests.
diff --git a/docs/cpp26_reflection.md b/docs/content/cpp26_reflection.md
similarity index 94%
rename from docs/cpp26_reflection.md
rename to docs/content/cpp26_reflection.md
index 496df7921..be316ffd2 100644
--- a/docs/cpp26_reflection.md
+++ b/docs/content/cpp26_reflection.md
@@ -52,7 +52,7 @@ enabled by default as well, which means that `rfl::Result` is an alias for
 type, pass `-DREFLECTCPP_USE_STD_EXPECTED=OFF`.
 
 If you include the source files directly into your own build (see
-[Installation](install.md#option-4-include-source-files-into-your-own-build)), add the
+[Installation](../install)), add the
 compile definition `-DREFLECTCPP_USE_CPP26_REFLECTION` and the appropriate compiler flag
 to all translation units that include reflect-cpp.
 
@@ -63,7 +63,7 @@ to all translation units that include reflect-cpp.
 In C++-20/23 mode, fixed-size C arrays and inheritance are only supported when you pass
 the flag `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE`, and inheritance only works when all of
 the fields are inside the same struct. Refer to
-[C arrays and inheritance](c_arrays_and_inheritance.md) for details.
+*[C arrays and inheritance](../c_arrays_and_inheritance) for details.
 
 In C++-26 mode, neither restriction applies:
 
@@ -98,7 +98,7 @@ This results in the following JSON string:
 
 In C++-20/23 mode, enum values must be in the range `[RFL_ENUM_RANGE_MIN,
 RFL_ENUM_RANGE_MAX]`, where the default range is `[-256, 256]`. Refer to
-[Enums](enums.md) for details.
+*[Enums](../enums) for details.
 
 In C++-26 mode, the enumerators are read directly from the compiler, so there is no
 restriction on the range of enum values, and `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX`
@@ -122,5 +122,4 @@ cheaper.
 | Fixed-size C arrays | requires `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE` | supported out of the box |
 | Inheritance | requires `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE`, fields must be in a single struct | supported out of the box, fields may be spread over multiple structs |
 | Enum value range | restricted to `[RFL_ENUM_RANGE_MIN, RFL_ENUM_RANGE_MAX]` (default `[-256, 256]`) | no restriction |
-| `rfl::Result` | built-in type (or `std::expected` via `-DREFLECTCPP_USE_STD_EXPECTED`) | `std::expected` by default |
 | Compile time | higher | lower |
diff --git a/docs/concepts/custom_classes.md b/docs/content/custom_classes.md
similarity index 100%
rename from docs/concepts/custom_classes.md
rename to docs/content/custom_classes.md
diff --git a/docs/custom_parser.md b/docs/content/custom_parser.md
similarity index 100%
rename from docs/custom_parser.md
rename to docs/content/custom_parser.md
diff --git a/docs/default_val.md b/docs/content/default_val.md
similarity index 100%
rename from docs/default_val.md
rename to docs/content/default_val.md
diff --git a/docs/enum_descriptions.md b/docs/content/enum_descriptions.md
similarity index 100%
rename from docs/enum_descriptions.md
rename to docs/content/enum_descriptions.md
diff --git a/docs/enums.md b/docs/content/enums.md
similarity index 92%
rename from docs/enums.md
rename to docs/content/enums.md
index 5765fc261..5ab5561af 100644
--- a/docs/enums.md
+++ b/docs/content/enums.md
@@ -32,10 +32,10 @@ However, some limitations apply:
     ```cpp
     // OK - scoped enumeration
     enum class Color1 { red, green, blue, yellow };
-    
+
     // OK - scoped enumeration
     enum struct Color2 { red, green, blue, yellow };
-    
+
     // OK - unscoped enumeration
     enum Color3 { red, green, blue, yellow };
 
@@ -46,12 +46,11 @@ However, some limitations apply:
 2. Enum values must be in the range `[RFL_ENUM_RANGE_MIN, RFL_ENUM_RANGE_MAX]`. If the range is not specified, the
    default range is `[-256, 256]`.
 
-    !!! note "C++-26 reflection"
-
-        This restriction only applies when compiling reflect-cpp with C++-20 or C++-23. When
-        compiling with [C++-26 reflection](cpp26_reflection.md), the enumerators are read
-        directly from the compiler, so there is no restriction on the range of enum values,
-        and `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX` are not needed.
+    > [!NOTE]
+    > This restriction only applies when compiling reflect-cpp with C++-20 or C++-23. When
+    > compiling with [C++-26 reflection](../cpp26_reflection), the enumerators are read
+    > directly from the compiler, so there is no restriction on the range of enum values,
+    > and `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX` are not needed.
 
     - You can specify a custom range for the all enum values by defining `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX`
       before including the reflect-cpp header:
@@ -64,9 +63,9 @@ However, some limitations apply:
     - You can specify a custom range for a specific enum by defining the specialization `rfl::config::enum_range` for
       the enum type :
         ```cpp
-     
+
         enum class Color { yellow = 200, purple = 300, orange = 400 };
-     
+
         template <>
         struct rfl::config::enum_range {
           static constexpr int min = 200;
@@ -103,8 +102,8 @@ inline Color operator|(Color c1, Color c2) {
 }
 ```
 
-In this particular example, the important colors red, green, blue and yellow are all in the form of 2^N. 
-Other colors are ok as well, if they are expressed as combinations of the 2^N-colors. 
+In this particular example, the important colors red, green, blue and yellow are all in the form of 2^N.
+Other colors are ok as well, if they are expressed as combinations of the 2^N-colors.
 
 When something is a flag enum, then you can also do this:
 
@@ -178,7 +177,7 @@ By default, this also works when the number does not correspond to a
 declared enumerator (for instance, `{"color":"4"}` will produce the cast
 value `4`). If you want to reject numeric values and only accept the
 declared enumerator names, pass the
-[`rfl::EnumNamesOnly`](concepts/processors.md) processor to `read`.
+[`rfl::EnumNamesOnly`](../concepts/processors) processor to `read`.
 
 ## General-purpose enumeration utilities
 
diff --git a/docs/expected.md b/docs/content/expected.md
similarity index 98%
rename from docs/expected.md
rename to docs/content/expected.md
index 9e8dc7059..b1391e0a8 100644
--- a/docs/expected.md
+++ b/docs/content/expected.md
@@ -103,6 +103,6 @@ Schemata are generated for `std::expected` as well. The schema of `std::expected
 
 ## Relation to `rfl::Result`
 
-reflect-cpp's own result type, [`rfl::Result`](result.md), is what `rfl::json::read` and `rfl::json::write` return and operate on. Supporting `std::expected` is a separate concern: it means that you can use `std::expected` as a *data type* in your structs, which is what this section is about.
+reflect-cpp's own result type, [`rfl::Result`](../result), is what `rfl::json::read` and `rfl::json::write` return and operate on. Supporting `std::expected` is a separate concern: it means that you can use `std::expected` as a *data type* in your structs, which is what this section is about.
 
 Note that there is a CMake option `REFLECTCPP_USE_STD_EXPECTED` that makes `rfl::Result` an alias for `std::expected`. This is a separate feature from the one described in this section, but the two can be combined.
diff --git a/docs/extra_fields.md b/docs/content/extra_fields.md
similarity index 100%
rename from docs/extra_fields.md
rename to docs/content/extra_fields.md
diff --git a/docs/concepts/field_syntax.md b/docs/content/field_syntax.md
similarity index 100%
rename from docs/concepts/field_syntax.md
rename to docs/content/field_syntax.md
diff --git a/docs/flatten_structs.md b/docs/content/flatten_structs.md
similarity index 100%
rename from docs/flatten_structs.md
rename to docs/content/flatten_structs.md
diff --git a/docs/generic.md b/docs/content/generic.md
similarity index 100%
rename from docs/generic.md
rename to docs/content/generic.md
diff --git a/docs/install.md b/docs/content/install.md
similarity index 98%
rename from docs/install.md
rename to docs/content/install.md
index 4c7f1b30c..56880d47b 100644
--- a/docs/install.md
+++ b/docs/content/install.md
@@ -1,8 +1,3 @@
----
-hide:
-    - navigation
----
-
 # Installation
 
 The following compilers are supported for C++-20:
@@ -15,34 +10,6 @@ The following compilers are supported for C++-26:
 
 You can include the source files into your build or compile it using cmake and vcpkg.
 
-## Compiling with C++-26 reflection
-
-By default, reflect-cpp uses a C++-20 compatible reflection implementation, which works
-across a wide range of compilers. If you want to use the standard C++ reflection
-facilities (``, [P2996](https://wg21.link/P2996)), you can compile reflect-cpp in
-C++-26 mode instead. This is more powerful: fixed-size C arrays and inheritance are
-supported out of the box, and there are no range restrictions for enums. Refer to
-[C++26 reflection](cpp26_reflection.md) for details.
-
-To enable C++-26 reflection, pass the CMake option `REFLECTCPP_USE_CPP26_REFLECTION` and
-the compiler flag that activates reflection support in your compiler:
-
-* GCC: `-freflection`
-* Clang: `-freflection-latest` (experimental, only available in Clang builds that
-  implement [P2996](https://wg21.link/P2996), such as Bloomberg's
-  [clang-p2996](https://github.com/bloomberg/clang-p2996) fork)
-
-For example, using cmake:
-
-```bash
-cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
-cmake --build build -j 4
-```
-
-If you include the source files into your own build (see Option 4 below), also add the
-compile definition `-DREFLECTCPP_USE_CPP26_REFLECTION` and the appropriate compiler flag
-to all translation units that include reflect-cpp.
-
 ## Option 1: Using vcpkg
 
 Refer to [this port](https://vcpkg.link/ports/reflectcpp):
@@ -123,7 +90,6 @@ set(REFLECTCPP_YAML ON) # Optional
 target_link_libraries(your_project PRIVATE reflectcpp) # Link against the library
 ```
 
-
 ### Troubleshooting vcpkg
 
 vcpkg is a great, but very ambitious and complex project (just like C++ is a great, but very ambitious and complex language). Here are some of the you might run into and how to resolve them:
@@ -198,3 +164,31 @@ CMake-config package.
 
    This makes the `reflectcpp::reflectcpp` target available to your nodes
    while keeping the ROS build flow unchanged.
+
+## Compiling with C++-26 reflection
+
+By default, reflect-cpp uses a C++-20 compatible reflection implementation, which works
+across a wide range of compilers. If you want to use the standard C++ reflection
+facilities (``, [P2996](https://wg21.link/P2996)), you can compile reflect-cpp in
+C++-26 mode instead. This is more powerful: fixed-size C arrays and inheritance are
+supported out of the box, and there are no range restrictions for enums. Refer to
+[C++26 reflection](../cpp26_reflection) for details.
+
+To enable C++-26 reflection, pass the CMake option `REFLECTCPP_USE_CPP26_REFLECTION` and
+the compiler flag that activates reflection support in your compiler:
+
+* GCC: `-freflection`
+* Clang: `-freflection-latest` (experimental, only available in Clang builds that
+  implement [P2996](https://wg21.link/P2996), such as Bloomberg's
+  [clang-p2996](https://github.com/bloomberg/clang-p2996) fork)
+
+For example, using cmake:
+
+```bash
+cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
+cmake --build build -j 4
+```
+
+If you include the source files into your own build (see Option 4 below), also add the
+compile definition `-DREFLECTCPP_USE_CPP26_REFLECTION` and the appropriate compiler flag
+to all translation units that include reflect-cpp.
diff --git a/docs/json_schema.md b/docs/content/json_schema.md
similarity index 100%
rename from docs/json_schema.md
rename to docs/content/json_schema.md
diff --git a/docs/literals.md b/docs/content/literals.md
similarity index 100%
rename from docs/literals.md
rename to docs/content/literals.md
diff --git a/docs/named_tuple.md b/docs/content/named_tuple.md
similarity index 100%
rename from docs/named_tuple.md
rename to docs/content/named_tuple.md
diff --git a/docs/number_systems.md b/docs/content/number_systems.md
similarity index 100%
rename from docs/number_systems.md
rename to docs/content/number_systems.md
diff --git a/docs/object.md b/docs/content/object.md
similarity index 100%
rename from docs/object.md
rename to docs/content/object.md
diff --git a/docs/optional_fields.md b/docs/content/optional_fields.md
similarity index 99%
rename from docs/optional_fields.md
rename to docs/content/optional_fields.md
index d298b578e..752d09625 100644
--- a/docs/optional_fields.md
+++ b/docs/content/optional_fields.md
@@ -1,3 +1,4 @@
+
 # Optional fields
 
 Usually, when you set up a struct, all of the fields are required. For instance, in the previous example,
@@ -12,7 +13,7 @@ Likewise, if we read the JSON string and the field "children" is missing, that w
 But Bart doesn't have any children. After all, he's only 10 years old. To indicate to the library that the field "children" is optional,
 we can use either `std::optional`, `std::shared_ptr` or `std::unique_ptr`.
 
-If `std::optional` is `std::nullopt` or any of the smart pointers is a `nullptr`, 
+If `std::optional` is `std::nullopt` or any of the smart pointers is a `nullptr`,
 then the field will not be written to the JSON string. Likewise, when you read the JSON string, the fields will not be required. If you
 want the fields to be required, you can use the `rfl::NoOptionals` processor, please refer to the section on processors.
 
diff --git a/docs/patterns.md b/docs/content/patterns.md
similarity index 100%
rename from docs/patterns.md
rename to docs/content/patterns.md
diff --git a/docs/concepts/processors.md b/docs/content/processors.md
similarity index 100%
rename from docs/concepts/processors.md
rename to docs/content/processors.md
diff --git a/docs/replace.md b/docs/content/replace.md
similarity index 98%
rename from docs/replace.md
rename to docs/content/replace.md
index ffca4b370..3ba8ac77c 100644
--- a/docs/replace.md
+++ b/docs/content/replace.md
@@ -2,8 +2,6 @@
 
 `rfl::replace` creates a deep copy of the original struct or moves the original struct, replacing one or several fields in the process.
 
-This only works for the `rfl::Field`-syntax.
-
 In some cases, we really only want to change one or a few fields, to get from one struct to another:
 
 ```cpp
diff --git a/docs/result.md b/docs/content/result.md
similarity index 94%
rename from docs/result.md
rename to docs/content/result.md
index 567206706..f8b11969d 100644
--- a/docs/result.md
+++ b/docs/content/result.md
@@ -13,7 +13,7 @@ const auto homer = rfl::json::read(json_string);
 ```
 
 The reason is that parsing a JSON string is something that might fail. We do not know much about
-the string that put into there. It might not be a valid JSON. And even if it is a valid JSON, then it 
+the string that put into there. It might not be a valid JSON. And even if it is a valid JSON, then it
 might not conform to the assumptions that we have made about it and laid out in the type system
 in the form of various structs and containers.
 
@@ -21,7 +21,7 @@ in the form of various structs and containers.
 handling without exceptions. This is needed for two reasons:
 
 1) Exceptions are controversial, because they add another, hidden control
-path to your program that it hard to follow or predict. For this reasons, and others, the Google 
+path to your program that it hard to follow or predict. For this reasons, and others, the Google
 C++ style guide [disallows exceptions altogether](https://google.github.io/styleguide/cppguide.html#Exceptions).
 Modern programming languages like Go and Rust don't even support them in the first place. The C++
 standards committee has recognized this and introduced [std::expected](https://en.cppreference.com/w/cpp/utility/expected)
@@ -42,7 +42,7 @@ unlike `std::optional`, it does not simply contain `std::nullopt` if the operati
 it contains an `rfl::Error` with a clear error message.
 
 In laying out our structs an containers, about the the type system, we are making *requirements* about the
-JSON input we are expecting from the outside world. `rfl::json::read(...)` checks whether these requirements are met. 
+JSON input we are expecting from the outside world. `rfl::json::read(...)` checks whether these requirements are met.
 If the requirements are met, `rfl::json::read` returns T wrapped inside `rfl::Result`. If they are not met, it returns
 `rfl::Error` containing an error message explaining what went wrong.
 
@@ -62,7 +62,7 @@ The solution is to this instead:
 const auto configs = rfl::json::read>>(json_string);
 ```
 
-This means `rfl::json::read` is going to cut the end-users of your software some slack. But it also means that you, as the programmer, have to handle the fact that some of the configs might contain errors. 
+This means `rfl::json::read` is going to cut the end-users of your software some slack. But it also means that you, as the programmer, have to handle the fact that some of the configs might contain errors.
 
 Below, we will show you how to do that.
 
@@ -72,11 +72,11 @@ From the point of view of category theory, `rfl::Result` is both a functor and a
 
 This is reflected in its member functions `.transform(...)` and `.and_then(...)`.
 
-`.transform(...)` requires a function `F` of the type `T -> U`. If the `rfl::Result` contains a type `T`, 
+`.transform(...)` requires a function `F` of the type `T -> U`. If the `rfl::Result` contains a type `T`,
 then `r.transform(f)` *will* return an `rfl::Result` containing a type `U`, otherwise it will return an `rfl::Result`
 containing an error.
 
-`.and_then(...)` requires a function `F` of the type `T -> rfl::Result`. If the `rfl::Result` contains a type `T`, 
+`.and_then(...)` requires a function `F` of the type `T -> rfl::Result`. If the `rfl::Result` contains a type `T`,
 then `r.and_then(f)` *might* return an `rfl::Result` containing a type `U`, depending on whether `f` failed.
 If `r` already contained an error, then `r.and_then(f)` will surely return an `rfl::Result` containing an error.
 
@@ -105,7 +105,7 @@ Result load(const std::string& _fname) {
 
 This code works as follows: First, we read in the text file using `rfl::io::load_string`. This an operation that might fail (maybe
 the file doesn't exist, maybe it isn't readable, ...). Then we have to to parse its contents using `rfl::json::read`. Again,
-this is an operation that might fail (might not be a proper JSON, might not conform to our requirements, ...). Therefore, we 
+this is an operation that might fail (might not be a proper JSON, might not conform to our requirements, ...). Therefore, we
 have to call `.and_then(...)`.
 
 ## Retrieving values or errors
@@ -141,7 +141,7 @@ if (my_result) {
 
 `r.or_else(f)` expects a function `f` for type `Error -> rfl::Result`. It returns `r` if `r` did not contain an error and the results of `f` otherwise.
 
-`r.transform_error(f)` expects a function `f` for type `Error -> Error`. 
+`r.transform_error(f)` expects a function `f` for type `Error -> Error`.
 
 This is often used to produce better error messages:
 
@@ -154,4 +154,4 @@ return Parser::read(_r, &_var).transform_error(embellish_error);
 
 ## See also
 
-- [`std::expected`](expected.md) - The C++-23 standard result type, which is supported as a serializable data type.
+- [`std::expected`](../expected) - The C++-23 standard result type, which is supported as a serializable data type.
diff --git a/docs/rfl_ref.md b/docs/content/rfl_ref.md
similarity index 100%
rename from docs/rfl_ref.md
rename to docs/content/rfl_ref.md
diff --git a/docs/rfl_skip.md b/docs/content/rfl_skip.md
similarity index 100%
rename from docs/rfl_skip.md
rename to docs/content/rfl_skip.md
diff --git a/docs/rfl_tuple.md b/docs/content/rfl_tuple.md
similarity index 100%
rename from docs/rfl_tuple.md
rename to docs/content/rfl_tuple.md
diff --git a/docs/size_validation.md b/docs/content/size_validation.md
similarity index 100%
rename from docs/size_validation.md
rename to docs/content/size_validation.md
diff --git a/docs/standard_containers.md b/docs/content/standard_containers.md
similarity index 87%
rename from docs/standard_containers.md
rename to docs/content/standard_containers.md
index 0e0deca1c..32b51589a 100644
--- a/docs/standard_containers.md
+++ b/docs/content/standard_containers.md
@@ -2,7 +2,7 @@
 
 The serialization and deserialization of containers is handled as follows:
 
-`std::map`, `std::unordered_map`, 
+`std::map`, `std::unordered_map`,
 maps with any numeric types (integral and floating points) as keys,
 and any objects where the `ReflectionType` is either a `std::string` or
 a numeric type are treated as objects.
@@ -50,9 +50,9 @@ This will also be represented as follows:
 {"1":"Homer","2":"Simpson"}
 ```
 
-All other supported standard containers 
-(other than `std::variant`, `std::optional`, `std::unique_ptr`, `std::shared_ptr` and `std::expected`) 
+All other supported standard containers
+(other than `std::variant`, `std::optional`, `std::unique_ptr`, `std::shared_ptr` and `std::expected`)
 will be represented as arrays. Containers for which the `value_type`
-is a key-value-pair will be represented as arrays of pairs. 
+is a key-value-pair will be represented as arrays of pairs.
 
-`std::expected` is an exception to this: it is serialized as its value type, or as an object with a single `error` field. Refer to the [std::expected](expected.md) section for details.
+`std::expected` is an exception to this: it is serialized as its value type, or as an object with a single `error` field. Refer to the [std::expected](../expected) section for details.
diff --git a/docs/concepts/structs.md b/docs/content/structs.md
similarity index 94%
rename from docs/concepts/structs.md
rename to docs/content/structs.md
index cca07a616..77afafe1f 100644
--- a/docs/concepts/structs.md
+++ b/docs/content/structs.md
@@ -82,5 +82,6 @@ Person{"Bart", "Simpson", ...};
 But if you create a custom constructor, then C++ will no longer allow this kind of constructions.
 
 If you want to create the struct from one of your classes (the most like reason, you want to create custom constructors in the first place),
-you might want to check out the section on [custom classes](custom_classes.md) or [custom parsers](../custom_parser.md).
+you might want to check out the section on [custom classes](../custom_classes) or [custom parsers](../custom_parser).
+
 
diff --git a/docs/content/supported_formats/_index.md b/docs/content/supported_formats/_index.md
new file mode 100644
index 000000000..91bd2e458
--- /dev/null
+++ b/docs/content/supported_formats/_index.md
@@ -0,0 +1,75 @@
+# Supported formats
+
+reflect-cpp provides a unified reflection-based interface across different serialization formats. They are listed below:
+
+## Comparing formats
+
+When choosing a format for your use case, consider the following factors:
+
+1. **Readability**: JSON, YAML, TOML, and CSV are human-readable. Binary formats (BSON, CBOR, UBJSON, msgpack, Avro, Cap'n Proto, yas, etc.) are not.
+2. **Performance**: For raw speed, yas, msgpack, and flexbuffers are typically the fastest. Note that due to a highly efficient implementation, JSON is a lot faster than you might think.
+3. **Backwards compatibility**: Schemaless formats (JSON, YAML, TOML, BSON, CBOR, UBJSON, msgpack, Flexbuffers) tolerate structural changes better than schemaful formats.
+4. **Data structure**: Nested, hierarchical data works best with JSON, YAML, or XML. Flat, tabular data works best with CSV or Parquet.
+5. **External dependencies**: Some formats require linking to external libraries (Avro, Cap'n Proto, CBOR, msgpack, YAML, TOML, XML, BSON, Boost.Serialization, Cereal, Flexbuffers). JSON and environment variables have no external dependencies.
+
+## Textual formats
+
+Human-readable formats for configuration, data exchange, and legacy integration.
+
+{{< cards >}}
+  {{< card link="json" title="JSON" icon="book-open" subtitle="Out-of-the-box support via yyjson. Standard for web APIs and data interchange." >}}
+  {{< card link="yaml" title="YAML" icon="book-open" subtitle="Textual format with an emphasis on readability. Widely used in Docker, Kubernetes, and CI/CD configuration." >}}
+  {{< card link="toml" title="TOML" icon="book-open" subtitle="Textual format with an emphasis on readability. Popular for application configuration in the Rust ecosystem." >}}
+  {{< card link="csv" title="CSV" icon="book-open" subtitle="Tabular textual format. The universal interchange format for spreadsheets, databases, and ETL pipelines." >}}
+  {{< card link="xml" title="XML" icon="book-open" subtitle="Textual format used in many legacy projects. Dominates enterprise SOAP APIs and document formats." >}}
+{{< /cards >}}
+
+## JSON-like binary formats
+
+Compact binary formats designed for small payload sizes and interoperability.
+
+{{< cards >}}
+  {{< card link="bson" title="BSON" icon="book-open" subtitle="JSON-like binary format. Native storage format for MongoDB." >}}
+  {{< card link="cbor" title="CBOR" icon="book-open" subtitle="JSON-like binary format. IETF-standardized (RFC 7049); widely used in IoT and JWT tokens." >}}
+  {{< card link="msgpack" title="msgpack" icon="book-open" subtitle="JSON-like binary format. Optimized for speed; popular in RPC frameworks like gRPC. Very fast." >}}
+  {{< card link="ubjson" title="UBJSON" icon="book-open" subtitle="JSON-like binary format. A more efficient binary replacement for JSON in network protocols." >}}
+{{< /cards >}}
+
+## Schemaful binary formats
+
+Binary formats that require a predefined schema, enabling strict type safety and efficient serialization.
+
+{{< cards >}}
+  {{< card link="avro" title="Avro" icon="book-open" subtitle="Schemaful binary format. Widely used in big data pipelines (Apache Hadoop, Kafka) for schema evolution." >}}
+  {{< card link="capnproto" title="Cap'n Proto" icon="book-open" subtitle="Schemaful binary format. Designed for game networking and IPC." >}}
+{{< /cards >}}
+
+## Tabular formats
+
+Formats designed for storing collections of records, optimized for analytical workloads and data exchange.
+
+{{< cards >}}
+  {{< card link="csv" title="CSV" icon="book-open" subtitle="Tabular textual format. The universal format for spreadsheets, databases, and ETL pipelines." >}}
+  {{< card link="parquet" title="Parquet" icon="book-open" subtitle="Tabular binary format. Columnar storage of choice for data warehousing and Apache Spark." >}}
+{{< /cards >}}
+
+## C++ serialization libraries
+
+C++-native serialization libraries offering compact, high-performance binary output.
+
+{{< cards >}}
+  {{< card link="cereal" title="Cereal" icon="book-open" subtitle="C++ serialization library with multiple formats. Commonly used in game development and scientific computing for checkpoint/restart workflows." >}}
+  {{< card link="flexbuffers" title="Flexbuffers" icon="book-open" subtitle="Schema-less version of flatbuffers, binary format. Ideal for game assets and dynamic data without code generation. Very fast." >}}
+  {{< card link="yas" title="yas" icon="book-open" subtitle="Very fast and compact serialization library. Targets applications where speed and memory matter. Very fast." >}}
+  {{< card link="boost_serialization" title="Boost.Serialization" icon="book-open" subtitle="Streaming binary format with archive interop. Integrates with the broader Boost ecosystem for object graph serialization." >}}
+{{< /cards >}}
+
+## Other
+
+Non-serialization interfaces for configuration and command-line integration.
+
+{{< cards >}}
+  {{< card link="cli" title="Command Line Interface" icon="book-open" subtitle="Parse command-line arguments into a reflectable struct." >}}
+  {{< card link="env" title="Environment Variables" icon="book-open" subtitle="Flat, hierarchical key-value store for configuration. Standard for containerized and cloud-native applications." >}}
+  {{< card link="supporting_your_own_format" title="Supporting Your Own Format" icon="book-open" subtitle="Extend reflect-cpp to support custom serialization formats." >}}
+{{< /cards >}}
diff --git a/docs/supported_formats/avro.md b/docs/content/supported_formats/avro.md
similarity index 99%
rename from docs/supported_formats/avro.md
rename to docs/content/supported_formats/avro.md
index cd6686038..be8cea9ae 100644
--- a/docs/supported_formats/avro.md
+++ b/docs/content/supported_formats/avro.md
@@ -1,4 +1,9 @@
-# Avro 
+---
+breadcrumbs: true
+---
+
+
+# Avro
 
 For Avro support, you must also include the header `` and link to the [avro-c](https://avro.apache.org/docs/1.11.1/api/c/) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_AVRO=ON` to cmake.
diff --git a/docs/supported_formats/boost_serialization.md b/docs/content/supported_formats/boost_serialization.md
similarity index 99%
rename from docs/supported_formats/boost_serialization.md
rename to docs/content/supported_formats/boost_serialization.md
index 191ca61d4..40acd1fbd 100644
--- a/docs/supported_formats/boost_serialization.md
+++ b/docs/content/supported_formats/boost_serialization.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # Boost.Serialization
 
 For Boost.Serialization support, you must also include the header `` and link to the [Boost.Serialization](https://www.boost.org/doc/libs/release/libs/serialization/) library.
diff --git a/docs/supported_formats/bson.md b/docs/content/supported_formats/bson.md
similarity index 98%
rename from docs/supported_formats/bson.md
rename to docs/content/supported_formats/bson.md
index 63c477d2b..fa38a33e5 100644
--- a/docs/supported_formats/bson.md
+++ b/docs/content/supported_formats/bson.md
@@ -1,4 +1,8 @@
-# BSON 
+---
+breadcrumbs: true
+---
+
+# BSON
 
 For BSON support, you must also include the header `` and link to the [libbson](https://github.com/mongodb/mongo-c-driver) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_BSON=ON` to cmake. If you are using vcpkg, there
diff --git a/docs/supported_formats/capnproto.md b/docs/content/supported_formats/capnproto.md
similarity index 99%
rename from docs/supported_formats/capnproto.md
rename to docs/content/supported_formats/capnproto.md
index 0bd55e664..63f0a372b 100644
--- a/docs/supported_formats/capnproto.md
+++ b/docs/content/supported_formats/capnproto.md
@@ -1,4 +1,8 @@
-# Cap'n Proto 
+---
+breadcrumbs: true
+---
+
+# Cap'n Proto
 
 For Cap'n Proto support, you must also include the header `` and link to the [capnproto](https://capnproto.org) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_CAPNPROTO=ON` to cmake. If you are using vcpkg or Conan, there
diff --git a/docs/supported_formats/cbor.md b/docs/content/supported_formats/cbor.md
similarity index 98%
rename from docs/supported_formats/cbor.md
rename to docs/content/supported_formats/cbor.md
index 4f72a31d5..dc73a5d63 100644
--- a/docs/supported_formats/cbor.md
+++ b/docs/content/supported_formats/cbor.md
@@ -1,6 +1,10 @@
-# CBOR 
+---
+breadcrumbs: true
+---
 
-For CBOR support, you must also include the header `` and include the [jsoncons](https://github.com/danielaparker/jsoncons) library. 
+# CBOR
+
+For CBOR support, you must also include the header `` and include the [jsoncons](https://github.com/danielaparker/jsoncons) library.
 Note that it is header-only. Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_CBOR=ON` to cmake. If you are using vcpkg or Conan, there
 should be an appropriate feature (vcpkg) or option (Conan) that will abstract this away for you.
 
diff --git a/docs/supported_formats/cereal.md b/docs/content/supported_formats/cereal.md
similarity index 99%
rename from docs/supported_formats/cereal.md
rename to docs/content/supported_formats/cereal.md
index e45d21fc9..f01c831d9 100644
--- a/docs/supported_formats/cereal.md
+++ b/docs/content/supported_formats/cereal.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # Cereal
 
 For Cereal support, you must also include the header `` and link to the [Cereal](https://uscilab.github.io/cereal/) library.
diff --git a/docs/cli.md b/docs/content/supported_formats/cli.md
similarity index 99%
rename from docs/cli.md
rename to docs/content/supported_formats/cli.md
index b16555511..aeeb9d83e 100644
--- a/docs/cli.md
+++ b/docs/content/supported_formats/cli.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # rfl::cli — Command-Line Argument Parser
 
 Parse `argc`/`argv` into any reflectable struct via `rfl::cli::read(argc, argv)`.
diff --git a/docs/supported_formats/csv.md b/docs/content/supported_formats/csv.md
similarity index 99%
rename from docs/supported_formats/csv.md
rename to docs/content/supported_formats/csv.md
index eeb2fb6e3..5dc3323ae 100644
--- a/docs/supported_formats/csv.md
+++ b/docs/content/supported_formats/csv.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # csv
 
 For CSV support, include the header `` and link to the [Apache Arrow](https://arrow.apache.org/) library.
diff --git a/docs/supported_formats/env.md b/docs/content/supported_formats/env.md
similarity index 99%
rename from docs/supported_formats/env.md
rename to docs/content/supported_formats/env.md
index 47297a98d..4eb513287 100644
--- a/docs/supported_formats/env.md
+++ b/docs/content/supported_formats/env.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # Environment Variables
 
 For environment variable support, you must also include the header ``.
diff --git a/docs/supported_formats/flexbuffers.md b/docs/content/supported_formats/flexbuffers.md
similarity index 99%
rename from docs/supported_formats/flexbuffers.md
rename to docs/content/supported_formats/flexbuffers.md
index 8605805a8..68ebd3ae5 100644
--- a/docs/supported_formats/flexbuffers.md
+++ b/docs/content/supported_formats/flexbuffers.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # Flexbuffers
 
 For flexbuffers support, you must also include the header `` and link to the [flatbuffers](https://github.com/google/flatbuffers) library.
diff --git a/docs/supported_formats/json.md b/docs/content/supported_formats/json.md
similarity index 99%
rename from docs/supported_formats/json.md
rename to docs/content/supported_formats/json.md
index ad0ca1539..e85d91c39 100644
--- a/docs/supported_formats/json.md
+++ b/docs/content/supported_formats/json.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # JSON
 
 For JSON support, you must also include the header ``.
diff --git a/docs/supported_formats/msgpack.md b/docs/content/supported_formats/msgpack.md
similarity index 98%
rename from docs/supported_formats/msgpack.md
rename to docs/content/supported_formats/msgpack.md
index ac363d9ad..134c242aa 100644
--- a/docs/supported_formats/msgpack.md
+++ b/docs/content/supported_formats/msgpack.md
@@ -1,4 +1,8 @@
-# msgpack 
+---
+breadcrumbs: true
+---
+
+# msgpack
 
 For msgpack support, you must also include the header `` and link to the [msgpack-c](https://github.com/msgpack/msgpack-c) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_MSGPACK=ON` to cmake. If you are using vcpkg or Conan, there
diff --git a/docs/supported_formats/parquet.md b/docs/content/supported_formats/parquet.md
similarity index 99%
rename from docs/supported_formats/parquet.md
rename to docs/content/supported_formats/parquet.md
index b4723061a..622d1df32 100644
--- a/docs/supported_formats/parquet.md
+++ b/docs/content/supported_formats/parquet.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # parquet
 
 For Parquet support, you must also include the header `` and link to the [Apache Arrow](https://arrow.apache.org/) and [Apache Parquet](https://parquet.apache.org/) libraries.
@@ -142,7 +146,7 @@ This will automatically convert field names from snake_case to camelCase during
 The following processors are **NOT supported** and will cause compilation errors:
 
 - `rfl::AddTagsToVariants` - Cannot be used for tabular data
-- `rfl::NoOptionals` - Cannot be used for tabular data  
+- `rfl::NoOptionals` - Cannot be used for tabular data
 - `rfl::DefaultIfMissing` - Cannot be used for tabular data
 - `rfl::NoExtraFields` - Cannot be used for tabular data
 - `rfl::NoFieldNames` - Cannot be used for tabular data
diff --git a/docs/supported_formats/supporting_your_own_format.md b/docs/content/supported_formats/supporting_your_own_format.md
similarity index 98%
rename from docs/supported_formats/supporting_your_own_format.md
rename to docs/content/supported_formats/supporting_your_own_format.md
index b3f7ba71a..86e8cc43a 100644
--- a/docs/supported_formats/supporting_your_own_format.md
+++ b/docs/content/supported_formats/supporting_your_own_format.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # Supporting your own format
 
 In order to support your own serialization format, you need to implement a reader and a writer on top of whatever serialization libary
@@ -28,7 +32,7 @@ rfl::Result read(const std::string& _str) {
     const InputVarType root = str_to_input_var(_str);
 
     // You can pass variables to the constructor, if necessary
-    const auto r = Reader(...); 
+    const auto r = Reader(...);
 
     return YourParser::read(r, root);
 }
@@ -51,7 +55,7 @@ You should probably just copy + paste this into your own code and fill in the bl
 
 As a reference, you can take a look at how this is done for JSON: https://github.com/getml/reflect-cpp/tree/main/include/rfl/json
 
-## Implementing your own writer 
+## Implementing your own writer
 
 Because writers are somewhat simpler, we will start with them.
 
@@ -152,7 +156,7 @@ struct Writer {
 };
 ```
 
-## Implementing your own reader 
+## Implementing your own reader
 
 Any Reader needs to define the following:
 
@@ -165,7 +169,7 @@ Any Reader needs to define the following:
    whether the class in question as a custom constructor, which might
    be called something like `from_json_obj(...)`. If you do not want to
    support this functionality, just set it to false.
-   
+
 It also needs to support the following methods:
 
 ```cpp
@@ -216,7 +220,7 @@ struct Reader {
     std::optional read_array(const ArrayReader& _array_reader,
                                     const InputArrayType& _arr) const noexcept {...}
 
-    /// Iterates through an object and inserts the key-value pairs into the object 
+    /// Iterates through an object and inserts the key-value pairs into the object
     /// reader. See below for a more detailed explanation.
     template 
     std::optional read_object(const ObjectReader& _object_reader,
@@ -248,7 +252,7 @@ std::optional read(const InputVarType& _var) const noexcept;
 ```
 
 Within your implementation of `read_array`, you must iterate through the array passed
-to the function and then insert the resulting values into `array_reader.read`. If 
+to the function and then insert the resulting values into `array_reader.read`. If
 `array_reader.read` returns an error, then you must return that error immediately.
 
 ## `read_object`
@@ -266,11 +270,11 @@ to the function and then insert the resulting key-value-pairs into `object_reade
 
 ## Additional requirements for schemaful formats
 
-Schemaful formats, like Apache Avro or Cap'n Proto, 
+Schemaful formats, like Apache Avro or Cap'n Proto,
 are somewhat more complicated than schemaless ones. There are additional factors
 to consider which do not apply schemaless formats:
 
-1. Schemaful formats needs to differentiate between *objects*, for which 
+1. Schemaful formats needs to differentiate between *objects*, for which
    the field names are known at compile time and *maps*, for which the
    field names are not known at compile time. In schemaless formats, there
    is no differentiation.
@@ -294,7 +298,7 @@ struct Writer {
   using OutputObjectType = ...;
   using OutputUnionType = ...;
   using OutputVarType = ...;
-  
+
   /// Sets an empty map as the root element of the document.
   /// Some serialization formats require you to pass the expected size in
   /// advance. If you are not working with such a format, you can ignore the
@@ -386,7 +390,7 @@ struct Writer {
   /// OutputVarType containing the new value.
   template 
   OutputVarType add_value_to_map(const std::string_view& _name, const T& _var,
-                                 OutputMapType* _parent) const noexcept; 
+                                 OutputMapType* _parent) const noexcept;
 
   /// Adds a basic value (bool, numeric, string) to an existing union. The key
   /// or name of the field is signified by `name`. Returns an
@@ -398,7 +402,7 @@ struct Writer {
   /// Signifies to the writer that we do not want to add any further elements to
   /// this map. Some serialization formats require this. If you are working
   /// with a serialization format that doesn't, just leave the function empty.
-  void end_map(OutputMapType* _obj) const noexcept; 
+  void end_map(OutputMapType* _obj) const noexcept;
 
 };
 ```
@@ -422,7 +426,7 @@ struct Reader {
   /// the field names are known at compile time and maps, for which the
   /// field names are not known at compile time.
   rfl::Result to_map(const InputVarType& _var) const noexcept;
-    
+
   /// read_map works exactly the same as read_object in schemaless formats.
   template 
   std::optional read_map(const MapReader& _map_reader,
@@ -432,9 +436,10 @@ struct Reader {
   rfl::Result to_union(const InputVarType& _var) const noexcept;
 
   /// read_union needs to be able to take an InputUnionType and return the corresponding
-  /// variant (like std::variant or rfl::Variant). 
+  /// variant (like std::variant or rfl::Variant).
   template 
   rfl::Result read_union(
       const InputUnionType& _union) const noexcept;
 };
 ```
+
diff --git a/docs/supported_formats/toml.md b/docs/content/supported_formats/toml.md
similarity index 98%
rename from docs/supported_formats/toml.md
rename to docs/content/supported_formats/toml.md
index 1abd7e254..c5656b966 100644
--- a/docs/supported_formats/toml.md
+++ b/docs/content/supported_formats/toml.md
@@ -1,4 +1,8 @@
-# TOML 
+---
+breadcrumbs: true
+---
+
+# TOML
 
 For TOML support, you must also include the header `` and include the [toml++](https://github.com/marzer/tomlplusplus) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_TOML=ON` to cmake. If you are using vcpkg or Conan, there
diff --git a/docs/supported_formats/ubjson.md b/docs/content/supported_formats/ubjson.md
similarity index 98%
rename from docs/supported_formats/ubjson.md
rename to docs/content/supported_formats/ubjson.md
index 7f061e6e9..4e0b3334d 100644
--- a/docs/supported_formats/ubjson.md
+++ b/docs/content/supported_formats/ubjson.md
@@ -1,6 +1,10 @@
-# UBJSON 
+---
+breadcrumbs: true
+---
 
-For UBJSON support, you must also include the header `` and include the [jsoncons](https://github.com/danielaparker/jsoncons) library. 
+# UBJSON
+
+For UBJSON support, you must also include the header `` and include the [jsoncons](https://github.com/danielaparker/jsoncons) library.
 Note that it is header-only. Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_UBJSON=ON` to cmake. If you are using vcpkg or Conan, there
 should be an appropriate feature (vcpkg) or option (Conan) that will abstract this away for you.
 
diff --git a/docs/supported_formats/xml.md b/docs/content/supported_formats/xml.md
similarity index 99%
rename from docs/supported_formats/xml.md
rename to docs/content/supported_formats/xml.md
index e9e4d4009..a28cf95f9 100644
--- a/docs/supported_formats/xml.md
+++ b/docs/content/supported_formats/xml.md
@@ -1,4 +1,8 @@
-# XML 
+---
+breadcrumbs: true
+---
+
+# XML
 
 For XML support, you must also include the header `` and include the [pugixml](https://github.com/zeux/pugixml) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_XML=ON` to cmake. If you are using vcpkg or Conan, there
@@ -84,7 +88,7 @@ This will result in the following XML string:
 
 ```
 
-Unlike most other formats, XML distinguishes between attributes and nodes. 
+Unlike most other formats, XML distinguishes between attributes and nodes.
 If you want something to be displayed as an attribute, you must mark it as such:
 
 ```cpp
@@ -185,7 +189,7 @@ This will result in the following XML string:
 
 ### There must be exactly one root node
 
-The XML format requires that there must be exactly one root node. 
+The XML format requires that there must be exactly one root node.
 Other formats, like JSON, allow you to have an array as the root element. XML disallows that.
 
 ### The root node must have a name
diff --git a/docs/supported_formats/yaml.md b/docs/content/supported_formats/yaml.md
similarity index 98%
rename from docs/supported_formats/yaml.md
rename to docs/content/supported_formats/yaml.md
index 57903312b..b07f6263e 100644
--- a/docs/supported_formats/yaml.md
+++ b/docs/content/supported_formats/yaml.md
@@ -1,4 +1,8 @@
-# YAML 
+---
+breadcrumbs: true
+---
+
+# YAML
 
 For YAML support, you must also include the header `` and include the [yaml-cpp](https://github.com/jbeder/yaml-cpp) library.
 Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_YAML=ON` to cmake. If you are using vcpkg or Conan, there
diff --git a/docs/supported_formats/yas.md b/docs/content/supported_formats/yas.md
similarity index 98%
rename from docs/supported_formats/yas.md
rename to docs/content/supported_formats/yas.md
index cbe44128f..2fa6bede5 100644
--- a/docs/supported_formats/yas.md
+++ b/docs/content/supported_formats/yas.md
@@ -1,3 +1,7 @@
+---
+breadcrumbs: true
+---
+
 # yas
 
 For [yas](https://github.com/niXman/yas) support, you must also include the header `` and link to the yas library.
diff --git a/docs/timestamps.md b/docs/content/timestamps.md
similarity index 100%
rename from docs/timestamps.md
rename to docs/content/timestamps.md
diff --git a/docs/to_view.md b/docs/content/to_view.md
similarity index 100%
rename from docs/to_view.md
rename to docs/content/to_view.md
diff --git a/docs/validating_numbers.md b/docs/content/validating_numbers.md
similarity index 100%
rename from docs/validating_numbers.md
rename to docs/content/validating_numbers.md
diff --git a/docs/variants_and_tagged_unions.md b/docs/content/variants_and_tagged_unions.md
similarity index 100%
rename from docs/variants_and_tagged_unions.md
rename to docs/content/variants_and_tagged_unions.md
diff --git a/docs/docs-readme.md b/docs/docs-readme.md
deleted file mode 100644
index d33777e2a..000000000
--- a/docs/docs-readme.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Documentation
-
-## The basics
-
-[Structs](concepts/structs.md) - Recaps the motivating example in the README. A struct is the equivalent of an AND statement or a product type in type theory.
-
-[Optional fields](optional_fields.md) - For defining fields in your serialized format that might be absent in some cases.
-
-[Struct flattening](flatten_structs.md) - For making struct A "inherit" the fields of struct B.
-
-[Processors](concepts/processors.md) - For modifying the structs before serialization and deserialization. For instance, processors can be used to transform all field names from `snake_case` to `camelCase`.
-
-[The rfl::Field-syntax](concepts/field_syntax.md) - Describes an alternative syntax which requires slightly more effort, but allows for some powerful functionalities.
-
-[String literals](literals.md) - For representing strings that can only assume a limited number of enumerated values.
-
-[Enums](enums.md) - Describes how reflect-cpp handles C++ enums.
-
-[std::variant and rfl::TaggedUnion](variants_and_tagged_unions.md) - For structs that can be one of several formats. This is the equivalent of an OR statement or a sum type in type theory.
-
-[rfl::Box and rfl::Ref](rfl_ref.md) - For defining recursive structures.
-
-[rfl::Timestamp and std::chrono::duration](timestamps.md) - For serializing and deserializing timestamps and durations.
-
-[rfl::Skip](rfl_skip.md) - For skipping fields during serialization and/or deserialization.
-
-[rfl::Commented](commented.md) - For adding comments to your serialized format (only supported by some formats, such as YAML or XML). 
-
-[rfl::Result](result.md) - For error handling without exceptions.
-
-[Standard containers](standard_containers.md) - Describes how reflect-cpp treats containers in the standard library.
-
-[std::expected](expected.md) - For serializing and deserializing `std::expected`, the C++-23 result type.
-
-[C arrays and inheritance](c_arrays_and_inheritance.md) - Describes how reflect-cpp handles C arrays and inheritance.
-
-[rfl::Bytestring](bytestring.md) - Describes how reflect-cpp handles binary strings for formats that support them.
-
-[rfl::Binary, rfl::Hex and rfl::Oct](number_systems.md)- For expressing numbers in different formats.
-
-[Default values](default_val.md) - For defining default values for fields that might be absent during deserialization.
-
-[Atomic types](atomic.md) - For serializing and deserializing atomic types.
-
-## Validation
-
-[Regex patterns](patterns.md) - For requiring that strings follow used-defined regex patterns.
-
-[Validating numbers](validating_numbers.md) - For imposing constraints on numbers.
-
-[Composing validators](composing_validators.md) - For defining more complex validators using operators such as `rfl::AllOf` or `rfl::AnyOf`.
-
-[Size validation](size_validation.md) - For imposing size constraints on containers such as `std::vector` or `std::string`.
-
-[JSON schema](json_schema.md) - For validating your schema before you even send it to your C++ backend.
-
-## Generic elements
-
-[rfl::Object](object.md) - A map-like type representing a object with field names that are unknown at compile time.
-
-[rfl::Generic](generic.md) - A catch-all type that can represent (almost) anything.
-
-[rfl::ExtraFields](extra_fields.md) - For adding extra fields to your structs, the names of which are unknown at compile time.
-
-## Custom classes
-
-[Custom classes](concepts/custom_classes.md) - For custom classes with private fields.
-
-[Custom parsers for your classes](custom_parser.md) - For custom classes with private fields that you want (or need) to leave absolutely untouched.
-
-## Useful helper functions and classes
-
-[rfl::replace](replace.md) - For replacing one or several fields in a struct.
-
-[rfl::as](as.md) - For casting structs as other structs.
-
-[rfl::NamedTuple](named_tuple.md) - For structural typing.
-
-[rfl::Tuple](rfl_tuple.md) - An alternative to `std::tuple` that compiles more quickly.
-
-[rfl::to_view](to_view.md) - For accessing fields of a struct by index or name.
-
-## Advanced topics
-
-[Supporting your own format](supported_formats/supporting_your_own_format.md) - For supporting your own serialization and deserialization formats.
-
-[Maintaining backwards compatability](backwards_compatability.md) - Instructions on how to ensure that your API is backwards-compatible with older versions.
-
-[Benchmarks](benchmarks.md) - Extensive benchmarks of popular libraries for serialization, deserialization.
-
-
diff --git a/docs/go.mod b/docs/go.mod new file mode 100644 index 000000000..f75b3bd53 --- /dev/null +++ b/docs/go.mod @@ -0,0 +1,5 @@ +module github.com/imfing/hextra-starter-template + +go 1.26 + +require github.com/imfing/hextra v0.12.3 // indirect diff --git a/docs/go.sum b/docs/go.sum new file mode 100644 index 000000000..afa868093 --- /dev/null +++ b/docs/go.sum @@ -0,0 +1,2 @@ +github.com/imfing/hextra v0.12.3 h1:DZHY2rUWYteyzjlHi9r4n7Bb5e2Q+6LXe4C1Dqn0ZjM= +github.com/imfing/hextra v0.12.3/go.mod h1:vi+yhpq8YPp/aghvJlNKVnJKcPJ/VyAEcfC1BSV9ARo= diff --git a/docs/hugo.yaml b/docs/hugo.yaml new file mode 100644 index 000000000..b63d2af3d --- /dev/null +++ b/docs/hugo.yaml @@ -0,0 +1,50 @@ +# Hugo configuration file +title: reflect-cpp + +# import hextra as module +module: + imports: + - path: github.com/imfing/hextra + +markup: + # allow raw html + goldmark: + renderer: + unsafe: true + + # enable hextra syntax highlight + highlight: + noClasses: false + +menu: + main: + - name: Main Page + pageRef: / + weight: 1 + - name: Supported Formats + pageRef: /supported_formats + weight: 2 + - name: C++-26 reflection + pageRef: /cpp26_reflection + weight: 3 + - name: Contributing + pageRef: /contributing + weight: 4 + - name: Search + weight: 5 + params: + type: search + - name: GitHub + weight: 6 + url: "https://github.com/getml/reflect-cpp/" + params: + icon: github + +params: + navbar: + displayTitle: true + displayLogo: false + + footer: + displayCopyright: false + displayPoweredBy: true diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 6d1f60684..000000000 --- a/docs/index.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -hide: - # - toc - - navigation - - feedback ---- - - -
- -# ![C++](https://img.shields.io/badge/c++-%237156c2.svg?style=for-the-badge&logo=c%2B%2B&logoColor=white) reflect-cpp - -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity) -[![Generic badge](https://img.shields.io/badge/C++-20-blue.svg)](https://shields.io/) -[![Generic badge](https://img.shields.io/badge/gcc-11+-blue.svg)](https://shields.io/) -[![Generic badge](https://img.shields.io/badge/clang-14+-blue.svg)](https://shields.io/) -[![Generic badge](https://img.shields.io/badge/MSVC-17+-blue.svg)](https://shields.io/) -[![Conan Center](https://img.shields.io/conan/v/reflect-cpp)](https://conan.io/center/recipes/reflect-cpp) - -
- - **💻 Source Code**: [https://github.com/getml/reflect-cpp](https://github.com/getml/reflect-cpp) - -**reflect-cpp** is a C++-20 library for **fast serialization, deserialization and validation** using reflection, similar to [pydantic](https://github.com/pydantic/pydantic) in Python, [serde](https://github.com/serde-rs) in Rust, [encoding](https://github.com/golang/go/tree/master/src/encoding) in Go or [aeson](https://github.com/haskell/aeson/tree/master) in Haskell. - -reflect-cpp fills an important gap in C++ development. It minimizes boilerplate code and enhances code safety for seamless and efficient data exchange across system components. - -

Design principles for reflect-cpp include:

- -- Close integration with [containers](https://github.com/getml/reflect-cpp?tab=readme-ov-file#support-for-containers) from the C++ standard library -- Close adherence to C++ idioms -- Out-of-the-box support for [JSON](https://rfl.getml.com/supported_formats/json) -- Simple [installation](https://rfl.getml.com/install) -- Simple extendability to [other serialization formats](https://rfl.getml.com/supported_formats/supporting_your_own_format) -- Simple extendability to [custom classes](https://rfl.getml.com/concepts/custom_classes) -- Support for default-valued fields via `rfl::DefaultVal` (see [Default values](default_val.md)) -- Being one of the fastest serialization libraries in existence, as demonstrated by our [benchmarks](https://rfl.getml.com/benchmarks) - - -## Why do we need this? - -Suppose your C++ program has complex data structures it needs to save and load. Or maybe it needs to interact with some kind of external API. If you do this the traditional way, you will have a lot of boilerplate code. This is annoying and error-prone. - -!!! example - - If you are new to reflect-cpp, please refer to our [GitHub repository](https://github.com/getml/reflect-cpp) for the latest list of supported [serialization formats]. You will also find a [simple] and [more comprehensive code example]. - - [github repo]: https://github.com/getml/reflect-cpp - [serialization formats]: https://github.com/getml/reflect-cpp#serialization-formats - [simple]: https://github.com/getml/reflect-cpp#simple-example - [more comprehensive code example]: https://github.com/getml/reflect-cpp#more-comprehensive-example - - -reflect-cpp is not just a reflection library, it is for **serialization, deserialization and validation** through reflection. - -That means that you can encode your requirements about the input data in the type system and have them validated upfront. This is why the library also includes algebraic data types like tagged unions and numerous validation routines. Having your requirements encoded in the type system is the most reliable way of ensuring they are met. If your requirements are not met, the user of your software gets a very clear error message. Encoding your requirements in the type system also makes it a lot easier for anyone reading your code. - -This increases user experience and developer experience, it makes your code safer (fewer bugs) and more secure (less prone to malicious attacks). - -For a more in-depth theoretical discussions of these topics, the following books are warmly recommended: - -- *Category Theory for Programmers* by Bartosz Milewski [on GitHub](https://github.com/hmemcpy/milewski-ctfp-pdf/releases) -- *Domain Modeling Made Functional* by Scott Wlaschin - -## The team behind reflect-cpp - -reflect-cpp has been developed by [getML (Code17 GmbH)](https://getml.com), a company specializing in software engineering and machine learning for enterprise applications. reflect-cpp is currently maintained by Patrick Urbanke and Manuel Bellersen, with major contributions coming from the community. - -### Related projects - -reflect-cpp was originally developed for [getml-community](https://github.com/getml/getml-community), the fastest open-source tool for feature engineering on relational data and time series. If you are interested in Data Science and/or Machine Learning, please check it out. - -### Professional C++ support - -For comprehensive C++ support beyond the scope of GitHub discussions, we’re here to help! Reach out at [support@getml.com](mailto:support%40getml.com?subject=C++%20support%20request) to discuss any technical challenges or project requirements. We’re excited to support your work as independent software consultants. - - -## License -reflect-cpp is released under the MIT License. diff --git a/mkdocs.yaml b/mkdocs.yaml deleted file mode 100644 index 306a38137..000000000 --- a/mkdocs.yaml +++ /dev/null @@ -1,202 +0,0 @@ -# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json - -site_name: "reflect-cpp" -strict: false -site_url: https://rfl.getml.com/ -site_author: Code17 GmbH -site_description: >- - A C++20 library for fast serialization, deserialization and validation using reflection. - Supports JSON, AVRO, BSON, Boost Serialization, Cap'n Proto, CBOR, Cereal, CSV, flexbuffers, msgpack, parquet, TOML, UBJSON, XML, YAML, yas - -theme: - name: "material" - palette: - - media: "(prefers-color-scheme)" - toggle: - icon: material/brightness-5 - name: "Switch to light mode" - - media: "(prefers-color-scheme: light)" - scheme: default - primary: getml - accent: getml - toggle: - icon: material/brightness-2 - name: "Switch to dark mode" - - media: "(prefers-color-scheme: dark)" - scheme: slate - primary: getml - accent: getml - toggle: - icon: material/brightness-6 - name: "Switch to system preference" - font: - text: Roboto - code: Roboto Mono - features: - - content.tabs.link - - content.code.annotate - - content.code.copy - - announce.dismiss - - navigation.tabs - - navigation.instant - - navigation.instant.prefetch - - navigation.instant.preview - - navigation.instant.progress - - navigation.path - - navigation.top - - navigation.tracking - - search.suggest - - toc.follow - # logo: assets/images/rfl-favicon.png - # favicon: assets/images/rfl-favicon-square.png - -repo_name: getml/reflect-cpp -repo_url: https://github.com/getml/reflect-cpp -edit_uri: edit/main/docs/ - -extra: - social: - - icon: fontawesome/brands/github - link: https://github.com/getml - - icon: fontawesome/brands/youtube - link: https://www.youtube.com/@code17-gmbh - - icon: fontawesome/brands/linkedin - link: https://www.linkedin.com/company/code17-gmbh - -# https://www.mkdocs.org/user-guide/configuration/#validation -#validation: -# absolute_links: warn -# unrecognized_links: warn - -validation: - omitted_files: warn - links: - absolute_links: relative_to_docs - anchors: warn - unrecognized_links: warn - -extra_css: - - assets/stylesheets/tweaks.css - -exclude_docs: | - -nav: - - Welcome: index.md - # - Concepts: - # - Structs: concepts/structs.md - # - Custom Classes: concepts/custom_classes.md - # - Fields: concepts/field_syntax.md - # # - Type: concepts/types.md - # - Processors: concepts/processors.md - # # - Serialization: concepts/serialization.md - # # - Validators: concepts/validators.md - # # - Errors handling: concepts/errors.md - - Supported Formats: - - Avro: supported_formats/avro.md - - Boost Serialization: supported_formats/boost_serialization.md - - BSON: supported_formats/bson.md - - Cap'n Proto: supported_formats/capnproto.md - - CBOR: supported_formats/cbor.md - - Cereal: supported_formats/cereal.md - - CSV: supported_formats/csv.md - - Environment variables: supported_formats/env.md - - FlexBuffers: supported_formats/flexbuffers.md - - JSON: supported_formats/json.md - - MessagePack: supported_formats/msgpack.md - - Parquet: supported_formats/parquet.md - - TOML: supported_formats/toml.md - - UBJSON: supported_formats/ubjson.md - - XML: supported_formats/xml.md - - YAML: supported_formats/yaml.md - - yas: supported_formats/yas.md - - Custom Format: supported_formats/supporting_your_own_format.md - # - Reflective Programming: ./reflective_programming.md - - Installation: install.md - - C++26 reflection: cpp26_reflection.md - - Documentation: - - docs-readme.md - - The basics: - - Structs: concepts/structs.md - - Optional fields: optional_fields.md - - Default values: default_val.md - - Struct flattening: flatten_structs.md - - Processors: concepts/processors.md - - The rfl::Field-syntax: concepts/field_syntax.md - - String literals: literals.md - - Enums: enums.md - - std::variant and rfl::TaggedUnion: variants_and_tagged_unions.md - - rfl::Box and rfl::Ref: rfl_ref.md - - rfl::Timestamp: timestamps.md - - rfl::Skip: rfl_skip.md - - rfl::Commented: commented.md - - rfl::Result: result.md - - Standard containers: standard_containers.md - - std::expected: expected.md - - C arrays and inheritance: c_arrays_and_inheritance.md - - rfl::Bytestring: bytestring.md - - rfl::Binary, rfl::Hex and rfl::Oct: number_systems.md - - std::atomic, std::atomic_flag: atomic.md - - Validation: - - Regex patterns: patterns.md - - Validating numbers: validating_numbers.md - - Composing validators: composing_validators.md - - Size validation: size_validation.md - - JSON schema: json_schema.md - - Enum descriptions: enum_descriptions.md - - Generic elements: - - rfl::Object: object.md - - rfl::Generic: generic.md - - rfl::ExtraFields: extra_fields.md - - Custom classes: - - Custom classes: concepts/custom_classes.md - - Custom parsers for your classes: custom_parser.md - - Useful helper functions and classes: - - rfl::replace: replace.md - - rfl::as: as.md - - rfl::NamedTuple: named_tuple.md - - rfl::Tuple: rfl_tuple.md - - rfl::to_view: to_view.md - - Advanced topics: - - Supporting your own format: supported_formats/supporting_your_own_format.md - - Maintaining backwards compatability: backwards_compatability.md - - Benchmarks: benchmarks.md - - Contributing: contributing.md - -markdown_extensions: - - tables - - def_list - - toc: - permalink: true - title: Page contents - - admonition - - pymdownx.details - - pymdownx.superfences - - pymdownx.highlight: - pygments_lang_class: true - - pymdownx.extra - - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg - - pymdownx.tabbed: - alternate_style: true - -watch: - - docs - -plugins: - - search - - meta - - htmlproofer: - enabled: !ENV [ENABLED_HTMLPROOFER, False] - raise_error_after_finish: True - raise_error_excludes: - 403: ['*'] - 502: ['*'] - 504: ['*'] - 429: ['*'] - - ignore_urls: - - localhost:8080/* - - mailto:* - - 'data:image/*' - - '#*'