diff --git a/.github/workflows/hugo.yaml b/.github/workflows/hugo.yaml new file mode 100644 index 0000000..7a819a6 --- /dev/null +++ b/.github/workflows/hugo.yaml @@ -0,0 +1,79 @@ +# Sample workflow for building and deploying a Hugo site to GitHub Pages +name: Deploy Hugo site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: + - main + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# 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.122.0 + steps: + - name: Install Hugo CLI + 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: Install Dart Sass + run: sudo snap install dart-sass + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - name: Setup Pages + id: pages + uses: actions/configure-pages@v4 + - name: Install Node.js dependencies + run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" + - 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 }}/" + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: ./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@v3 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f982c51 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Node.js assets +node_modules/ + +# Hugo-generated assets +.hugo_build.lock +public/ +resources/ + +# clone of gohugoio/hugo for docker-support +hugo/ + +# local GH token, used for some scripts +.gh-token + +# build directories +/bin + +# OSX .DS_Store +.DS_Store diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..ce9f588 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +cozystack.io diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bf046d4 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# cozystack-website +Cozystack.io website diff --git a/assets/scss/_adopters.scss b/assets/scss/_adopters.scss index a6e572c..05b9494 100644 --- a/assets/scss/_adopters.scss +++ b/assets/scss/_adopters.scss @@ -130,7 +130,7 @@ .logo { height: 120px; display: flex; - background-color: $flux-white; + background-color: $cozy-white; opacity: 1; img { max-width: 552px; @@ -175,7 +175,7 @@ h3 { font-variant-caps: all-small-caps; font-weight: 700; - color: $flux-lighter-blue; + color: $cozy-lighter-blue; } } } @@ -238,7 +238,7 @@ padding: 1rem; #carousel-caption { - color: $flux-darkest-blue; + color: $cozy-darkest-blue; } } } diff --git a/assets/scss/_buttons.scss b/assets/scss/_buttons.scss index bddc9f5..2e03186 100644 --- a/assets/scss/_buttons.scss +++ b/assets/scss/_buttons.scss @@ -13,12 +13,12 @@ } @mixin flat-white-button { - color: $flux-mid-gray !important; - background-color: $flux-white !important; + color: $cozy-mid-gray !important; + background-color: $cozy-white !important; border: none; &:hover { - color: $flux-gray !important; + color: $cozy-gray !important; box-shadow: none !important; text-shadow: none !important; } @@ -46,8 +46,8 @@ @mixin projects-btn-secondary { a.btn-secondary { @include flat-white-button; - background-color: $flux-light-blue !important; - color: $flux-gray !important; + background-color: $cozy-light-blue !important; + color: $cozy-gray !important; margin-right: 1rem; padding-left: 1rem; diff --git a/assets/scss/_index.scss b/assets/scss/_index.scss index 21cecd8..2774365 100644 --- a/assets/scss/_index.scss +++ b/assets/scss/_index.scss @@ -3,20 +3,20 @@ @mixin white-background-a { a { - color: $flux-lighter-blue !important; + color: $cozy-lighter-blue !important; &:hover { - color: $flux-darkest-blue !important; + color: $cozy-darkest-blue !important; } } } @mixin gray-background-a { a { - color: $flux-light-blue !important; + color: $cozy-light-blue !important; &:hover { - color: $flux-dark-blue !important; + color: $cozy-dark-blue !important; } } } @@ -79,7 +79,7 @@ main.td-main { .resources { h4 { - color: $flux-white; + color: $cozy-white; font-size: 1.25rem; font-weight: 600; margin: 0.85rem 0; @@ -169,7 +169,7 @@ main.td-main { } .carousel-inner { - background: $flux-white; + background: $cozy-white; .carousel-item { height: 220px; @@ -190,7 +190,7 @@ main.td-main { } } .carousel-item-caption { - color: $flux-gray; + color: $cozy-gray; font-size: 1.8rem; } } @@ -228,11 +228,11 @@ main.td-main { .section-community { @include gray-background-a; - background-color: $flux-gray; + background-color: $cozy-gray; .td-box--dark { - background-color: $flux-gray; + background-color: $cozy-gray; } a { @@ -241,7 +241,7 @@ main.td-main { .section-label { margin: 0 0 2rem 0; - color: $flux-white !important; + color: $cozy-white !important; } section.row.td-box { @@ -269,7 +269,7 @@ main.td-main { .community-item { flex: none; - border: 1px solid $flux-white; + border: 1px solid $cozy-white; padding: 0.5rem 1rem; margin: 1rem; width: 320px; diff --git a/assets/scss/_variables_project.scss b/assets/scss/_variables_project.scss index efae2e3..4f2d490 100644 --- a/assets/scss/_variables_project.scss +++ b/assets/scss/_variables_project.scss @@ -15,23 +15,23 @@ $twitter-blue: #1da1f2; $linkedin-blue: #0e76a8; // Flux color palette -$flux-darkest-blue: #243f80; -$flux-dark-blue: #3d6ddd; -$flux-lighter-blue: #5f86e3; -$flux-light-blue: #c3d2f4; +$cozy-darkest-blue: #243f80; +$cozy-dark-blue: #3d6ddd; +$cozy-lighter-blue: #5f86e3; +$cozy-light-blue: #c3d2f4; -$flux-green: #3eaf7c; +$cozy-green: #3eaf7c; -$flux-black: #1a1a1a; -$flux-white: #ffffff; -$flux-gray: #2f2f2f; -$flux-mid-gray: #555555; -$flux-light-gray: #5f5f5f; +$cozy-black: #202124; +$cozy-white: #ffffff; +$cozy-gray: #2f2f2f; +$cozy-mid-gray: #555555; +$cozy-light-gray: #5f5f5f; -$primary: $flux-dark-blue; -$secondary: $flux-light-blue; -$dark: $flux-black; -$blue: $flux-dark-blue; +$primary: $cozy-dark-blue; +$secondary: $cozy-light-blue; +$dark: $cozy-black; +$blue: $cozy-dark-blue; $info : #428bca; $warning: #ffa630; @@ -40,7 +40,7 @@ $danger: #d9534f; $google_font_name: "Montserrat"; $google_font_family: "Montserrat:300,300i,400,400i,600,600i,700,700i"; -$navbar-dark-color: rgba($flux-white, 0.75) !default; -$navbar-dark-hover-color: rgba($flux-white, 0.5) !default; -$navbar-dark-active-color: $flux-white !default; -$navbar-dark-disabled-color: rgba($flux-white, 0.25) !default; +$navbar-dark-color: rgba($cozy-white, 0.75) !default; +$navbar-dark-hover-color: rgba($cozy-white, 0.5) !default; +$navbar-dark-active-color: $cozy-white !default; +$navbar-dark-disabled-color: rgba($cozy-white, 0.25) !default; diff --git a/assets/scss/blocks/_cncf.scss b/assets/scss/blocks/_cncf.scss index 13f7765..523c601 100644 --- a/assets/scss/blocks/_cncf.scss +++ b/assets/scss/blocks/_cncf.scss @@ -14,7 +14,7 @@ } a { - color: $flux-darkest-blue; + color: $cozy-darkest-blue; } } diff --git a/assets/scss/blocks/_features.scss b/assets/scss/blocks/_features.scss index 3d45e5b..575c6be 100644 --- a/assets/scss/blocks/_features.scss +++ b/assets/scss/blocks/_features.scss @@ -1,6 +1,6 @@ .features, .benefits { .fas, .fab, .fa { - color: $flux-dark-blue; + color: $cozy-dark-blue; } } diff --git a/assets/scss/blocks/_hero.scss b/assets/scss/blocks/_hero.scss index 630e681..12c34ac 100644 --- a/assets/scss/blocks/_hero.scss +++ b/assets/scss/blocks/_hero.scss @@ -10,15 +10,7 @@ padding: 0 15px; } - background: $flux-dark-blue; - - background: radial-gradient(circle at bottom left, $flux-darkest-blue, rgba($flux-dark-blue, 0.5) 30vw, transparent 80vw), - linear-gradient(0deg, $flux-dark-blue, rgba($flux-darkest-blue, 0.3) 30px, rgba($flux-darkest-blue, 0.3) 150px, transparent 400px), - linear-gradient(0deg, $flux-dark-blue, transparent 200px), - radial-gradient(circle at top right, rgba($flux-light-blue, 0.8), rgba($flux-lighter-blue, 0.5) 40%, rgba($flux-dark-blue, 0.8) 50%, transparent), - repeating-linear-gradient(15deg, rgba($flux-darkest-blue, 0.3), rgba($flux-darkest-blue, 0.3) 2px, rgba($flux-dark-blue, 0.3) 2px, rgba($flux-dark-blue, 0.3) 4px), - $flux-dark-blue; - + background: $cozy-gray; .td-hero-block { padding-bottom: 4rem; @@ -34,9 +26,9 @@ margin-top: 1.5rem; p { - color: $flux-white; + color: $cozy-white; font-weight: 500; - font-size: 1.4rem; + font-size: 1.2rem; } p:first-child { @@ -46,34 +38,35 @@ } p { - color: $flux-white; + color: $cozy-white; } h1 { - color: rgba($flux-white, 0.95); + color: rgba($cozy-white, 0.95); font-size: 2.8em; padding-left: 14px; + padding-top: 50px; @include media-breakpoint-up(sm) { - font-size: 3.8em; + font-size: 2.6em; } } h2 { - color: rgba($flux-white, 0.95); + color: rgba($cozy-white, 0.95); font-weight: 600; font-size: 1.4em; } a { - color: $flux-light-blue !important; + color: $cozy-light-blue !important; font-weight: 400; font-style: italic; text-decoration: underline; &:hover { - color: $flux-darkest-blue !important; - text-shadow: -1px 1px $flux-lighter-blue; + color: $cozy-darkest-blue !important; + text-shadow: -1px 1px $cozy-lighter-blue; } } @@ -109,7 +102,7 @@ .td-arrow-down { &::before { border: { - color: #{$flux-dark-blue} transparent transparent transparent; + color: #{$cozy-gray} transparent transparent transparent; } } } diff --git a/assets/scss/blocks/_nav.scss b/assets/scss/blocks/_nav.scss index 7ff86a7..22ce166 100644 --- a/assets/scss/blocks/_nav.scss +++ b/assets/scss/blocks/_nav.scss @@ -1,6 +1,6 @@ // // override docsy styles nav.navbar { - background: $flux-black; + background: $cozy-black; padding: 0; @include media-breakpoint-down(md) { diff --git a/content/en/.gitignore b/content/en/.gitignore new file mode 100644 index 0000000..61dc536 --- /dev/null +++ b/content/en/.gitignore @@ -0,0 +1,5 @@ +# Imported +community.md +contributing.md +governance.md +security.md diff --git a/content/en/.gitkeep b/content/en/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/content/en/_index.html b/content/en/_index.html new file mode 100644 index 0000000..102a8fa --- /dev/null +++ b/content/en/_index.html @@ -0,0 +1,129 @@ +--- +title: Cozystack - Free PaaS platform for cloud providers +description: > + With Cozystack, you can transform your bunch of servers into an intelligent system with a simple REST API for spawning Kubernetes clusters, Database-as-a-Service, virtual machines, load balancers, HTTP caching services, and other services with ease. + + You can use Cozystack to build your own cloud or to provide a cost-effective development environments. +benefits: + - title: API-first + icon: fas fa-code + description: > + Cozystack is based on Kubernetes and involves close interaction with its API. We don’t aim to completely hide the all elements behind a pretty UI or any sort of customizations; instead, we provide a standard interface and teach users how to work with basic primitives. + - title: Standardization and unification + icon: fas fa-certificate + description: > + All components of the platform are based on proven open source tools and technologies which are widely known in the industry. + We strive to use the most standard and correct approaches, as a result the whole platform is very simple and have no vendor lock-in. + - title: Collaborate, not compete + icon: fas fa-handshake + description: > + We are proud of our community and closely interact with projects around it. + Thus if a feature being developed for the platform could be useful to a upstream project, + it should be contributed to upstream project, rather than being implemented within the platform. +features: + - title: Easy to install + icon: fas fa-wrench + description: > + With [talos-bootstrap](https://github.com/aenix-io/talos-bootstrap/), we provide the ultimate easy installation method, + allowing you to bootstrap Cozystack using PXE or ISO method on a set of your servers out-of-nothing in a bare data center. + Using immutable OS allows us to maintain system consistency and ensure that everything will work as expected. + - title: Easy to integrate + icon: fas fa-plug + description: > + We provide a native Kubernetes RESTful API, widely recognized for its declarativity. + Therefore, to integrate with your billing, it's enough to instruct your system to submit a specific YAML manifest defining the desired service to the Kubernetes API. + Cozystack will do the rest of the work for you. + - title: Easy to extend + icon: fas fa-up-right-and-down-left-from-center + description: > + Each package in the platform consists of a set of YAML files. Therefore, anyone with some familiarity with Kubernetes primitives can modify or expand the platform. Delivery of packages to the system is handled by FluxCD, a well-known and widely used tool in the community. + - title: Cost efficiency and high performance + icon: fas fa-gauge-high + description: > + We care about performance. That's why we adopt the most performant technologies balancing stability and functionality. + Moreover, our unique tenant model enables efficient allocation of cloud resources for the control plane, ensuring cost-efficiency and the necessary level of security + - title: Monitoring included + icon: fas fa-area-chart + description: > + Each instance of each service is accompanied by a set of pre-configured dashboards and alerts. + You can create separate monitoring hubs for every tenant or combine them into one. + - title: Dashboard + icon: fas fa-window-maximize + description: > + While the primary goal of the platform is to provide a beautiful API, it also has a dashboard for deploying applications. The Web UI facilitates a quick dive into the platform and provides a visual demonstration of its capabilities. +--- + +
+ {{% blocks/hero title="Cozystack: Free PaaS platform for cloud providers" color="primary" + height="full" link_title="Get started" link_url="/docs/get-started/" %}} + With Cozystack, you can transform your bunch of servers into an intelligent system with a simple REST API for spawning Kubernetes clusters, Database-as-a-Service, virtual machines, load balancers, HTTP caching services, and other services with ease. + + You can use Cozystack to build your own cloud or to provide a cost-effective development environments. + + {{% /blocks/hero %}} + +
+ {{< blocks/lead >}} + {{< /blocks/lead >}} +
+
+ + + +{{< home/benefits >}} +{{< home/features >}} + + + +{{% blocks/lead title="A project by Ænix" color="primary" %}} +

Commercial Support

+ +Ænix offers enterprise-grade support, available 24/7. + +We provide all types of assistance, including consultations, development of missing features, design, assistance with installation, and integration. + +Contact us + +{{< /blocks/lead >}} + + +
+ {{< blocks/lead color="dark" >}} +

+ Community +

+ +

We deeply appreciate the steadfast support and contributions from our community towards the growth of Cozystack. Join our community and become part of our journey.

+ + {{< /blocks/lead >}} + +
+ {{< blocks/section color="dark" type="community-row">}} + + {{< home/community icon="fab fa-github" title="GitHub Discussions" >}} + Join the conversation in GitHub Discussions. Everything Cozystack related ranging from specifications and feature planning to Show & Tell happens here. + + {{< /home/community >}} + + + + + + {{< home/community icon="fa fa-paper-plane" title="Telegram" >}} + We also have a large community on Telegram. Join the @cozystack group chat to engage with fellow users, ask questions, and stay updated on the latest news and developments. + {{< /home/community >}} + + {{< /blocks/section >}} +
+ +
+ + + diff --git a/content/en/blog/2024-02-public-release-of-cozystack.md b/content/en/blog/2024-02-public-release-of-cozystack.md new file mode 100644 index 0000000..5a2d5bf --- /dev/null +++ b/content/en/blog/2024-02-public-release-of-cozystack.md @@ -0,0 +1,17 @@ +--- +author: kvaps +date: 2024-02-08 +title: Public release of Cozystack +description: We are pleased to present the first public release of the Cozystack platform. The platform can already be installed and poked. We will be glad to receive any feedback. + +--- + +We are pleased to present the first public release of the Cozystack platform 🎉🎉🎉 +The platform can already be installed and poked. We will be glad to receive any feedback. + + + +- https://github.com/aenix-io/cozystack + +Please give us stars ⭐ +(this will greatly help the development of the project) diff --git a/content/en/blog/_index.md b/content/en/blog/_index.md new file mode 100644 index 0000000..d4498bc --- /dev/null +++ b/content/en/blog/_index.md @@ -0,0 +1,7 @@ +--- +title: Blog +type: section +menu: + main: + weight: 30 +--- diff --git a/content/en/docs/.gitkeep b/content/en/docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/content/en/docs/_index.md b/content/en/docs/_index.md new file mode 100644 index 0000000..19c7690 --- /dev/null +++ b/content/en/docs/_index.md @@ -0,0 +1,17 @@ +--- +title: "Cozystack Documentation" +linkTitle: "Documentation" +description: "Open and extensible continuous delivery solution for Kubernetes." +taxonomyCloud: [] +cascade: + type: docs +menu: + main: + weight: 40 +--- + +Cozystack is an open-source PaaS platform for cloud providers. + +With Cozystack, you can transform your bunch of servers into an intelligent system with a simple REST API for spawning Kubernetes clusters, Database-as-a-Service, virtual machines, load balancers, HTTP caching services, and other services with ease. + +You can use Cozystack to build your own cloud or to provide a cost-effective development environments. diff --git a/content/en/docs/components.md b/content/en/docs/components.md new file mode 100644 index 0000000..fde2047 --- /dev/null +++ b/content/en/docs/components.md @@ -0,0 +1,108 @@ +--- +title: "Cozystack Components" +linkTitle: "Components" +description: "Cozystack Components" +weight: 40 +--- + +## Basic Platform Stack + +### Kubernetes + +Kubernetes has already become a kind of de facto standard for managing server workloads. + +One of the key features of Kubernetes is a convenient and unified API that is understandable to everyone (everything is YAML). Also, the best software design patterns that provide continuous recovery in any situation (reconciliation method) and efficient scaling to a large number of servers. + +This fully solves the integration problem, since all existing virtualization platforms have an outdated and rather complex APIs that cannot be extended without modifying the source code. As a result, there is always a need to create your own custom solutions, which requires additional effort. + +### Talos Linux + +Using Talos Linux as the base layer for the platform allows to strictly limit the technology stack and make the system stable as a rock. + +Talos Linux has no moving parts, no traditional package manager, no file structure, and no ability to run anything except Kubernetes containers.
 +The base layer of the platform includes the latest version of the kernel, all the necessary kernel modules, container runtime and a Kubernetes-like API for interacting with the system. + +Updating the system is done by rewriting the image "as is" entirely onto the hard drive. + +### KubeVirt + +KubeVirt is a project started by global industry leaders with a common vision to unify Kubernetes and a desire to introduce it to the world of virtualization. KubeVirt extends the capabilities of Kubernetes by providing convenient abstractions for launching and managing virtual machines, as well the all related entities such as snapshots, presets, virtual volumes, and more. + +At the moment, the KubeVirt project is being jointly developed by such world-famous companies as RedHat, NVIDIA, ARM. + +### DRBD + +DRBD is the fastest replication block storage running right in the Linux kernel. When DRBD only deals with data replication, time-tested technologies such as LVM or ZFS are used for securely store the data. +The DRBD kernel module is included in the mainline Linux kernel and has been used to build fault-tolerant systems for over a decade. + +DRBD is managed using LINSTOR, a system integrated with Kubernetes and which is a management layer for creating virtual volumes based on DRBD. It allows you to easily manage hundreds or thousands of virtual volumes in a cluster. + +### OVN + +OVN is a free implementation of virtual network fabric for Kubernetes and OpenStack based on Open vSwitch technology. With OVN, you get a robust and functional virtual network that ensures reliable isolation between tenants and provides floating addresses for virtual machines. + +In the future, this will enable seamless integration with other clusters and customer network services + +### Cilium + +Utilizing Cilium in conjunction with OVN enables the most efficient and flexible network policies, along with a productive services network in Kubernetes, leveraging an offloaded Linux network stack featuring the cutting-edge eBPF technology. + +Cilium is a highly promising project, widely adopted and supported by numerous cloud providers worldwide. + +### Grafana + +Grafana with Grafana Loki and the OnCall extension provides a single interface to Observability. It allows you to conveniently view charts, logs and manage alerts for your infrastructure and applications. + +### Victoria Metrics + +Victoria Metrics allows you to most efficiently collect, store and process metrics in the Open Metrics format, doing it more efficiently than Prometheus in the same setup. + +### MetalLB + +MetalLB is the default load balancer for Kubernetes; with its help, your services can obtain public addresses that are accessible not only from inside, but also from outside your cluster network. + +### Haproxy + +HAProxy is an advanced and widely known TCP balancer. It continuously checks the availability of services and carefully balance production traffic between them in real time. + + +## Application stack + + +### Managed PostgreSQL + +Nowadays PostgreSQL is the most popular relational database. Its platform-side implementation involves a self-healing replicated cluster, managed with the increasingly popular CloudNativePG operator within the community. + +### Managed MySQL + +MySQL is an equally well-known and also widely used relational database. The implementation in the platform provides the ability to create a replicated MariaDB cluster, which is managed using the increasingly popular mariadb-operator. + +> For each database, there is an interface for configuring users, their permissions, as well the schedules for creating backups using the currently most efficient tool - Restic. + +### Managed Redis + +Redis is the most commonly used key-value in-memory data store. It is most often used as a cache, as storage for user sessions, or as a message broker. The platform-side implementation involves a replicated failover Redis cluster with Sentinel, which is managed by the spotahome redis-operator. + +### Managed RabbitMQ + +Widely known message broker. Platform-side implementation allows you to create failover clusters managed by the official RabbitMQ operator. + +### Managed HTTP Cache + +Nginx-based HTTP caching service - with its help you can always protect your application from overload using the powerful Nginx, which is traditionally used to build CDNs and caching servers. + +The platform-side implementation features efficient caching without using a clustered file system and horizontal scaling without duplicating data on multiple servers. + +### Managed Kubernetes + +Managed Kubernetes is a service that allows you to create full-featured Kubernetes clusters on demand, right out of the box, with just the click of a button. For each cluster, a separate managed control-plane and virtual compute nodes are created. + +In the future, there will be added functionality for automatically collecting metrics and logs from users clusters into a common Monitoring Stack. To implement this service, the development of the Kubefarm project will be used. + +> This set of services is enough to run almost any modern application. + +### Managed VPN Service + +The VPN Service is powered by the Outline Server, an advanced and user-friendly VPN solution. Internally known as "Shadowbox", which simplifies the process of setting up and sharing Shadowsocks servers. It operates by launching Shadowsocks instances on demand. + +The Shadowsocks protocol implies the use of symmetric encryption algorithms, enabling a fast way to access the internet while complicating traffic analysis and blocking through DPI (Deep Packet Inspection). diff --git a/content/en/docs/concepts.md b/content/en/docs/concepts.md new file mode 100644 index 0000000..f0a849c --- /dev/null +++ b/content/en/docs/concepts.md @@ -0,0 +1,79 @@ +--- +title: Core Concepts +description: Core Concepts of Cozystack. +weight: 10 +--- + +These are some core concepts in Cozystack. + +## Platform Architecture + +The core principle of the platform is that the end-user never has direct access to the API management cluster. Instead, the platform facilitates easy integration with the provider’s system, which in turn creates all the necessary services for the user. Then, it provides the credentials for user access to these services. + +Besides managed services, the platform allows to bootstrap tenant Kubernetes clusters. The users have full access to their tenant Kubernetes clusters but have no access to the management cluster. + +All controllers serving the user’s cluster are run externally from it, which allows to fully isolate the management cluster API from tenants and minimizes the potential for attacks on the management cluster. + +Once access is granted to the tenant Kubernetes, the user can order physical volumes, load balancers, and eventually other services using tenant Kubernetes API. + +![Cozystack for public cloud](/img/case-public-cloud.png) + +All use cases are presented here: + +* [**Using Cozystack to build public cloud**](/docs/use-cases/public-cloud/) + How to use Cozystack to build public cloud + +* [**Using Cozystack to build private cloud**](/docs/use-cases/private-cloud/) + How to use Cozystack to build private cloud + +* [**Using Cozystack as Kubernetes distribution**](/docs/use-cases/kubernetes-distribution/) + How to use Cozystack as Kubernetes distribution + + +## Tenant system + +A tenant is the main unit of security on the platform. The closest analogy would be Linux kernel namespaces. + +Tenants can be created recursively and are subject to the following rules: + +#### Higher-level tenants can access lower-level ones. + +Higher-level tenants can view and manage the applications of all their children. + +#### Each tenant has its own domain + +By default (unless otherwise specified), it inherits the domain of its parent with a prefix of its name, for example, if the parent had the domain `example.org`, then `tenant-foo` would get the domain `foo.example.org` by default. + +Kubernetes clusters created in this tenant namespace would get domains like: `kubernetes-cluster.foo.example.org` + +Example: +``` +tenant-root (example.org) +└── tenant-foo (foo.example.org) + └── kubernetes-cluster1 (kubernetes-cluster1.foo.example.org) +``` + +#### Lower-level tenants can access the cluster services of their parent (provided they do not run their own) + +Thus, you can create `tenant-u1` with a set of services like `etcd`, `ingress`, `monitoring`. And create another tenant namespace `tenant-u2` inside of `tenant-u1`. + +Let's see what will happen when you run Kubernetes and Postgres under `tenant-u2` namesapce. + +Since `tenant-u2` does not have its own cluster services like `etcd`, `ingress`, and `monitoring`, the applications will use the cluster services of the parent tenant. +This in turn means: + +- The Kubernetes cluster data will be stored in etcd for `tenant-u1`. +- Access to the cluster will be through the common ingress of `tenant-u1`. +- Essentially, all metrics will be collected in the monitoring from `tenant-u1`, and only it will have access to them. + + +Example: +``` +tenant-u1 +├── etcd +├── ingress +├── monitoring +└── tenant-u2 + ├── kubernetes-cluster1 + └── postgres-db1 +``` diff --git a/content/en/docs/faq.md b/content/en/docs/faq.md new file mode 100644 index 0000000..5b79eeb --- /dev/null +++ b/content/en/docs/faq.md @@ -0,0 +1,13 @@ +--- +title: "Frequently asked questions" +linkTitle: "FAQ" +description: "Flux and the GitOps Toolkit frequently asked questions." +weight: 144 +--- + +{{% alert title="Troubleshooting" %}} +Troubleshooting advice can be found on our [Troubleshooting Cheatsheet](/docs/troubleshooting/). +{{% /alert %}} + +## General questions + diff --git a/content/en/docs/get-started.md b/content/en/docs/get-started.md new file mode 100644 index 0000000..d6b6e55 --- /dev/null +++ b/content/en/docs/get-started.md @@ -0,0 +1,525 @@ +--- +title: "Get Started with Cozystack" +linkTitle: "Get Started" +description: "Get Started with Cozystack." +weight: 30 +--- + +This tutorial shows you how to bootstrap Cozystack on a few servers in your infrastructure + +## Before you begin + +![Cozystack deployment](/img/cozystack-deployment.png) + +You need 3 physical servers or VMs with nested virtualisation: + +```yaml +CPU: 4 cores +CPU model: host +RAM: 8-16 GB +HDD1: 32 GB +HDD2: 100GB (raw) +``` + +And one management VM or physical server connected to the same network. +Any Linux system installed on it (eg. Ubuntu should be enough) + +{{% alert color="warning" %}} +:warning: This VM should support `x86-64-v2` architecture, the most probably you can achieve this by setting cpu model to `host` +{{% /alert %}} + +## Objectives + +- Bootstrap Cozystack on three servers using PXE +- Configure Storage +- Configure Networking interconnection +- Access Cozystack dashboard +- Deploy etcd, ingress and monitoring stack + +## Install dependencies: + +- `docker` +- `talosctl` +- `dialog` +- `nmap` +- `make` +- `yq` +- `kubectl` +- `helm` + +## Netboot server + +Start matchbox with prebuilt Talos image for Cozystack: + +```bash +sudo docker run --name=matchbox -d --net=host ghcr.io/aenix-io/cozystack/matchbox:v0.0.2 \ + -address=:8080 \ + -log-level=debug +``` + +Start DHCP-Server: +```bash +sudo docker run --name=dnsmasq -d --cap-add=NET_ADMIN --net=host quay.io/poseidon/dnsmasq \ + -d -q -p0 \ + --dhcp-range=192.168.100.3,192.168.100.254 \ + --dhcp-option=option:router,192.168.100.1 \ + --enable-tftp \ + --tftp-root=/var/lib/tftpboot \ + --dhcp-match=set:bios,option:client-arch,0 \ + --dhcp-boot=tag:bios,undionly.kpxe \ + --dhcp-match=set:efi32,option:client-arch,6 \ + --dhcp-boot=tag:efi32,ipxe.efi \ + --dhcp-match=set:efibc,option:client-arch,7 \ + --dhcp-boot=tag:efibc,ipxe.efi \ + --dhcp-match=set:efi64,option:client-arch,9 \ + --dhcp-boot=tag:efi64,ipxe.efi \ + --dhcp-userclass=set:ipxe,iPXE \ + --dhcp-boot=tag:ipxe,http://192.168.100.254:8080/boot.ipxe \ + --log-queries \ + --log-dhcp +``` + +Where: +- `192.168.100.3,192.168.100.254` range to allocate IPs from +- `192.168.100.1` your gateway +- `192.168.100.254` is address of your management server + +Check status of containers: + +``` +docker ps +``` + +example output: + +```console +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +22044f26f74d quay.io/poseidon/dnsmasq "/usr/sbin/dnsmasq -…" 6 seconds ago Up 5 seconds dnsmasq +231ad81ff9e0 ghcr.io/aenix-io/cozystack/matchbox:v0.0.2 "/matchbox -address=…" 58 seconds ago Up 57 seconds matchbox +``` + +## Bootstrap cluster + +Write configuration for Cozystack: + +```yaml +cat > patch.yaml <<\EOT +machine: + kubelet: + nodeIP: + validSubnets: + - 192.168.100.0/24 + kernel: + modules: + - name: openvswitch + - name: drbd + parameters: + - usermode_helper=disabled + - name: zfs + install: + image: ghcr.io/aenix-io/cozystack/talos:v1.6.4 + files: + - content: | + [plugins] + [plugins."io.containerd.grpc.v1.cri"] + device_ownership_from_security_context = true + path: /etc/cri/conf.d/20-customization.part + op: create + +cluster: + network: + cni: + name: none + podSubnets: + - 10.244.0.0/16 + serviceSubnets: + - 10.96.0.0/16 +EOT + +cat > patch-controlplane.yaml <<\EOT +cluster: + allowSchedulingOnControlPlanes: true + controllerManager: + extraArgs: + bind-address: 0.0.0.0 + scheduler: + extraArgs: + bind-address: 0.0.0.0 + apiServer: + certSANs: + - 127.0.0.1 + proxy: + disabled: true + discovery: + enabled: false + etcd: + advertisedSubnets: + - 192.168.100.0/24 +EOT +``` + +Run [talos-bootstrap](https://github.com/aenix-io/talos-bootstrap/) to deploy cluster: + +```bash +talos-bootstrap install +``` + +Save admin kubeconfig to access your Kubernetes cluster: +```bash +cp -i kubeconfig ~/.kube/config +``` + +Check connection: +```bash +kubectl get ns +``` + +example output: +```console +NAME STATUS AGE +default Active 7m56s +kube-node-lease Active 7m56s +kube-public Active 7m56s +kube-system Active 7m56s +``` + + +{{% alert color="warning" %}} +:warning: All nodes should currently show as `READY: False`, don't worry about that, this is because you disabled the default CNI plugin in the previous step. Cozystack will install it's own CNI-plugin on the next step. +{{% /alert %}} + +## Install Cozystack + +write config for cozystack: + +{{% alert color="warning" %}} +:warning: please make sure that you written the same setting specified in `patch.yaml` and `patch-controlplane.yaml` files. +{{% /alert %}} + +```yaml +cat > cozystack-config.yaml <<\EOT +apiVersion: v1 +kind: ConfigMap +metadata: + name: cozystack + namespace: cozy-system +data: + cluster-name: "cozystack" + ipv4-pod-cidr: "10.244.0.0/16" + ipv4-pod-gateway: "10.244.0.1" + ipv4-svc-cidr: "10.96.0.0/16" + ipv4-join-cidr: "100.64.0.0/16" +EOT +``` + +Create namesapce and install Cozystack system components: + +```bash +kubectl create ns cozy-system +kubectl apply -f cozystack-config.yaml +kubectl apply -f manifests/cozystack-installer.yaml +``` + +(optional) You can track the logs of installer: +```bash +kubectl logs -n cozy-system deploy/cozystack -f +``` + +Wait for a while, then check the status of installation: +```bash +kubectl get hr -A +``` + +Wait until all releases become to `Ready` state: +```console +NAMESPACE NAME AGE READY STATUS +cozy-cert-manager cert-manager 4m1s True Release reconciliation succeeded +cozy-cert-manager cert-manager-issuers 4m1s True Release reconciliation succeeded +cozy-cilium cilium 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-operator 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-providers 4m1s True Release reconciliation succeeded +cozy-dashboard dashboard 4m1s True Release reconciliation succeeded +cozy-fluxcd cozy-fluxcd 4m1s True Release reconciliation succeeded +cozy-grafana-operator grafana-operator 4m1s True Release reconciliation succeeded +cozy-kamaji kamaji 4m1s True Release reconciliation succeeded +cozy-kubeovn kubeovn 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi-operator 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt-operator 4m1s True Release reconciliation succeeded +cozy-linstor linstor 4m1s True Release reconciliation succeeded +cozy-linstor piraeus-operator 4m1s True Release reconciliation succeeded +cozy-mariadb-operator mariadb-operator 4m1s True Release reconciliation succeeded +cozy-metallb metallb 4m1s True Release reconciliation succeeded +cozy-monitoring monitoring 4m1s True Release reconciliation succeeded +cozy-postgres-operator postgres-operator 4m1s True Release reconciliation succeeded +cozy-rabbitmq-operator rabbitmq-operator 4m1s True Release reconciliation succeeded +cozy-redis-operator redis-operator 4m1s True Release reconciliation succeeded +cozy-telepresence telepresence 4m1s True Release reconciliation succeeded +cozy-victoria-metrics-operator victoria-metrics-operator 4m1s True Release reconciliation succeeded +tenant-root tenant-root 4m1s True Release reconciliation succeeded +``` + +## Configure Storage + +Setup alias to access LINSTOR: +```bash +alias linstor='kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor' +``` + +list your nodes +```bash +linstor node list +``` + +example output: + +```console ++-------------------------------------------------------+ +| Node | NodeType | Addresses | State | +|=======================================================| +| srv1 | SATELLITE | 192.168.100.11:3367 (SSL) | Online | +| srv2 | SATELLITE | 192.168.100.12:3367 (SSL) | Online | +| srv3 | SATELLITE | 192.168.100.13:3367 (SSL) | Online | ++-------------------------------------------------------+ +``` + +list empty devices: + +```bash +linstor physical-storage list +``` + +example output: +```console ++--------------------------------------------+ +| Size | Rotational | Nodes | +|============================================| +| 107374182400 | True | srv3[/dev/sdb] | +| | | srv1[/dev/sdb] | +| | | srv2[/dev/sdb] | ++--------------------------------------------+ +``` + + +create storage pools: + +```bash +linstor ps cdp lvm srv1 /dev/sdb --pool-name data --storage-pool data +linstor ps cdp lvm srv2 /dev/sdb --pool-name data --storage-pool data +linstor ps cdp lvm srv3 /dev/sdb --pool-name data --storage-pool data +``` + +list storage pools: + +```bash +linstor sp l +``` + +example output: + +```console ++-------------------------------------------------------------------------------------------------------------------------------------+ +| StoragePool | Node | Driver | PoolName | FreeCapacity | TotalCapacity | CanSnapshots | State | SharedName | +|=====================================================================================================================================| +| DfltDisklessStorPool | srv1 | DISKLESS | | | | False | Ok | srv1;DfltDisklessStorPool | +| DfltDisklessStorPool | srv2 | DISKLESS | | | | False | Ok | srv2;DfltDisklessStorPool | +| DfltDisklessStorPool | srv3 | DISKLESS | | | | False | Ok | srv3;DfltDisklessStorPool | +| data | srv1 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv1;data | +| data | srv2 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv2;data | +| data | srv3 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv3;data | ++-------------------------------------------------------------------------------------------------------------------------------------+ +``` + + +Create default storage classes: +```yaml +kubectl create -f- < 2m10s +data-etcd-1 Bound pvc-1579f95a-a69d-4a26-bcc2-b15ccdbede0d 10Gi RWO local 115s +data-etcd-2 Bound pvc-907009e5-88bf-4d18-91e7-b56b0dbfb97e 10Gi RWO local 91s +grafana-db-1 Bound pvc-7b3f4e23-228a-46fd-b820-d033ef4679af 10Gi RWO local 2m41s +grafana-db-2 Bound pvc-ac9b72a4-f40e-47e8-ad24-f50d843b55e4 10Gi RWO local 113s +vmselect-cachedir-vmselect-longterm-0 Bound pvc-622fa398-2104-459f-8744-565eee0a13f1 2Gi RWO local 2m21s +vmselect-cachedir-vmselect-longterm-1 Bound pvc-fc9349f5-02b2-4e25-8bef-6cbc5cc6d690 2Gi RWO local 2m21s +vmselect-cachedir-vmselect-shortterm-0 Bound pvc-7acc7ff6-6b9b-4676-bd1f-6867ea7165e2 2Gi RWO local 2m41s +vmselect-cachedir-vmselect-shortterm-1 Bound pvc-e514f12b-f1f6-40ff-9838-a6bda3580eb7 2Gi RWO local 2m40s +vmstorage-db-vmstorage-longterm-0 Bound pvc-e8ac7fc3-df0d-4692-aebf-9f66f72f9fef 10Gi RWO local 2m21s +vmstorage-db-vmstorage-longterm-1 Bound pvc-68b5ceaf-3ed1-4e5a-9568-6b95911c7c3a 10Gi RWO local 2m21s +vmstorage-db-vmstorage-shortterm-0 Bound pvc-cee3a2a4-5680-4880-bc2a-85c14dba9380 10Gi RWO local 2m41s +vmstorage-db-vmstorage-shortterm-1 Bound pvc-d55c235d-cada-4c4a-8299-e5fc3f161789 10Gi RWO local 2m41s +``` + +Check all pods are running: + + +```bash +kubectl get pod -n tenant-root +``` + +example output: +```console +NAME READY STATUS RESTARTS AGE +etcd-0 1/1 Running 0 2m1s +etcd-1 1/1 Running 0 106s +etcd-2 1/1 Running 0 82s +grafana-db-1 1/1 Running 0 119s +grafana-db-2 1/1 Running 0 13s +grafana-deployment-74b5656d6-5dcvn 1/1 Running 0 90s +grafana-deployment-74b5656d6-q5589 1/1 Running 1 (105s ago) 111s +root-ingress-controller-6ccf55bc6d-pg79l 2/2 Running 0 2m27s +root-ingress-controller-6ccf55bc6d-xbs6x 2/2 Running 0 2m29s +root-ingress-defaultbackend-686bcbbd6c-5zbvp 1/1 Running 0 2m29s +vmalert-vmalert-644986d5c-7hvwk 2/2 Running 0 2m30s +vmalertmanager-alertmanager-0 2/2 Running 0 2m32s +vmalertmanager-alertmanager-1 2/2 Running 0 2m31s +vminsert-longterm-75789465f-hc6cz 1/1 Running 0 2m10s +vminsert-longterm-75789465f-m2v4t 1/1 Running 0 2m12s +vminsert-shortterm-78456f8fd9-wlwww 1/1 Running 0 2m29s +vminsert-shortterm-78456f8fd9-xg7cw 1/1 Running 0 2m28s +vmselect-longterm-0 1/1 Running 0 2m12s +vmselect-longterm-1 1/1 Running 0 2m12s +vmselect-shortterm-0 1/1 Running 0 2m31s +vmselect-shortterm-1 1/1 Running 0 2m30s +vmstorage-longterm-0 1/1 Running 0 2m12s +vmstorage-longterm-1 1/1 Running 0 2m12s +vmstorage-shortterm-0 1/1 Running 0 2m32s +vmstorage-shortterm-1 1/1 Running 0 2m31s +``` + +Now you can get public IP of ingress controller: +``` +kubectl get svc -n tenant-root root-ingress-controller +``` + +example output: +```console +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +root-ingress-controller LoadBalancer 10.96.16.141 192.168.100.200 80:31632/TCP,443:30113/TCP 3m33s +``` + +Use `grafana.example.org` (under 192.168.100.200) to access system monitoring, where `example.org` is your domain specified for `tenant-root` + +- login: `admin` +- to get password: + ```bash + kubectl get secret -n tenant-root grafana-admin-password -o go-template='{{ printf "%s\n" (index .data "password" | base64decode) }}' + ``` diff --git a/content/en/docs/roadmap.md b/content/en/docs/roadmap.md new file mode 100644 index 0000000..f5f7f5c --- /dev/null +++ b/content/en/docs/roadmap.md @@ -0,0 +1,52 @@ +--- +title: "Cozystack Roadmap" +linkTitle: "Roadmap" +description: "Cozystack Roadmap" +weight: 50 +--- + +### Platform + +- [x] Installing the platform on a group of servers, ordering VM, MySQL, Postgres, Redis, LoadBalancer and VPN. +- [x] Running databases in replicated master/slave mode with the ability to manage users and rights +- [x] Creation of a basic graphical interface with authorization by tokens. +- [x] Collecting metrics from all services and dashboards for displaying detailed status. +- [x] Monitoring as a general system service. +- [ ] Enhanced etcd management +- [ ] Community repository - a repository similar to Archlinux AUR, where each user can publish their custom package + +### Monitoring + +- [x] Ability to launch a separate Monitoring Stack for each tenant. +- [x] Each tenant has a separate database for collecting logs and metrics +- [ ] Collects metrics from user workloads into their own Monitoring Stack. +- [ ] Alerts from all components get collected into a common IRM +- [ ] Routing alerts into Slack and Telegram +- [ ] Collecting logs from all services into separate databases for each tenant + +### Managed Kubernetes + +- [x] Ability to run Managed Kubernetes clusters with isolated control-plane +- [x] Ability to order PVCs and LoadBalancer type services from a tenant's Kubernetes cluster +- [ ] Automatic logs and metrics collection from tenant's Kubernetes clusters into the tenant’s Monitoring Stack + +### Applications + +- [X] Managed VPN service +- [X] PostgreSQL users and database management +- [X] PostgreSQL backups +- [X] MariaDB users and database management +- [X] MariaDB backups +- [ ] MariaDB recovery enhancements +- [ ] MariaDB to support maxscale +- [ ] Enhanced Virtual Machines management + +### Security + +- [x] Basic management of tenants +- [ ] Network isolation between tenants +- [ ] Improvement of the authorization and access control system +- [ ] User creation and granular permission assignment +- [ ] Integration with external authentication systems (LDAP, OIDC, etc.) +- [ ] Common authentication gateway and security logging portal +- [ ] VPCs and network isolation diff --git a/content/en/docs/troubleshooting.md b/content/en/docs/troubleshooting.md new file mode 100644 index 0000000..0df449e --- /dev/null +++ b/content/en/docs/troubleshooting.md @@ -0,0 +1,80 @@ +--- +title: "Troubleshooting cheatsheet" +linkTitle: "Troubleshooting" +description: "Showcase various ways to get more information out of Flux controllers to debug potential problems." +weight: 60 +--- + +## Getting basic information + +You can see the logs of main installer by executing: + +```yaml +kubectl logs -n cozy-system deploy/cozystack -f +``` + +All the platform components are installed using fluxcd HelmRelases. + +You can get all installed HelmRelases: + +```bash +# kubectl get hr -A +NAMESPACE NAME AGE READY STATUS +cozy-cert-manager cert-manager 4m1s True Release reconciliation succeeded +cozy-cert-manager cert-manager-issuers 4m1s True Release reconciliation succeeded +cozy-cilium cilium 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-operator 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-providers 4m1s True Release reconciliation succeeded +cozy-dashboard dashboard 4m1s True Release reconciliation succeeded +cozy-fluxcd cozy-fluxcd 4m1s True Release reconciliation succeeded +cozy-grafana-operator grafana-operator 4m1s True Release reconciliation succeeded +cozy-kamaji kamaji 4m1s True Release reconciliation succeeded +cozy-kubeovn kubeovn 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi-operator 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt-operator 4m1s True Release reconciliation succeeded +cozy-linstor linstor 4m1s True Release reconciliation succeeded +cozy-linstor piraeus-operator 4m1s True Release reconciliation succeeded +cozy-mariadb-operator mariadb-operator 4m1s True Release reconciliation succeeded +cozy-metallb metallb 4m1s True Release reconciliation succeeded +cozy-monitoring monitoring 4m1s True Release reconciliation succeeded +cozy-postgres-operator postgres-operator 4m1s True Release reconciliation succeeded +cozy-rabbitmq-operator rabbitmq-operator 4m1s True Release reconciliation succeeded +cozy-redis-operator redis-operator 4m1s True Release reconciliation succeeded +cozy-telepresence telepresence 4m1s True Release reconciliation succeeded +cozy-victoria-metrics-operator victoria-metrics-operator 4m1s True Release reconciliation succeeded +tenant-root tenant-root 4m1s True Release reconciliation succeeded +``` + +Normaly all of them should be `Ready` and `Release reconciliation succeeded` + + +### Diagnosing `install retries exhausted` error + +Sometimes you can face with the error: + +```bash +# kubectl get hr -A -n cozy-dashboard dashboard +NAMESPACE NAME AGE READY STATUS +cozy-dashboard dashboard 15m False install retries exhausted +``` + +You can try to figure out by checking events: + +```bash +kubectl describe hr -n cozy-dashboard dashboard +``` + +if `Events: ` then suspend and reume the release: + +```bash +kubectl patch hr -n cozy-dashboard dashboard -p '{"spec": {"suspend": true}}' --type=merge +kubectl patch hr -n cozy-dashboard dashboard -p '{"spec": {"suspend": null}}' --type=merge +``` + +and check the events again: + +```bash +kubectl describe hr -n cozy-dashboard dashboard +``` diff --git a/content/en/docs/use-cases/_index.md b/content/en/docs/use-cases/_index.md new file mode 100644 index 0000000..2f7ffbe --- /dev/null +++ b/content/en/docs/use-cases/_index.md @@ -0,0 +1,6 @@ +--- +title: "Use Cases" +linkTitle: "Use Cases" +description: "Cozystack use cases." +weight: 20 +--- diff --git a/content/en/docs/use-cases/kubernetes-distribution.md b/content/en/docs/use-cases/kubernetes-distribution.md new file mode 100644 index 0000000..771d238 --- /dev/null +++ b/content/en/docs/use-cases/kubernetes-distribution.md @@ -0,0 +1,18 @@ +--- +title: Using Cozystack as Kubernetes distribution +linkTitle: Kubernetes Distribution +description: "How to use Cozystack as Kubernetes distribution" +weight: 30 +--- + +You can use Cozystack as Kubernetes distribution for Bare Metal + +### Overview + +We created Cozystack primarily for our own needs, having vast experience in building reliable systems on bare metal infrastructure. This experience led to the formation of a separate boxed product, which is aimed at standardizing and providing a ready-to-use tool for managing your infrastructure. + +Currently, Cozystack already solves a huge scope of infrastructure tasks: starting from provisioning bare metal servers, having a ready monitoring system, fast and reliable storage, a network fabric with the possibility of interconnect with your infrastructure, the ability to run virtual machines, databases, and much more right out of the box. + +All this makes Cozystack a convenient platform for delivering and launching your application on Bare Metal. + +![Cozystack as Kubernetes Distribution](/img/case-distribution.png) diff --git a/content/en/docs/use-cases/private-cloud.md b/content/en/docs/use-cases/private-cloud.md new file mode 100644 index 0000000..86ecd1b --- /dev/null +++ b/content/en/docs/use-cases/private-cloud.md @@ -0,0 +1,18 @@ +--- +title: Using Cozystack to build private cloud +linkTitle: Private Cloud +description: "How to use Cozystack to build private cloud" +weight: 20 +--- + +You can use Cozystack as platform to build a private cloud powered by Infrastructure-as-Code + +### Overview + +One of the use cases is a self-portal for users within your company, where they can order the service they're interested in or a managed database. + +You can implement best GitOps practices, where users will launch their own Kubernetes clusters and databases for their needs with a simple commit of configuration into your infrastructure Git repository. + +Thanks to the standardization of the approach to deploying applications, you can expand the platform's capabilities using the functionality of standard Helm charts. + +![Cozystack for private cloud](/img/case-private-cloud.png) diff --git a/content/en/docs/use-cases/public-cloud.md b/content/en/docs/use-cases/public-cloud.md new file mode 100644 index 0000000..14828f0 --- /dev/null +++ b/content/en/docs/use-cases/public-cloud.md @@ -0,0 +1,20 @@ +--- +title: Using Cozystack to build public cloud +linkTitle: Public Cloud +description: "How to use Cozystack to build public cloud" +weight: 10 +--- + +You can use Cozystack as backend for a public cloud + +### Overview + +Cozystack positions itself as a kind of framework for building public clouds. The key word here is framework. In this case, it's important to understand that Cozystack is made for cloud providers, not for end users. + +Despite having a graphical interface, the current security model does not imply public user access to your management cluster. + +Instead, end users get access to their own Kubernetes clusters, can order LoadBalancers and additional services from it, but they have no access and know nothing about your management cluster powered by Cozystack. + +Thus, to integrate with your billing system, it's enough to teach your system to go to the management Kubernetes and place a YAML file signifying the service you're interested in. Cozystack will do the rest of the work for you. + +![Cozystack for public cloud](/img/case-public-cloud.png) diff --git a/hugo.yaml b/hugo.yaml index 04c4f95..65a692b 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -1,5 +1,5 @@ baseURL: / -title: Flux +title: Cozystack enableRobotsTXT: true enableEmoji: true @@ -91,28 +91,28 @@ outputs: params: description: Open and extensible continuous delivery solution for Kubernetes. - copyright: The Flux authors - github_repo: https://github.com/fluxcd/website - github_branch: main - github_project_repo: https://github.com/fluxcd/flux2 - slack: https://cloud-native.slack.com/messages/flux + copyright: Ænix, + github_repo: https://github.com/aenix-io/cozystack-website + github_branch: source + github_project_repo: https://github.com/aenix-io/cozystack + #slack: https://cloud-native.slack.com/messages/cozystack support: /support images: [img/flux-social.png] # Enable Algolia DocSearch - algolia_docsearch: true + algolia_docsearch: false offlineSearch: false version_menu: "Versions" - version: "2.2" + version: "0.1" archived_version: false version_menu_pagelinks: true - url_latest_version: https://fluxcd.io/flux/ - versions: - - version: "v2.2" - url: https://fluxcd.io - - version: "v2.1" - url: https://v2-1.docs.fluxcd.io - - version: "v2.0" - url: https://v2-0.docs.fluxcd.io + url_latest_version: https://cozystack.io/docs + #versions: + # - version: "v2.2" + # url: https://fluxcd.io + # - version: "v2.1" + # url: https://v2-1.docs.fluxcd.io + # - version: "v2.0" + # url: https://v2-0.docs.fluxcd.io logos: navbar: flux-horizontal-white.png hero: flux-horizontal-color.png @@ -139,11 +139,11 @@ params: # End user relevant links. These will show up on left side of footer and in the community page if you have one. user: - name: Twitter - url: https://twitter.com/fluxcd + url: https://twitter.com/aenix_io icon: fab fa-twitter desc: Follow us on Twitter to get the latest news! - name: LinkedIn - url: https://linkedin.com/groups/8985374 + url: https://www.linkedin.com/company/aenix-io icon: fab fa-linkedin desc: Join the Flux Community group on LinkedIn! - name: RSS Feed @@ -151,78 +151,34 @@ params: icon: fa fa-rss desc: Subscribe to the RSS feed of our blog! - name: Support - url: /support + url: https://aenix.io/contact-us/ icon: fas fa-comments - desc: Subscribe to the RSS feed of our blog! + desc: Get enterprise-grade support. # Developer relevant links. These will show up on right side of footer and in the community page if you have one. developer: - - name: Flux project on GitHub - url: https://github.com/fluxcd + - name: Cozystack project on GitHub + url: https://github.com/aenix-io/cozystack icon: fab fa-github desc: Development takes place here! - - name: Slack - url: https://cloud-native.slack.com/messages/flux - icon: fab fa-slack + #- name: Slack + # url: https://kubernetes.slack.com/messages/cozystack + # icon: fab fa-slack + # desc: Chat with other project developers + - name: Telegram + url: https://t.me/cozystack/ + icon: fab fa-telegram desc: Chat with other project developers - - name: Developer mailing list - url: https://lists.cncf.io/g/cncf-flux-dev - icon: fa fa-envelope - desc: Discuss development issues around the project - - name: Flux YouTube channel - url: https://youtube.com/@fluxcd - icon: fab fa-youtube - desc: Watch videos about Using Flux and Flux Development + menus: main: - - name: Documentation - url: /flux - weight: 10 - - name: Code of Conduct - parent: Project - url: https://github.com/fluxcd/community/blob/main/CODE_OF_CONDUCT.md - weight: 1 - - name: Resources - parent: Project - url: /resources + - name: Ænix + url: https://aenix.io weight: 5 - - name: Support - parent: Project - url: /support + - name: GitHub + url: https://github.com/aenix-io/cozystack weight: 10 - - name: Community - parent: Project - url: /community - weight: 20 - - name: Contributing - parent: Project - url: /contributing - weight: 30 - - name: Governance - parent: Project - url: /governance - weight: 40 - - name: Roadmap - parent: Project - url: /roadmap - weight: 50 - - name: Security - parent: Project - url: /security - weight: 60 - - name: Branding - parent: Project - url: https://github.com/cncf/artwork/blob/master/examples/graduated.md#flux-logos - weight: 9999 - - name: Adopters - url: /adopters - weight: 80 - - name: Ecosystem - url: /ecosystem - weight: 90 - - name: Flagger - url: https://flagger.app - weight: 100 - - identifier: Project - name: Project - weight: 110 + +services: + googleAnalytics: + ID: G-XX2TEZM82F diff --git a/i18n/en.toml b/i18n/en.toml new file mode 100644 index 0000000..50246a5 --- /dev/null +++ b/i18n/en.toml @@ -0,0 +1,38 @@ +[caution] +other = "Caution:" + +[docs_create_issue] +other = "Create documentation issue" + +[docs_create_project_issue] +other = "Create project issue" + +[docs_edit] +other = "Edit this page" + +[docs_last_mod] +other = "Last modified" + +[docs_table_of_contents] +other = "Table of contents" + +[note] +other = "Note:" + +[outdated_blog__message] +other = "This article is more than one year old. Older articles may contain outdated content. Check that the information in the page has not become incorrect since its publication." + +[ui_minute_read] +other = "minute read" + +[ui_pager_next] +other = "Next" + +[ui_pager_prev] +other = "Previous" + +[ui_read_more] +other = "Read more" + +[warning] +other = "Warning:" diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..9a83581 --- /dev/null +++ b/layouts/404.html @@ -0,0 +1,22 @@ +{{ define "main"}} +
+
+
+

Sorry, page not found ... 🤷

+

Were you looking for?

+ + +
+

Something else...

+
+
+
+
+
+ +{{ end }} diff --git a/layouts/_default/_markup/render-link.html b/layouts/_default/_markup/render-link.html new file mode 100644 index 0000000..e552f14 --- /dev/null +++ b/layouts/_default/_markup/render-link.html @@ -0,0 +1,10 @@ +{{ $link := .Destination }} +{{ $isRemote := strings.HasPrefix $link "http" }} +{{- if not $isRemote -}} +{{ $url := urls.Parse .Destination }} +{{- if $url.Path -}} +{{ $fragment := "" }} +{{- with $url.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}} +{{- with .Page.GetPage $url.Path }}{{ $link = printf "%s%s" .RelPermalink $fragment }}{{ end }}{{ end -}} +{{- end -}} +{{ .Text | safeHTML }} \ No newline at end of file diff --git a/layouts/blog/baseof.html b/layouts/blog/baseof.html new file mode 100644 index 0000000..857a47c --- /dev/null +++ b/layouts/blog/baseof.html @@ -0,0 +1,40 @@ + + + + {{ partial "head.html" . }} + + +
+ {{ partial "navbar.html" . }} +
+
+
+
+ + +
+ {{ partial "version-banner.html" . }} + {{ with .CurrentSection.OutputFormats.Get "rss" -}} + + + + {{ end -}} + + {{ block "deprecated" . }} + {{ partial "deprecation-warning.html" . }} + {{ end }} + {{ block "main" . }}{{ end }} +
+
+
+ {{ partial "footer.html" . }} +
+ {{ partial "scripts.html" . }} + + \ No newline at end of file diff --git a/layouts/blog/list.html b/layouts/blog/list.html new file mode 100644 index 0000000..2251c65 --- /dev/null +++ b/layouts/blog/list.html @@ -0,0 +1,50 @@ +{{ define "main" }} +{{ if (and .Parent .Parent.IsHome) }} +{{ $.Scratch.Set "blog-pages" (where .Site.RegularPages "Section" .Section) }} +{{ else }} +{{$.Scratch.Set "blog-pages" .Pages }} +{{ end }} + +
+
+ {{- if .Pages -}} + {{ $pag := .Paginate (( $.Scratch.Get "blog-pages").GroupByDate "2006" )}} + {{ range $pag.PageGroups }} +

{{ T "post_posts_in" }} {{ .Key }}

+
    + {{ range .Pages }} + +
  • +
    +
    {{ .Title }}
    +

    {{ .Date.Format ($.Param "time_format_blog") }} {{ T "ui_in"}} {{ .CurrentSection.LinkTitle }}

    + + {{ partial "featured-image.html" (dict "p" . "w" 250 "h" 125 "class" "float-left mr-3 pt-1 d-none d-md-block") }} +

    tl;dr: {{ .Description }}

    +

    + {{ .Plain | safeHTML | truncate 400 }} +

    + {{ if .Truncated }} +

    {{ T "ui_read_more"}}

    + {{ end }} +
    +
  • + {{ end }} +
+ {{ end }} + {{ end }} +
+
+
+
+ {{ if .Pages }} + {{ template "_internal/pagination.html" . }} + {{ end }} +
+
+{{ end }} \ No newline at end of file diff --git a/layouts/docs/baseof.html b/layouts/docs/baseof.html new file mode 100644 index 0000000..d331798 --- /dev/null +++ b/layouts/docs/baseof.html @@ -0,0 +1,46 @@ + + + + {{ partial "head.html" . }} + + +
+ {{ partial "navbar.html" . }} +
+
+
+
+ + + {{ if not .Params.hugeTable }} + + {{ end }} + {{ if not .Params.hugeTable }} +
+ {{ else }} +
+ {{ end }} + {{ partial "version-banner.html" . }} + {{ if not .Site.Params.ui.breadcrumb_disable }}{{ partial "breadcrumb.html" . }}{{ end }} + {{ block "main" . }}{{ end }} +
+
+
+ {{ partial "footer.html" . }} +
+ {{ partial "scripts.html" . }} + + \ No newline at end of file diff --git a/layouts/docs/docsportal_home.html b/layouts/docs/docsportal_home.html new file mode 100644 index 0000000..a6aedcc --- /dev/null +++ b/layouts/docs/docsportal_home.html @@ -0,0 +1,25 @@ +{{ define "main" }} +
+ {{ if not .Params.notitle }} +

{{ .Title }}

+ {{ with .Params.description }}
{{ . | markdownify }}
{{ end }} + {{ end }} + {{ template "docs-portal-content" . }} +{{ end }} + +{{ define "content-id" }}content{{ end }} + +{{ define "docs-portal-content" }} +
+
+

{{ .Params.overview | safeHTML }}

+
+
+ {{ $page := (partial "docs/docs-portal-card" .) }} + {{ .Scratch.Set "html" $page }} + {{ $page }} +
+
+
+
+{{ end }} diff --git a/layouts/page/single.html b/layouts/page/single.html new file mode 100644 index 0000000..9e62bd1 --- /dev/null +++ b/layouts/page/single.html @@ -0,0 +1,9 @@ +{{ define "main" }} + + +
+{{ partial "version-banner.html" . }} +{{ .Content }} +
+ +{{ end }} diff --git a/layouts/partials/deprecation-warning.html b/layouts/partials/deprecation-warning.html new file mode 100644 index 0000000..fe898b5 --- /dev/null +++ b/layouts/partials/deprecation-warning.html @@ -0,0 +1,7 @@ +{{ if and (eq .Section "blog") (not .Params.evergreen) .Date (.Date.Before (now.AddDate -1 0 0)) -}} +
+
+

{{ T "outdated_blog__message" }}

+
+
+{{ end }} diff --git a/layouts/partials/docs/docs-portal-card.html b/layouts/partials/docs/docs-portal-card.html new file mode 100644 index 0000000..a574771 --- /dev/null +++ b/layouts/partials/docs/docs-portal-card.html @@ -0,0 +1,29 @@ +{{ range .Params.cards }} +
+

{{ .title }}

+

{{ .description }}

+ + {{ if .button }} +
+ +
+
+ {{ end }} +
+{{ end }} diff --git a/layouts/partials/favicons.html b/layouts/partials/favicons.html new file mode 100644 index 0000000..57f9716 --- /dev/null +++ b/layouts/partials/favicons.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/layouts/partials/hooks/body-end.html b/layouts/partials/hooks/body-end.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/partials/hooks/head-end.html b/layouts/partials/hooks/head-end.html new file mode 100644 index 0000000..42b02be --- /dev/null +++ b/layouts/partials/hooks/head-end.html @@ -0,0 +1 @@ +{{ template "_internal/google_analytics.html" . }} diff --git a/layouts/partials/navbar-version-selector.html b/layouts/partials/navbar-version-selector.html new file mode 100644 index 0000000..638fed0 --- /dev/null +++ b/layouts/partials/navbar-version-selector.html @@ -0,0 +1,13 @@ + + \ No newline at end of file diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html new file mode 100644 index 0000000..cba6796 --- /dev/null +++ b/layouts/partials/navbar.html @@ -0,0 +1,93 @@ + +{{ $logo := "icons/logo.svg" }} +{{ $title := .Site.Title }} + +{{ if in .Permalink "/flagger" }} +{{ $logo = "icons/flagger.svg" }} +{{ $title = "Flagger" }} +{{ end }} + +{{ $cover := and + (.HasShortcode "blocks/cover") + (not .Site.Params.ui.navbar_translucent_over_cover_disable) +-}} + + diff --git a/layouts/partials/page-meta-links.html b/layouts/partials/page-meta-links.html new file mode 100644 index 0000000..6308ab3 --- /dev/null +++ b/layouts/partials/page-meta-links.html @@ -0,0 +1,58 @@ +{{ if .File }} +{{ $pathFormatted := replace .File.Path "\\" "/" -}} +{{ $gh_repo := ($.Param "github_repo") -}} +{{ $gh_url := ($.Param "github_url") -}} +{{ $gh_subdir := ($.Param "github_subdir") -}} +{{ $gh_project_repo := ($.Param "github_project_repo") -}} +{{ $gh_branch := (default "main" ($.Param "github_branch")) -}} + +{{ $importedDoc := $.Param "importedDoc" | default "false" }} +
+{{ if $gh_url -}} + {{ warnf "Warning: use of `github_url` is deprecated. For details see https://www.docsy.dev/docs/adding-content/repository-links/#github_url-optional" -}} + {{ T "post_edit_this" }} +{{ else if $gh_repo -}} + {{ $gh_repo_path := printf "%s/content/%s" $gh_branch $pathFormatted -}} + {{ if and ($gh_subdir) (.Site.Language.Lang) -}} + {{ $gh_repo_path = printf "%s/%s/content/%s/%s" $gh_branch $gh_subdir ($.Site.Language.Lang) $pathFormatted -}} + {{ else if .Site.Language.Lang -}} + {{ $gh_repo_path = printf "%s/content/%s/%s" $gh_branch ($.Site.Language.Lang) $pathFormatted -}} + {{ else if $gh_subdir -}} + {{ $gh_repo_path = printf "%s/%s/content/%s" $gh_branch $gh_subdir $pathFormatted -}} + {{ end -}} + + {{/* Adjust $gh_repo_path based on path_base_for_github_subdir */ -}} + {{ $ghs_base := $.Param "path_base_for_github_subdir" -}} + {{ $ghs_rename := "" -}} + {{ if reflect.IsMap $ghs_base -}} + {{ $ghs_rename = $ghs_base.to -}} + {{ $ghs_base = $ghs_base.from -}} + {{ end -}} + {{ with $ghs_base -}} + {{ $gh_repo_path = replaceRE . $ghs_rename $gh_repo_path -}} + {{ end -}} + + {{ $viewURL := printf "%s/tree/%s" $gh_repo $gh_repo_path -}} + {{ $editURL := printf "%s/edit/%s" $gh_repo $gh_repo_path -}} + {{ $issuesURL := printf "%s/issues/new?title=%s" $gh_repo (safeURL $.Title ) -}} + {{ $newPageStub := resources.Get "stubs/new-page-template.md" -}} + {{ $newPageQS := querify "value" $newPageStub.Content "filename" "change-me.md" | safeURL -}} + {{ $newPageURL := printf "%s/new/%s?%s" $gh_repo $gh_repo_path $newPageQS -}} + + {{ if eq $importedDoc "false" }} + {{ T "post_view_this" }} + {{ T "post_edit_this" }} + {{ T "post_create_child_page" }} + {{ end }} + {{ T "post_create_issue" }} + {{ with $gh_project_repo -}} + {{ $project_issueURL := printf "%s/issues/new" . -}} + {{ T "post_create_project_issue" }} + {{ end -}} + +{{ end -}} +{{ with .CurrentSection.AlternativeOutputFormats.Get "print" -}} + {{ T "print_entire_section" }} +{{ end }} +
+{{ end -}} diff --git a/layouts/partials/resource.html b/layouts/partials/resource.html new file mode 100644 index 0000000..bd6ef25 --- /dev/null +++ b/layouts/partials/resource.html @@ -0,0 +1,18 @@ +{{ $youtube := .youtube }} +{{ $youtube_url := print "https://www.youtube.com/watch?v=" $youtube }} +{{ $thumbnail := printf "https://i3.ytimg.com/vi/%s/0.jpg" $youtube }} + +{{ if .thumbnail }} +{{ $thumbnail = printf "https://i3.ytimg.com/vi/%s/0.jpg" (.thumbnail) }} +{{ end }} + +{{ $url := .url | default $youtube_url }} +{{ $title := .title | default "Video title" }} + +
+ {{ $title | markdownify }} +

{{ $title | markdownify }}

+ + {{ if .description }}

{{ .description }}

{{ end }} + +
diff --git a/layouts/partials/sidebar-tree.html b/layouts/partials/sidebar-tree.html new file mode 100644 index 0000000..6a4a26e --- /dev/null +++ b/layouts/partials/sidebar-tree.html @@ -0,0 +1,71 @@ +{{/* We cache this partial for bigger sites and set the active class client side. */}} +{{ $sidebarCacheLimit := cond (isset .Site.Params.ui "sidebar_cache_limit") .Site.Params.ui.sidebar_cache_limit 2000 -}} +{{ $shouldDelayActive := ge (len .Site.Pages) $sidebarCacheLimit -}} +
+ {{ if not .Site.Params.ui.sidebar_search_disable -}} + + {{ else -}} +
+ +
+
+ {{ end -}} + +
+{{ define "section-tree-nav-section" -}} +{{ $s := .section -}} +{{ $p := .page -}} +{{ $shouldDelayActive := .shouldDelayActive -}} +{{ $sidebarMenuTruncate := .sidebarMenuTruncate -}} +{{ $treeRoot := cond (eq .ulNr 0) true false -}} +{{ $ulNr := .ulNr -}} +{{ $ulShow := .ulShow -}} +{{ $active := and (not $shouldDelayActive) (eq $s $p) -}} +{{ $activePath := and (not $shouldDelayActive) (or (eq $p $s) ($p.IsDescendant $s)) -}} +{{ $show := cond (or (lt $ulNr $ulShow) $activePath (and (not $shouldDelayActive) (eq $s.Parent $p.Parent)) (and (not $shouldDelayActive) (eq $s.Parent $p)) (not $p.Site.Params.ui.sidebar_menu_compact) (and (not $shouldDelayActive) ($p.IsDescendant $s.Parent))) true false -}} +{{ $mid := printf "m-%s" ($s.RelPermalink | anchorize) -}} +{{ $pages_tmp := where (union $s.Pages $s.Sections).ByWeight ".Params.toc_hide" "!=" true -}} +{{ $pages := $pages_tmp | first $sidebarMenuTruncate -}} +{{ $withChild := gt (len $pages) 0 -}} +{{ $manualLink := cond (isset $s.Params "manuallink") $s.Params.manualLink ( cond (isset $s.Params "manuallinkrelref") (relref $s $s.Params.manualLinkRelref) $s.RelPermalink) -}} +{{ $manualLinkTitle := cond (isset $s.Params "manuallinktitle") $s.Params.manualLinkTitle $s.Title -}} +
  • + {{ if (and $p.Site.Params.ui.sidebar_menu_foldable (ge $ulNr 1)) -}} + + + {{ else -}} + {{ with $s.Params.Icon}}{{ end }}{{ $s.LinkTitle }} + {{- end }} + {{- if $withChild }} + {{- $ulNr := add $ulNr 1 }} +
      + {{ range $pages -}} + {{ if (not (and (eq $s $p.Site.Home) (eq .Params.toc_root true))) -}} + {{ template "section-tree-nav-section" (dict "page" $p "section" . "shouldDelayActive" $shouldDelayActive "sidebarMenuTruncate" $sidebarMenuTruncate "ulNr" $ulNr "ulShow" $ulShow) }} + {{- end }} + {{- end }} +
    + {{- end }} +
  • +{{- end }} \ No newline at end of file diff --git a/layouts/partials/version-banner.html b/layouts/partials/version-banner.html new file mode 100644 index 0000000..d16f3eb --- /dev/null +++ b/layouts/partials/version-banner.html @@ -0,0 +1,17 @@ + + {{ if .Site.Params.archived_version }} + {{ $color := "primary" }} + {{ $latest_version := .Site.Params.url_latest_version }} + {{ $current_version := .Site.Params.version }} +
    +

    You are viewing documentation for Flux version: {{ $current_version }}

    + {{ with $current_version }}

    Version {{ . | markdownify }} of the + documentation is no longer actively maintained. The site that you are + currently viewing is an archived snapshot. + {{ with $latest_version }}For up-to-date documentation, see the + latest version.

    + {{ end }} + {{ end }} +
    +{{ end }} diff --git a/layouts/resources/list.html b/layouts/resources/list.html new file mode 100644 index 0000000..ef58cb5 --- /dev/null +++ b/layouts/resources/list.html @@ -0,0 +1,34 @@ +{{ define "main" }} + + +
    + + {{ partial "version-banner.html" . }} + + {{ .Content | markdownify }} + + {{ $resources := $.Site.Data.resources.resources }} + {{ $years := slice }} + {{ range $resources }} + {{ $years = $years | append (time.Format "2006" .date) }} + {{ $years = uniq $years }} + {{ end }} + {{ range $years }} + {{ $year := . }} +

    {{ . }}

    + +
    +
    +
    + {{ range $resources }} + {{ if eq (time.Format "2006" .date) $year }} + {{ partial "resource.html" . }} + {{ end }} + {{ end }} +
    +
    +
    + {{ end }} + +
    +{{ end }} diff --git a/layouts/shortcodes/blocks/flux_ui_galleries.html b/layouts/shortcodes/blocks/flux_ui_galleries.html new file mode 100644 index 0000000..56b0295 --- /dev/null +++ b/layouts/shortcodes/blocks/flux_ui_galleries.html @@ -0,0 +1,42 @@ +{{ $one := slice "Weave GitOps" "/img/uis/wego-*.png" "wego" }} +{{ $two := slice "VS Code GitOps Tools" "/img/uis/vscode-*.png" "vscode" }} +{{ $data := slice $one $two }} + +{{ range $data }} + {{ $title := index . 0 }} + {{ $glob := index . 1 }} + {{ $id := index . 2 }} +

    {{ $title }}

    +
    + {{ $match := resources.Match $glob }} + {{ range $match }} +
    +
    + +
    +
    + {{ end }} +
    + + +{{ end }} diff --git a/layouts/shortcodes/blocks/hero.html b/layouts/shortcodes/blocks/hero.html new file mode 100644 index 0000000..1d07473 --- /dev/null +++ b/layouts/shortcodes/blocks/hero.html @@ -0,0 +1,60 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +{{ $blockID := printf "td-cover-block-%d" .Ordinal }} +{{ $promo_image := (.Page.Resources.ByType "image").GetMatch "**background*" }} +{{ $logo_image := (.Page.Resources.ByType "image").GetMatch "**logo*" }} +{{ $col_id := .Get "color" | default "dark" }} +{{ $image_anchor := .Get "image_anchor" | default "smart" }} +{{ $logo_anchor := .Get "logo_anchor" | default "smart" }} +{{/* Height can be one of: auto, min, med, max, full. */}} +{{ $height := .Get "height" | default "max" }} +{{ $byline := .Get "byline" | default "" }} +{{ $link_url := .Get "link_url" | default "#" }} +{{ $link_title := .Get "link_title" | default "Get started" }} +{{ with $promo_image }} +{{ $promo_image_big := (.Fill (printf "1920x1080 %s" $image_anchor)) }} +{{ $promo_image_small := (.Fill (printf "960x540 %s" $image_anchor)) }} + + + + +{{ end }} +
    +
    +
    + {{ with .Get "title" }}

    {{ $title := . }}{{ with $logo_image }}{{ $logo_image_resized := (.Fit (printf "70x70 %s" $logo_anchor)) }}{{ end }}{{ $title | html }}

    {{ end }} + {{ with .Get "subtitle" }}

    {{ . | html }}

    {{ end }} +
    +
    +
    + {{ if eq .Page.File.Ext "md" }} + {{ .Inner | markdownify }} + {{ else }} + {{ .Inner | htmlUnescape | safeHTML }} + {{ end }} + + {{ if ne $link_url "#" }} + {{ $link_title }}
    + {{ end }} +
    + +
    +
    +
    + screenshot +
    +
    +
    + +
    +
    +
    diff --git a/layouts/shortcodes/blocks/resource.html b/layouts/shortcodes/blocks/resource.html new file mode 100644 index 0000000..6a76843 --- /dev/null +++ b/layouts/shortcodes/blocks/resource.html @@ -0,0 +1,16 @@ +{{ $youtube := .Get "youtube" }} +{{ $youtube_url := print "https://www.youtube.com/watch?v=" $youtube }} +{{ $thumbnail := printf "https://i3.ytimg.com/vi/%s/0.jpg" $youtube }} + +{{ if .Get "thumbnail" }} +{{ $thumbnail = printf "https://i3.ytimg.com/vi/%s/0.jpg" (.Get "thumbnail") }} +{{ end }} + +{{ $url := .Get "url" | default $youtube_url }} +{{ $title := .Get "title" | default "Video title" }} + +
    + {{ $title | markdownify }} +

    {{ $title | markdownify }}

    +

    {{ .Inner | markdownify }}

    +
    diff --git a/layouts/shortcodes/caution.html b/layouts/shortcodes/caution.html new file mode 100644 index 0000000..1959ae5 --- /dev/null +++ b/layouts/shortcodes/caution.html @@ -0,0 +1,4 @@ +{{ $_hugo_config := `{ "version": 1 }` }} + diff --git a/layouts/shortcodes/home/adopters_wall.html b/layouts/shortcodes/home/adopters_wall.html new file mode 100644 index 0000000..d41ebfe --- /dev/null +++ b/layouts/shortcodes/home/adopters_wall.html @@ -0,0 +1,29 @@ +

    Adopted by

    + diff --git a/layouts/shortcodes/home/announce.html b/layouts/shortcodes/home/announce.html new file mode 100644 index 0000000..708e8df --- /dev/null +++ b/layouts/shortcodes/home/announce.html @@ -0,0 +1,16 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +{{ $blockID := printf "td-cover-block-%d" .Ordinal }} +{{ $emoji := .Get "emoji" | default "" }} +{{ $url := .Get "url" | default "/" }} +{{ $color := .Get "color" | default "yellow" }} + +
    +
    +

    + {{ $emoji }} + + {{ .Inner | markdownify }} + +

    +
    +
    diff --git a/layouts/shortcodes/home/benefits.html b/layouts/shortcodes/home/benefits.html new file mode 100644 index 0000000..55876dc --- /dev/null +++ b/layouts/shortcodes/home/benefits.html @@ -0,0 +1,23 @@ +{{ $benefits := $.Page.Params.benefits -}} + +
    +
    +
    +
    +

    Benefits

    +
    + + {{ range $benefits -}} + {{ $icon := .icon -}} + {{ $desc := .description | markdownify -}} + {{ $title := .title | markdownify -}} +
    +
    + +

    {{ $title }}

    +

    {{ $desc }}

    +
    +
    + {{ end }} +
    +
    diff --git a/layouts/shortcodes/home/calendar.html b/layouts/shortcodes/home/calendar.html new file mode 100644 index 0000000..49911e5 --- /dev/null +++ b/layouts/shortcodes/home/calendar.html @@ -0,0 +1,35 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +
    +

    Our Team Calendar

    +

    The upcoming meetings, talks and community events in the next month are listed below. (All times are UTC.)

    + +
      + {{ range $.Site.Data.calendar }} +
    • +
      +
      {{ .date }}
      +
      {{ .time }}
      +
      {{ .label }}
      +
      +
      + + + {{ .description | safeHTML }} +
      +
    • + {{ end }} +
    + +

    See this page + for more detail and subscription options.

    +
    diff --git a/layouts/shortcodes/home/cncf.html b/layouts/shortcodes/home/cncf.html new file mode 100644 index 0000000..360348a --- /dev/null +++ b/layouts/shortcodes/home/cncf.html @@ -0,0 +1,10 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +{{ $blockID := printf "td-cover-block-%d" .Ordinal }} +{{ $logo := printf "img/logos/%s" site.Params.logos.cncf | relURL }} + diff --git a/layouts/shortcodes/home/community.html b/layouts/shortcodes/home/community.html new file mode 100644 index 0000000..81dd8f2 --- /dev/null +++ b/layouts/shortcodes/home/community.html @@ -0,0 +1,14 @@ +{{ $icon := .Get "icon" | default "fa-lightbulb" }} +
    +
    +
    + +
    +

    + {{ .Get "title" | htmlUnescape | safeHTML }} +

    +
    +

    + {{ .Inner | htmlUnescape | safeHTML }} +

    +
    diff --git a/layouts/shortcodes/home/contributors.html b/layouts/shortcodes/home/contributors.html new file mode 100644 index 0000000..69f0756 --- /dev/null +++ b/layouts/shortcodes/home/contributors.html @@ -0,0 +1,6 @@ +{{ $_hugo_config := `{ "version": 1 }` }} +
    + {{ range $.Site.Data.contributors }} + + {{ end }} +
    diff --git a/layouts/shortcodes/home/endorsements.html b/layouts/shortcodes/home/endorsements.html new file mode 100644 index 0000000..b8668a3 --- /dev/null +++ b/layouts/shortcodes/home/endorsements.html @@ -0,0 +1,36 @@ + diff --git a/layouts/shortcodes/home/features.html b/layouts/shortcodes/home/features.html new file mode 100644 index 0000000..c4bfd5c --- /dev/null +++ b/layouts/shortcodes/home/features.html @@ -0,0 +1,26 @@ +{{ $features := $.Page.Params.features -}} + +
    +
    +
    +

    Features

    +
    + + {{ range $features -}} + {{ $icon := .icon -}} + {{ $desc := .description | markdownify -}} + {{ $title := .title | markdownify -}} + +
    +
    +
    + +

    {{ $title }}

    +
    +

    {{ $desc }}

    +
    +
    + {{ end }} +
    +
    +
    diff --git a/layouts/shortcodes/home/resources_section.html b/layouts/shortcodes/home/resources_section.html new file mode 100644 index 0000000..6633760 --- /dev/null +++ b/layouts/shortcodes/home/resources_section.html @@ -0,0 +1,5 @@ +{{ $resources := $.Site.Data.resources.resources }} + +{{ range first 3 (where $resources "description" "!=" nil) }} + {{ partial "resource.html" . }} +{{ end }} diff --git a/layouts/shortcodes/note.html b/layouts/shortcodes/note.html new file mode 100644 index 0000000..64562a1 --- /dev/null +++ b/layouts/shortcodes/note.html @@ -0,0 +1,4 @@ +{{ $_hugo_config := `{ "version": 1 }` }} + diff --git a/layouts/shortcodes/warning.html b/layouts/shortcodes/warning.html new file mode 100644 index 0000000..9e98f19 --- /dev/null +++ b/layouts/shortcodes/warning.html @@ -0,0 +1,4 @@ +{{ $_hugo_config := `{ "version": 1 }` }} + diff --git a/layouts/shortcodes/youtube.html b/layouts/shortcodes/youtube.html new file mode 100644 index 0000000..6542cf3 --- /dev/null +++ b/layouts/shortcodes/youtube.html @@ -0,0 +1,10 @@ +{{- $pc := .Page.Site.Config.Privacy.YouTube -}} +{{- if not $pc.Disable -}} +{{- $ytHost := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" -}} +{{- $id := .Get "id" | default (.Get 0) -}} +{{- $class := .Get "class" | default "responsive-video" -}} +{{- $title := .Get "title" | default "YouTube Video" }} +
    + +
    +{{ end -}} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..844c6c6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1617 @@ +{ + "name": "site", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "devDependencies": { + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32", + "postcss-cli": "^11.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", + "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001538", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", + "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.490", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz", + "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", + "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.0.0.tgz", + "integrity": "sha512-4YxRvMi4P5C3WQTvdRfrv5UVqbISpqjORFQAW5QPiKAauaxNCwrEdIi6pG3tDFhKKpMen+enEhHIzB/tvIO+/w==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^1.0.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", + "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", + "dev": true, + "dependencies": { + "chokidar": "^3.3.0", + "dependency-graph": "^0.11.0", + "fs-extra": "^11.0.0", + "get-stdin": "^9.0.0", + "globby": "^14.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^5.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "postcss": "index.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-load-config": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.0.2.tgz", + "integrity": "sha512-Q8QR3FYbqOKa0bnC1UQ2bFq9/ulHX5Bi34muzitMr8aDtUelO5xKeJEYC/5smE0jNE9zdB/NBnOwXKexELbRlw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/postcss-reporter": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", + "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/thenby": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + } + }, + "dependencies": { + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sindresorhus/merge-streams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", + "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "dev": true, + "requires": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + } + }, + "caniuse-lite": { + "version": "1.0.30001538", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", + "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.490", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz", + "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fraction.js": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", + "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", + "dev": true + }, + "fs-extra": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.0.0.tgz", + "integrity": "sha512-4YxRvMi4P5C3WQTvdRfrv5UVqbISpqjORFQAW5QPiKAauaxNCwrEdIi6pG3tDFhKKpMen+enEhHIzB/tvIO+/w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", + "dev": true, + "requires": { + "@sindresorhus/merge-streams": "^1.0.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", + "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", + "dev": true, + "requires": { + "chokidar": "^3.3.0", + "dependency-graph": "^0.11.0", + "fs-extra": "^11.0.0", + "get-stdin": "^9.0.0", + "globby": "^14.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^5.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "yargs": "^17.0.0" + } + }, + "postcss-load-config": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.0.2.tgz", + "integrity": "sha512-Q8QR3FYbqOKa0bnC1UQ2bFq9/ulHX5Bi34muzitMr8aDtUelO5xKeJEYC/5smE0jNE9zdB/NBnOwXKexELbRlw==", + "dev": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + } + }, + "postcss-reporter": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", + "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", + "dev": true, + "requires": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "thenby": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true + }, + "yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..23d13bd --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "devDependencies": { + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32", + "postcss-cli": "^11.0.0" + } +} diff --git a/static/favicons/android-chrome-192x192.png b/static/favicons/android-chrome-192x192.png new file mode 100644 index 0000000..ab545d4 Binary files /dev/null and b/static/favicons/android-chrome-192x192.png differ diff --git a/static/favicons/android-chrome-512x512.png b/static/favicons/android-chrome-512x512.png new file mode 100644 index 0000000..5ec0be3 Binary files /dev/null and b/static/favicons/android-chrome-512x512.png differ diff --git a/static/favicons/apple-touch-icon.png b/static/favicons/apple-touch-icon.png new file mode 100644 index 0000000..39c1ff6 Binary files /dev/null and b/static/favicons/apple-touch-icon.png differ diff --git a/static/favicons/browserconfig.xml b/static/favicons/browserconfig.xml new file mode 100644 index 0000000..b3c41af --- /dev/null +++ b/static/favicons/browserconfig.xml @@ -0,0 +1,13 @@ + + + + + + + + + + #1a1a1a + + + diff --git a/static/favicons/favicon-16x16.png b/static/favicons/favicon-16x16.png new file mode 100644 index 0000000..a3d1fb2 Binary files /dev/null and b/static/favicons/favicon-16x16.png differ diff --git a/static/favicons/favicon-32x32.png b/static/favicons/favicon-32x32.png new file mode 100644 index 0000000..b149bda Binary files /dev/null and b/static/favicons/favicon-32x32.png differ diff --git a/static/favicons/favicon.ico b/static/favicons/favicon.ico new file mode 100644 index 0000000..fc04266 Binary files /dev/null and b/static/favicons/favicon.ico differ diff --git a/static/favicons/favicon.png b/static/favicons/favicon.png new file mode 100644 index 0000000..04eadca Binary files /dev/null and b/static/favicons/favicon.png differ diff --git a/static/favicons/favicon.svg b/static/favicons/favicon.svg new file mode 100644 index 0000000..0a1e22d --- /dev/null +++ b/static/favicons/favicon.svg @@ -0,0 +1,49 @@ + + + + + + + diff --git a/static/favicons/mstile-144x144.png b/static/favicons/mstile-144x144.png new file mode 100644 index 0000000..622ab2b Binary files /dev/null and b/static/favicons/mstile-144x144.png differ diff --git a/static/favicons/mstile-150x150.png b/static/favicons/mstile-150x150.png new file mode 100644 index 0000000..70d40bc Binary files /dev/null and b/static/favicons/mstile-150x150.png differ diff --git a/static/favicons/mstile-310x150.png b/static/favicons/mstile-310x150.png new file mode 100644 index 0000000..03f655f Binary files /dev/null and b/static/favicons/mstile-310x150.png differ diff --git a/static/favicons/mstile-310x310.png b/static/favicons/mstile-310x310.png new file mode 100644 index 0000000..0faae8a Binary files /dev/null and b/static/favicons/mstile-310x310.png differ diff --git a/static/favicons/mstile-70x70.png b/static/favicons/mstile-70x70.png new file mode 100644 index 0000000..f59b5aa Binary files /dev/null and b/static/favicons/mstile-70x70.png differ diff --git a/static/favicons/safari-pinned-tab.svg b/static/favicons/safari-pinned-tab.svg new file mode 100644 index 0000000..d72f1f4 --- /dev/null +++ b/static/favicons/safari-pinned-tab.svg @@ -0,0 +1,49 @@ + + + + + + + diff --git a/static/favicons/site.webmanifest b/static/favicons/site.webmanifest new file mode 100644 index 0000000..de22dbb --- /dev/null +++ b/static/favicons/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/favicons/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/favicons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#1a1a1a", + "background_color": "#1a1a1a", + "display": "standalone" +} diff --git a/static/img/case-distribution.png b/static/img/case-distribution.png new file mode 100644 index 0000000..716a9b9 Binary files /dev/null and b/static/img/case-distribution.png differ diff --git a/static/img/case-private-cloud.png b/static/img/case-private-cloud.png new file mode 100644 index 0000000..dae289c Binary files /dev/null and b/static/img/case-private-cloud.png differ diff --git a/static/img/case-public-cloud.png b/static/img/case-public-cloud.png new file mode 100644 index 0000000..7490b7e Binary files /dev/null and b/static/img/case-public-cloud.png differ diff --git a/static/img/cozystack-deployment.png b/static/img/cozystack-deployment.png new file mode 100644 index 0000000..d0cfbca Binary files /dev/null and b/static/img/cozystack-deployment.png differ diff --git a/static/img/logos/aenix.svg b/static/img/logos/aenix.svg new file mode 100644 index 0000000..6b495c3 --- /dev/null +++ b/static/img/logos/aenix.svg @@ -0,0 +1,74 @@ + + + + + + + + + diff --git a/static/img/screenshot.png b/static/img/screenshot.png new file mode 100644 index 0000000..ac2a482 Binary files /dev/null and b/static/img/screenshot.png differ