diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31ae4bc3d..0096648aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,10 +5,10 @@ on: branches: - main tags: ['v*.*.*'] - paths: ['.github/scripts/**','.github/workflows/**', '**/CMakeLists.txt', '**/Makefile', '**/*.h', '**/*.hpp', '**/*.c', '**/*.cpp', '**/*.cu'] + paths: ['.github/scripts/**','.github/workflows/build.yml', '**/CMakeLists.txt', '**/Makefile', '**/*.h', '**/*.hpp', '**/*.c', '**/*.cpp', '**/*.cu', '!docs/**', '!.gitignore'] pull_request: types: [opened, synchronize, reopened] - paths: ['.github/scripts/**','.github/workflows/**', '**/CMakeLists.txt', '**/Makefile', '**/*.h', '**/*.hpp', '**/*.c', '**/*.cpp', '**/*.cu'] + paths: ['.github/scripts/**','.github/workflows/build.yml', '**/CMakeLists.txt', '**/Makefile', '**/*.h', '**/*.hpp', '**/*.c', '**/*.cpp', '**/*.cu', '!docs/**', '!.gitignore'] env: BRANCH_NAME: ${{ github.head_ref || github.ref_name }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..7c049b358 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,73 @@ +name: Nitro Docs + +on: + push: + branches: + - main + paths: + - 'docs/**' + pull_request: + branches: + - main + paths: + - 'docs/**' + - '.github/workflows/docs.yml' + # Review gh actions docs if you want to further define triggers, paths, etc + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + +jobs: + deploy: + name: Deploy to GitHub Pages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install jq + uses: dcarbone/install-jq-action@v2.0.1 + + - name: Fill env vars + run: | + env_example_file=".env.example" + touch .env + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" == *"="* ]]; then + var_name=$(echo $line | cut -d '=' -f 1) + echo $var_name + var_value="$(jq -r --arg key "$var_name" '.[$key]' <<< "$SECRETS")" + echo "$var_name=$var_value" >> .env + fi + done < "$env_example_file" + working-directory: docs + env: + SECRETS: '${{ toJson(secrets) }}' + + - name: Install dependencies + run: yarn install + working-directory: docs + - name: Build website + run: sed -i '/process.env.DEBUG = namespaces;/c\// process.env.DEBUG = namespaces;' ./node_modules/debug/src/node.js && yarn build + working-directory: docs + + - name: Add Custome Domain file + if: github.event_name == 'push' && github.event.pull_request.head.repo.full_name != github.repository + run: echo "${{ vars.DOCUSAURUS_DOMAIN }}" > ./docs/build/CNAME + + # Popular action to deploy to GitHub Pages: + # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus + - name: Deploy to GitHub Pages + if: github.event_name == 'push' && github.event.pull_request.head.repo.full_name != github.repository + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + # Build output to publish to the `gh-pages` branch: + publish_dir: ./docs/build + # The following lines assign commit authorship to the official + # GH-Actions bot for deploys to `gh-pages` branch: + # https://github.com/actions/checkout/issues/13#issuecomment-724415212 + # The GH actions bot is used by default if you didn't specify the two fields. + # You can swap them out with your own user credentials. + user_name: github-actions[bot] + user_email: 41898282+github-actions[bot]@users.noreply.github.com \ No newline at end of file diff --git a/.gitignore b/.gitignore index aec371ecf..f75df993e 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,7 @@ *.pdb # Kernel Module Compile Results -*.mod* +*.mod *.cmd .tmp_versions/ modules.order diff --git a/docs/.env.example b/docs/.env.example new file mode 100644 index 000000000..6a9e9757c --- /dev/null +++ b/docs/.env.example @@ -0,0 +1,2 @@ +POSTHOG_PROJECT_API_KEY=xxxx +POSTHOG_APP_URL=xxxx \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..811400bb3 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,21 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.env \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..f516942cb --- /dev/null +++ b/docs/README.md @@ -0,0 +1,45 @@ +# Website + +This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. + +### Installation + +``` +$ yarn +``` + +### Local Development + +``` +$ yarn start +``` + +This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. + +### Build + +``` +$ yarn build +``` + +This command generates static content into the `build` directory and can be served using any static contents hosting service. + +### Deployment + +Using SSH: + +``` +$ USE_SSH=true yarn deploy +``` + +Not using SSH: + +``` +$ GIT_USER= yarn deploy +``` + +If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. + +### Additional Plugins +- @docusaurus/theme-live-codeblock +- [Redocusaurus](https://redocusaurus.vercel.app/): manually upload swagger files at `/openapi/OpenAPISpec.json` \ No newline at end of file diff --git a/docs/babel.config.js b/docs/babel.config.js new file mode 100644 index 000000000..e00595dae --- /dev/null +++ b/docs/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml new file mode 100644 index 000000000..f30d4610d --- /dev/null +++ b/docs/blog/authors.yml @@ -0,0 +1,6 @@ +dan-jan: + name: Daniel Onggunhao + title: Co-Founder + url: https://github.com/dan-jan + image_url: https://avatars.githubusercontent.com/u/101145494?v=4 + email: daniel@jan.ai \ No newline at end of file diff --git a/docs/blog/hello-world.md b/docs/blog/hello-world.md new file mode 100644 index 000000000..ad080e320 --- /dev/null +++ b/docs/blog/hello-world.md @@ -0,0 +1,12 @@ +--- +title: Hello World +description: This is my first post on Docusaurus. +slug: hello-world +authors: + - name: Daniel +tags: [hello, jan] +image: https://i.imgur.com/mErPwqL.png +hide_table_of_contents: false +--- + +Hello World! \ No newline at end of file diff --git a/docs/blog/test.md b/docs/blog/test.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/docs/api/overview.md b/docs/docs/api/overview.md new file mode 100644 index 000000000..7137deb37 --- /dev/null +++ b/docs/docs/api/overview.md @@ -0,0 +1,3 @@ +--- +title: Overview +--- diff --git a/docs/docs/community/changelog.md b/docs/docs/community/changelog.md new file mode 100644 index 000000000..66b750854 --- /dev/null +++ b/docs/docs/community/changelog.md @@ -0,0 +1,4 @@ +--- +title: Nitro Changelog +--- + diff --git a/docs/docs/community/coc.md b/docs/docs/community/coc.md new file mode 100644 index 000000000..b74e5a9ec --- /dev/null +++ b/docs/docs/community/coc.md @@ -0,0 +1,54 @@ +--- +title: Code of Conduct +--- + +# Maximize Signal-to-Noise Ratio + +## 1. Don't Waste Time +- **Efficient Contributions**: Ensure your posts, commits, or comments are efficient and valuable. Avoid low-effort or trivial contributions. +- **Consequence of Non-Compliance**: Repeated low-value contributions may lead to removal or a ban. +- **Impact**: This policy aims to minimize distractions and time-wasting (Noise). + +## 2. Add Value +- **Contribute Meaningfully**: Your contributions should be concise, impactful, and helpful. +- **Focus on Clarity**: Be clear and to the point. Avoid lengthy, complex explanations where simpler ones will do. + +## 3. Do No Harm +- **Respectful Interaction**: No tolerance for insults, trolling, or disruptive debates. +- **Maintain Positive Environment**: Harassing behavior or needless argumentation will lead to an immediate, irrevocable ban. + +### Guidelines for Constructive Contributions + +**Effective Use of Time**: +- Time is invaluable. Use it wisely and respect others' time. +- Make sure reading your contribution is worthwhile and not a drain on cognitive resources. + +**What to Do**: +- **High-Quality Posts**: Well-organized, clear, concise, and to the point. +- **Efficient Demonstrations**: Convey information quickly and clearly. +- **Useful Examples**: Illustrate how and why things work without unnecessary detail. + +**What to Avoid**: +- **Unproductive Debates**: Avoid arguing over minor details or off-topic issues. +- **Shifting Focus**: Don’t constantly change topics or goals. +- **Excessive Length or Irrelevance**: Long-winded, opinionated, or irrelevant posts. + +### Encouraging Valuable Contributions + +**Focus on Adding Value**: +- Contribute only when it enhances understanding, solves problems, or is genuinely helpful. +- If unsure whether your contribution adds value, consider refining or omitting it. + +**Positive Contributions Include**: +- Solving problems efficiently. +- Adding or improving code. +- Sharing resources that benefit the collective understanding. + +### Maintaining a Respectful Environment + +**Zero Tolerance for Disruptive Behavior**: +- Any form of trolling, flaming, or griefing is strictly prohibited. +- Disruptive behavior leads to immediate and permanent exclusion. + +**Participation is a Privilege**: +- Remember that being part of this project and community is a privilege. Act responsibly and respectfully to maintain a productive and inclusive environment. diff --git a/docs/docs/community/contribuiting.md b/docs/docs/community/contribuiting.md new file mode 100644 index 000000000..215ac9d65 --- /dev/null +++ b/docs/docs/community/contribuiting.md @@ -0,0 +1,41 @@ +--- +title: Contributing to Nitro +--- + +Nitro is an open-source, fast, lightweight, and embeddable inference engine. It's used in [Jan](https://jan.ai/). This document guides you through the process of contributing to Nitro, whether you’re new to open source or an experienced contributor. + +- For New Contributors, please check out [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) for a general guide on open-source contribution. + +## Code of Conduct +Before contributing, please read our [Code of Conduct](coc) to understand the rules and expectations in our community. + +## Get Involved +There are many ways to contribute to Nitro, and not all involve coding. Here's a few ideas to get started: + +- Begin by going through the [Getting Started](nitro/overview) guide. If you encounter issues or have suggestions, let us know by [opening an issue](https://github.com/janhq/nitro/issues). + +- Browse [open issues](https://github.com/janhq/nitro/issues). You can offer workarounds, clarification, or suggest labels to help organize issues. If you find an issue you’d like to resolve, feel free to [open a pull request](https://github.com/janhq/nitro/pulls). Start with issues tagged as `Good first issue`. + +- Read through Nitro's documentation. If something is confusing or can be improved, click “Edit this page” at the bottom of most docs to propose changes directly on GitHub. + +- Check out feature requests from the community. You can contribute by opening a [pull request](https://github.com/janhq/nitro/pulls) for something you’re interested in working on. + +### Join our Discord Channel +We have the [#nitro-dev](https://discord.gg/FTk2MvZwJH) channel on [Discord](https://discord.gg/FTk2MvZwJH) to discuss all things about Nitro development. You can also be of great help by helping other users in the help channel. + +## How to Contribute +### Reporting Issues +- If you encounter problems with Nitro, create a [GitHub issue](https://github.com/janhq/nitro). +- Describe the issue in detail, including error logs and steps to reproduce it. + +### Feature Requests +- For new features, submit a request on [Nitro’s official GitHub](https://github.com/janhq/nitro). Avoid duplicate requests and clearly explain the benefits of your proposed feature. + +### Pull Requests +- You can submit one Pull Request (PR) per day. +- Make sure your PR has a clear description and adheres to Nitro's code style and structure. +- Avoid unnecessary reformatting or refactoring. PRs not following these guidelines will be considered non-compliant and may be rejected. + +### Triaging Issues and PRs +- Help manage incoming issues and PRs by asking for more information, suggesting labels, flagging stale issues, or asking for test plans. +- Review code if you can and provide constructive feedback. \ No newline at end of file diff --git a/docs/docs/community/support.md b/docs/docs/community/support.md new file mode 100644 index 000000000..ef13a5efa --- /dev/null +++ b/docs/docs/community/support.md @@ -0,0 +1,17 @@ +--- +title: Support +--- + +On this page we've listed some Nitro-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. + +## Discord + +Join our [Discord](https://discord.gg/FTk2MvZwJH) for questions and discussion. Use the `#nitro-dev`` channel for discussions or questions. + +## Github + +Join our [Github](https://github.com/janhq/nitro) for understanding codebase. + +## News +For the latest news about Nitro, follow [Nitro Discord](https://discord.gg/FTk2MvZwJH) and the [official Nitro blog](https://nitro.jan.ai) on this website. + diff --git a/docs/docs/guides/overview.md b/docs/docs/guides/overview.md new file mode 100644 index 000000000..8e7f03312 --- /dev/null +++ b/docs/docs/guides/overview.md @@ -0,0 +1,6 @@ +--- +title: Overview +slug: /guides +--- + +About Nitro diff --git a/docs/docs/guides/troubleshooting.md b/docs/docs/guides/troubleshooting.md new file mode 100644 index 000000000..f7010e49f --- /dev/null +++ b/docs/docs/guides/troubleshooting.md @@ -0,0 +1,3 @@ +--- +title: Troubleshooting Nitro +--- diff --git a/docs/docs/nitro/architecture.md b/docs/docs/nitro/architecture.md new file mode 100644 index 000000000..a127910ca --- /dev/null +++ b/docs/docs/nitro/architecture.md @@ -0,0 +1,33 @@ +--- +title: Architecture +--- + +:::info +This document is being updated. Please stay tuned. +::: + +![Nitro Architecture](img/architecture.drawio.png) + +### Components + +- **Nitro CLI**: A command-line interface that manages model conversion and compilation for deployment. + + - **Converter**: Transforms the model into a compatible format (GGUF) for the Nitro system. + - **Compiler**: Optimizes the converted model for efficient execution. + +- **TensorRT - LLM**: A specialized component for large language models using NVIDIA's TensorRT optimization. + +- **Triton Inference Server**: Serves the optimized model, facilitating scalable and efficient inference requests via gRPC. + +- **Nitro.cpp**: The C++ implementation handling the deployment and interfacing of the models. + + - **Adapters**: + - **llama.cpp**: + - **Triton LMDeploy**:. + - **Inference File Server**: Manages files necessary for inference operations. + - **Cache**: Stores temporary data to improve performance. + - **Apps**: + - **Interface**: + - **JanAPI**: + - **OpenAI Compatible**: Ensures compatibility with OpenAI standards for ease of integration. + diff --git a/docs/docs/nitro/img/architecture.drawio.png b/docs/docs/nitro/img/architecture.drawio.png new file mode 100644 index 000000000..4c1100bc8 Binary files /dev/null and b/docs/docs/nitro/img/architecture.drawio.png differ diff --git a/docs/docs/nitro/installation.mdx b/docs/docs/nitro/installation.mdx new file mode 100644 index 000000000..06b1d92a5 --- /dev/null +++ b/docs/docs/nitro/installation.mdx @@ -0,0 +1,101 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Installation +## How to install + +This guide provides step-by-step instructions for installing the software on various operating systems. Please follow the steps that correspond to your system. + +### Step 1: Install dependencies + +First, you need to install the necessary dependencies. + + + +

Open the terminal, navigate to the project directory, and run:

+
./install_deps.sh
+
+ +

Open Command Prompt as Administrator, navigate to the project directory, and execute:

+
cmake -S ./nitro_deps -B ./build_deps/nitro_deps
+cmake --build ./build_deps/nitro_deps --config Release
+
+
+ +A new folder named `build_deps` will be created. + +### Step 2: Generate Build Files + +You will now generate the build files needed to compile the software. + + + +

In the terminal, run:

+
mkdir build && cd build
+cmake -DLLAMA_METAL=OFF ..
+
+ +

In the terminal, run:

+
mkdir build && cd build
+cmake -DLLAMA_CUBLAS=ON ..
+
+ +

In the terminal, run:

+
mkdir build && cd build
+cmake ..
+
+ +

In the terminal (or Command Prompt for Windows), run:

+
mkdir build && cd build
+cmake ..
+
+
+ +### Step 3: Build the Application + +Now it's time to compile the software. + + + +

Open the terminal and enter:

+
make -j $(sysctl -n hw.physicalcpu)
+
+ +

Open the terminal and enter:

+
make -j $(nproc)
+
+ +

In Command Prompt, run:

+
cmake --build . --config Release
+
+
+ +### Step 4: Run the Application + +To start the application: + + + +

In the terminal, navigate to the build directory and run:

+
./nitro
+
+ +

In the terminal, navigate to the build directory and run:

+
./nitro
+
+ +

In Command Prompt, navigate to the Release directory within the build folder and execute:

+
copy ..\..\build_deps\_install\bin\zlib.dll .
+nitro.exe
+
+
+ +### Verification: + +To verify if the build was successful, open your web browser and go to: + +``` +localhost:8080/test +``` + +You should see a confirmation page if the installation was successful. diff --git a/docs/docs/nitro/key-concepts.md b/docs/docs/nitro/key-concepts.md new file mode 100644 index 000000000..361bccee1 --- /dev/null +++ b/docs/docs/nitro/key-concepts.md @@ -0,0 +1,27 @@ +--- +title: Key Concepts +--- + +## Inference Server + +An inference server is a type of server designed to process requests for running large language models and to return predictions. This server acts as the backbone for AI-powered applications, providing real-time execution of models to analyze data and make decisions. + +## Batching + +Batching refers to the process of grouping several tasks and processing them as a single batch. In large language models inference, this means combining multiple inference requests into one batch to improve computational efficiency, leading to quicker response times and higher throughput. + +## Parallel Processing + +Parallel processing involves executing multiple computations simultaneously. For web servers and applications, this enables the handling of multiple requests at the same time, ensuring high efficiency and preventing delays in request processing. + +## Drogon Framework + +Drogon is an HTTP application framework based on C++14/17, designed for its speed and simplicity. Utilizing a non-blocking I/O and event-driven architecture, Drogon manages HTTP requests efficiently for high-performance and scalable applications. + +- **Event Loop**: Drogon uses an event loop to wait for and dispatch events or messages within a program. This allows for handling many tasks asynchronously, without relying on multi-threading. + +- **Threads**: While the event loop allows for efficient task management, Drogon also employs threads to handle parallel operations. These "drogon threads" process multiple tasks concurrently. + +- **Asynchronous Operations**: The framework supports non-blocking operations, permitting the server to continue processing other tasks while awaiting responses from databases or external services. + +- **Scalability**: Drogon's architecture is built to scale, capable of managing numerous connections at once, suitable for applications with high traffic loads. \ No newline at end of file diff --git a/docs/docs/nitro/overview.md b/docs/docs/nitro/overview.md new file mode 100644 index 000000000..876b4b7e6 --- /dev/null +++ b/docs/docs/nitro/overview.md @@ -0,0 +1,48 @@ +--- +title: Introduction +--- + +Nitro, is the lightweight inference engine that powers Jan. Nitro is written in C++, optimized for edge deployment. + +⚡ Explore Nitro's codebase: [GitHub](https://github.com/janhq/nitro) + +## Dependencies and Acknowledgements: + +- [llama.cpp](https://github.com/ggerganov/llama.cpp): Nitro wraps Llama.cpp, which runs Llama models in C++ +- [drogon](https://github.com/drogonframework/drogon): Nitro runs Drogon, which is a fast, C++17/20 HTTP application framework. +- (Coming soon) tensorrt-llm support. + +## Features + +In addition to the above features, Nitro also provides: + +- OpenAI compatibility +- HTTP interface with no bindings needed +- Runs as a separate process, not interfering with main app processes +- Multi-threaded server supporting concurrent users +- 1-click install +- No hardware dedendencies +- Ships as a small binary (~3mb compressed on average) +- Runs on Windows, MacOS, and Linux +- Compatible with arm64, x86, and NVIDIA GPUs + +## HTTP Interface + +Nitro offers a straightforward HTTP interface. With compatibility for multiple standard APIs, including OpenAI formats. + +```bash +curl --location 'http://localhost:3928/inferences/llamacpp/chat_completion' \ + --header 'Content-Type: application/json' \ + --header 'Accept: text/event-stream' \ + --header 'Access-Control-Allow-Origin: *' \ + --data '{ + "messages": [ + {"content": "Hello there 👋", "role": "assistant"}, + {"content": "Can you write a long story", "role": "user"} + ], + "stream": true, + "model": "gpt-3.5-turbo", + "max_tokens": 2000 + }' +``` + diff --git a/docs/docs/nitro/using-nitro.md b/docs/docs/nitro/using-nitro.md new file mode 100644 index 000000000..573ea9975 --- /dev/null +++ b/docs/docs/nitro/using-nitro.md @@ -0,0 +1,71 @@ +--- +title: Quick start +--- + +## Step 1: Download Nitro + +To use Nitro, download the released binaries from the release page below: + +🔗 [Download Nitro](https://github.com/janhq/nitro/releases) + +After downloading the release, double-click on the Nitro binary. + +## Step 2: Download a Model + +Download a llama model to try running the llama C++ integration. You can find a "GGUF" model on The Bloke's page below: + +🔗 [Download Model](https://huggingface.co/TheBloke) + +## Step 3: Run Nitro + +Double-click on Nitro to run it. After downloading your model, make sure it's saved to a specific path. Then, make an API call to load your model into Nitro. + +```zsh +curl -X POST 'http://localhost:3928/inferences/llamacpp/loadmodel' \ + -H 'Content-Type: application/json' \ + -d '{ + "llama_model_path": "/path/to/your_model.gguf", + "ctx_len": 2048, + "ngl": 100, + "embedding": true, + "n_parallel": 4, + "pre_prompt": "A chat between a curious user and an artificial intelligence", + "user_prompt": "USER: ", + "ai_prompt": "ASSISTANT: " + }' +``` + +Configure your system by setting the following parameters in your `jsonBody`. The table below outlines each parameter and its description: + +| Parameter | Type | Description | +|------------------|---------|--------------------------------------------------------------| +| `llama_model_path` | String | The file path to the LLaMA model. | +| `ngl` | Integer | The number of GPU layers to use. | +| `ctx_len` | Integer | The context length for the model operations. | +| `embedding` | Boolean | Whether to use embedding in the model. | +| `n_parallel` | Integer | The number of parallel operations. Uses Drogon thread count if not set. | +| `cont_batching` | Boolean | Whether to use continuous batching. | +| `user_prompt` | String | The prompt to use for the user. | +| `ai_prompt` | String | The prompt to use for the AI assistant. | +| `system_prompt` | String | The prompt to use for system rules. | +| `pre_prompt` | String | The prompt to use for internal configuration. | + +## Step 4: Nitro Inference + +```zsh +curl --location 'http://localhost:3928/inferences/llamacpp/chat_completion' \ + --header 'Content-Type: application/json' \ + --header 'Accept: text/event-stream' \ + --header 'Access-Control-Allow-Origin: *' \ + --data '{ + "messages": [ + {"content": "Hello there 👋", "role": "assistant"}, + {"content": "Can you write a long story", "role": "user"} + ], + "stream": true, + "model": "gpt-3.5-turbo", + "max_tokens": 2000 + }' +``` + +Nitro server is compatible with the OpenAI format, so you can expect the same output as the OpenAI ChatGPT API. \ No newline at end of file diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js new file mode 100644 index 000000000..90884e843 --- /dev/null +++ b/docs/docusaurus.config.js @@ -0,0 +1,174 @@ +// @ts-check +// Note: type annotations allow type checking and IDEs autocompletion + +require("dotenv").config(); + +const lightCodeTheme = require("prism-react-renderer/themes/github"); +const darkCodeTheme = require("prism-react-renderer/themes/dracula"); + +/** @type {import('@docusaurus/types').Config} */ +const config = { + title: "Nitro", + tagline: "Fast inference engine", + favicon: "img/favicon.ico", + + // Set the production url of your site here + url: "https://nitro.jan.ai", + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: "/", + + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: "janhq", // Usually your GitHub org/user name. + projectName: "nitro", // Usually your repo name. + + onBrokenLinks: "warn", + onBrokenMarkdownLinks: "warn", + + // Even if you don't use internalization, you can use this field to set useful + // metadata like html lang. For example, if your site is Chinese, you may want + // to replace "en" with "zh-Hans". + i18n: { + defaultLocale: "en", + locales: ["en"], + }, + + // Plugins we added + plugins: [ + "docusaurus-plugin-sass", + async function myPlugin(context, options) { + return { + name: "docusaurus-tailwindcss", + configurePostCss(postcssOptions) { + // Appends TailwindCSS and AutoPrefixer. + postcssOptions.plugins.push(require("tailwindcss")); + postcssOptions.plugins.push(require("autoprefixer")); + return postcssOptions; + }, + }; + }, + [ + "posthog-docusaurus", + { + apiKey: process.env.POSTHOG_PROJECT_API_KEY, + appUrl: process.env.POSTHOG_APP_URL, // optional + enableInDevelopment: false, // optional + }, + ], + ], + + // Only for react live + themes: ["@docusaurus/theme-live-codeblock"], + + // The classic preset will relay each option entry to the respective sub plugin/theme. + presets: [ + [ + "classic", + /** @type {import('@docusaurus/preset-classic').Options} */ + ({ + // Will be passed to @docusaurus/plugin-content-docs (false to disable) + docs: { + routeBasePath: "/", + sidebarPath: require.resolve("./sidebars.js"), + editUrl: "https://github.com/janhq/nitro/tree/main/docs", + showLastUpdateAuthor: true, + showLastUpdateTime: true, + }, + // Will be passed to @docusaurus/plugin-content-sitemap (false to disable) + sitemap: { + changefreq: "daily", + priority: 1.0, + ignorePatterns: ["/tags/**"], + filename: "sitemap.xml", + }, + // Will be passed to @docusaurus/plugin-content-blog (false to disable) + blog: { + blogSidebarTitle: "All Posts", + blogSidebarCount: "ALL", + }, + // Will be passed to @docusaurus/theme-classic. + theme: { + customCss: require.resolve("./src/styles/main.scss"), + }, + // Will be passed to @docusaurus/plugin-content-pages (false to disable) + // pages: {}, + }), + ], + // Redoc preset + [ + "redocusaurus", + { + specs: [ + { + spec: "openapi/OpenAPISpec.json", // can be local file, url, or parsed json object + route: "/api/", + }, + ], + theme: { + primaryColor: "#1a73e8", + primaryColorDark: "#1a73e8", + // redocOptions: { hideDownloadButton: false }, + }, + }, + ], + ], + + // Docs: https://docusaurus.io/docs/api/themes/configuration + themeConfig: + /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ + ({ + image: "img/nitro-social-card.png", + // Only for react live + liveCodeBlock: { + playgroundPosition: "bottom", + }, + navbar: { + title: "Nitro", + logo: { + alt: "Nitro Logo", + src: "img/logo.svg", + }, + items: [ + // Navbar left + { + type: "docSidebar", + sidebarId: "docsSidebar", + position: "left", + label: "Documentation", + }, + { + type: "docSidebar", + sidebarId: "apiSidebar", + position: "left", + label: "API Reference", + }, + { + type: "docSidebar", + sidebarId: "communitySidebar", + position: "left", + label: "Community", + }, + // Navbar right + { + type: "docSidebar", + sidebarId: "blogSidebar", + position: "right", + label: "Blog", + }, + ], + }, + prism: { + theme: lightCodeTheme, + darkTheme: darkCodeTheme, + additionalLanguages: ["python"], + }, + colorMode: { + defaultMode: "dark", + disableSwitch: false, + respectPrefersColorScheme: false, + }, + }), +}; + +module.exports = config; diff --git a/docs/manual_install.md b/docs/manual_install.md deleted file mode 100644 index d3e8ebeb0..000000000 --- a/docs/manual_install.md +++ /dev/null @@ -1,63 +0,0 @@ -# How to install - -### Step 1: - -Install dependencies static files -- On MacOS with Apple silicon - ```zsh - ./install_deps.sh - ``` -- On Windows - ``` - cmake -S ./nitro_deps -B ./build_deps/nitro_deps - cmake --build ./build_deps/nitro_deps --config Release - ``` -This will create a build_deps folder, just ignore it - -### Step 2: - -Generate build file -- On MacOS, Linux, and Windows - - ```zsh - mkdir build && cd build - cmake .. - ``` - -- On MacOS with Intel processors - ```zsh - mkdir build && cd build - cmake -DLLAMA_METAL=OFF .. - ``` - -- On Linux with CUDA: - ```zsh - mkdir build && cd build - cmake -DLLAMA_CUBLAS=ON .. - ``` - - -Build the app -- On MacOS and Linux - ``` - # MacOS - make -j $(sysctl -n hw.physicalcpu) - # Linux - make -j $(%NUMBER_OF_PROCESSORS%) - ``` - -- On Windows - ``` - cmake --build . --config Release - ``` - -### Step 3: -- On MacOS and Linux run ./nitro to start the process. -- On Windows: - ``` - cd Release - # add zlib dynamic lib - copy ..\..\build_deps\_install\bin\zlib.dll . - nitro.exe - -To see if the build was successful, visit `localhost:8080/test` diff --git a/docs/openapi/OpenAPISpec.json b/docs/openapi/OpenAPISpec.json new file mode 100644 index 000000000..9c18ec9d1 --- /dev/null +++ b/docs/openapi/OpenAPISpec.json @@ -0,0 +1,74 @@ +{ + "openapi": "3.0.0", + "info": { + "description": "Jan.ai api reference documentation.", + "title": "Rest Endpoints", + "version": "" + }, + "paths": { + "/api/rest/myquery": { + "get": { + "summary": "MyQuery", + "description": "***\nThe GraphQl query for this endpoint is:\n``` graphql\nquery MyQuery {\n collections {\n id\n name\n slug\n }\n}\n```", + "parameters": [ + { + "description": "Your x-hasura-admin-secret will be used for authentication of the API request.", + "in": "header", + "name": "x-hasura-admin-secret", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "collections": { + "items": { + "description": "columns and relationships of \"collections\"", + "nullable": false, + "properties": { + "id": { + "$ref": "#/components/schemas/uuid!" + }, + "name": { + "nullable": false, + "title": "String", + "type": "string" + }, + "slug": { + "nullable": false, + "title": "String", + "type": "string" + } + }, + "title": "collections", + "type": "object" + }, + "nullable": false, + "type": "array" + } + } + } + } + }, + "description": "Responses for GET /api/rest/myquery" + } + } + } + } + }, + "components": { + "schemas": { + "uuid!": { + "nullable": false, + "pattern": "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}", + "title": "uuid", + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..9a122d340 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,59 @@ +{ + "name": "docs", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start --port 3000", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids" + }, + "dependencies": { + "@docusaurus/core": "^2.4.3", + "@docusaurus/preset-classic": "^2.4.3", + "@docusaurus/theme-live-codeblock": "^2.4.3", + "@docusaurus/theme-mermaid": "^3.0.0", + "@headlessui/react": "^1.7.17", + "@heroicons/react": "^2.0.18", + "@mdx-js/react": "^1.6.22", + "autoprefixer": "^10.4.16", + "axios": "^1.5.1", + "clsx": "^1.2.1", + "docusaurus-plugin-sass": "^0.2.5", + "dotenv": "^16.3.1", + "js-yaml": "^4.1.0", + "postcss": "^8.4.30", + "posthog-docusaurus": "^2.0.0", + "prism-react-renderer": "^1.3.5", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-icons": "^4.11.0", + "redocusaurus": "^1.6.3", + "sass": "^1.69.3", + "tailwindcss": "^3.3.3" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "2.4.1", + "tailwindcss-animate": "^1.0.7" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "engines": { + "node": ">=16.14" + } +} diff --git a/docs/sidebars.js b/docs/sidebars.js new file mode 100644 index 000000000..3e6e280c0 --- /dev/null +++ b/docs/sidebars.js @@ -0,0 +1,59 @@ +/** + * Creating a sidebar enables you to: + - create an ordered group of docs + - render a sidebar for each doc of that group + - provide next/previous navigation + + The sidebars are explicitly defined here. + + Create as many sidebars as you want. + */ + +// @ts-check + +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const sidebars = { + blogSidebar: [ + "guides/overview" + ], + + docsSidebar: [ + "nitro/overview", + { + type: 'category', + label: 'Getting Started', + items: [ + "nitro/key-concepts", + "nitro/architecture", + "nitro/installation", + "nitro/using-nitro", + ], + }, + "guides/troubleshooting", + ], + + apiSidebar: [ + "api/overview", + { + type: "category", + label: "Endpoints", + collapsible: true, + collapsed: false, + items: [ + { + type: "autogenerated", + dirName: "api", + }, + ], + }, + ], + + communitySidebar: [ + "community/support", + "community/contribuiting", + "community/coc", + "community/changelog" + ] +}; + +module.exports = sidebars; diff --git a/docs/src/components/Announcement/index.js b/docs/src/components/Announcement/index.js new file mode 100644 index 000000000..641687684 --- /dev/null +++ b/docs/src/components/Announcement/index.js @@ -0,0 +1,78 @@ +import React from "react"; + +import { useAppStars } from "@site/src/hooks/useAppStars"; +import { useAppRelease } from "@site/src/hooks/useAppRelease"; + +import { AiOutlineGithub, AiOutlineTwitter } from "react-icons/ai"; +import { BiLogoDiscordAlt } from "react-icons/bi"; + +const socials = [ + { + icon: , + href: "https://twitter.com/janhq_", + }, + { + icon: , + href: "https://discord.com/invite/FTk2MvZwJH", + }, + { + icon: , + href: "https://github.com/janhq/nitro", + }, +]; + +export default function AnnoncementBanner() { + const { stargazers } = useAppStars(); + const { release } = useAppRelease(); + + return ( + + ); +} diff --git a/docs/src/components/Elements/dropdown.js b/docs/src/components/Elements/dropdown.js new file mode 100644 index 000000000..443547132 --- /dev/null +++ b/docs/src/components/Elements/dropdown.js @@ -0,0 +1,169 @@ +import React, { useState, useEffect } from "react"; +import { Fragment } from "react"; +import { Menu, Transition } from "@headlessui/react"; +import { ChevronDownIcon } from "@heroicons/react/20/solid"; +import axios from "axios"; + +const systemsTemplate = [ + { + name: "Download for Mac (M1/M2)", + logo: require("@site/static/img/apple-logo-white.png").default, + fileFormat: "{appname}-mac-arm64-{tag}.dmg", + }, + { + name: "Download for Mac (Intel)", + logo: require("@site/static/img/apple-logo-white.png").default, + fileFormat: "{appname}-mac-x64-{tag}.dmg", + }, + { + name: "Download for Windows", + logo: require("@site/static/img/windows-logo-white.png").default, + fileFormat: "{appname}-win-x64-{tag}.exe", + }, + { + name: "Download for Linux", + logo: require("@site/static/img/linux-logo-white.png").default, + fileFormat: "{appname}-linux-amd64-{tag}.deb", + }, +]; + +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} + +export default function Dropdown() { + const [systems, setSystems] = useState(systemsTemplate); + const [defaultSystem, setDefaultSystem] = useState(systems[0]); + + const getLatestReleaseInfo = async (repoOwner, repoName) => { + const url = `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`; + try { + const response = await axios.get(url); + return response.data; + } catch (error) { + console.error(error); + return null; + } + }; + + const extractAppName = (fileName) => { + // Extract appname using a regex that matches the provided file formats + const regex = /^(.*?)-(?:mac|win|linux)-(?:arm64|x64|amd64)-.*$/; + const match = fileName.match(regex); + return match ? match[1] : null; + }; + + const changeDefaultSystem = (systems) => { + const userAgent = navigator.userAgent; + if (userAgent.includes("Windows")) { + // windows user + setDefaultSystem(systems[2]); + } else if (userAgent.includes("Linux")) { + // linux user + setDefaultSystem(systems[3]); + } else if (userAgent.includes("Mac OS") && userAgent.includes("Intel")) { + // mac intel user + setDefaultSystem(systems[1]); + } else { + // mac user and also default + setDefaultSystem(systems[0]); + } + }; + useEffect(() => { + const updateDownloadLinks = async () => { + try { + const releaseInfo = await getLatestReleaseInfo("janhq", "jan"); + + // Extract appname from the first asset name + const firstAssetName = releaseInfo.assets[0].name; + const appname = extractAppName(firstAssetName); + + if (!appname) { + console.error( + "Failed to extract appname from file name:", + firstAssetName + ); + changeDefaultSystem(systems); + return; + } + + // Remove 'v' at the start of the tag_name + const tag = releaseInfo.tag_name.startsWith("v") + ? releaseInfo.tag_name.substring(1) + : releaseInfo.tag_name; + + const updatedSystems = systems.map((system) => { + const downloadUrl = system.fileFormat + .replace("{appname}", appname) + .replace("{tag}", tag); + return { + ...system, + href: `https://github.com/janhq/jan/releases/download/${releaseInfo.tag_name}/${downloadUrl}`, + }; + }); + + setSystems(updatedSystems); + changeDefaultSystem(updatedSystems); + } catch (error) { + console.error("Failed to update download links:", error); + } + }; + + updateDownloadLinks(); + }, []); + + return ( +
+ + Logo + {defaultSystem.name} + + + + Open OS options + + + +
+ {systems.map((system) => ( + setDefaultSystem(system)} + > + {({ active }) => ( + + Logo + {system.name} + + )} + + ))} +
+
+
+
+
+ ); +} diff --git a/docs/src/components/Footer/index.js b/docs/src/components/Footer/index.js new file mode 100644 index 000000000..c546c1f50 --- /dev/null +++ b/docs/src/components/Footer/index.js @@ -0,0 +1,123 @@ +import React from "react"; + +const menus = [ + { + name: "Resources", + child: [ + { + menu: "Home", + path: "/", + }, + { + menu: "Platform", + path: "/platform", + }, + { + menu: "Solutions", + path: "/solutions", + }, + ], + }, + { + name: "For Developers", + child: [ + { + menu: "Documentation (WIP)", + path: "/docs", + }, + { + menu: "Hardware (WIP)", + path: "/hardware", + }, + { + menu: "API (WIP)", + path: "/api", + }, + { + menu: "Changelog", + path: "https://github.com/janhq/nitro/releases", + external: true, + }, + ], + }, + { + name: "Community", + child: [ + { + menu: "Github", + path: "https://github.com/janhq/nitro", + external: true, + }, + { + menu: "Discord", + path: "https://discord.gg/FTk2MvZwJH", + external: true, + }, + { + menu: "Twitter", + path: "https://twitter.com/janhq_", + external: true, + }, + ], + }, + { + name: "Company", + child: [ + { + menu: "About", + path: "/about", + }, + { + menu: "Careers", + path: "https://janai.bamboohr.com/careers", + external: true, + }, + ], + }, +]; + +const getCurrentYear = new Date().getFullYear(); + +export default function Footer() { + return ( +
+
+
+
+
Nitro
+

+ Fast, Lightweight and Embeddable inference engine +

+
+ {menus.map((menu, i) => { + return ( +
+
{menu.name}
+ +
+ ); + })} +
+
+
+ + ©{getCurrentYear} Jan AI Pte Ltd. + +
+
+ ); +} diff --git a/docs/src/css/custom_toc.css b/docs/src/css/custom_toc.css new file mode 100644 index 000000000..caa5d1982 --- /dev/null +++ b/docs/src/css/custom_toc.css @@ -0,0 +1,5 @@ +.custom-toc-title { + font-weight: bold; + margin-bottom: 16px; + margin-top: -20px; + } \ No newline at end of file diff --git a/docs/src/hooks/useAppRelease.js b/docs/src/hooks/useAppRelease.js new file mode 100644 index 000000000..0ce13d26f --- /dev/null +++ b/docs/src/hooks/useAppRelease.js @@ -0,0 +1,31 @@ +import React, { useEffect, useState } from "react"; + +import axios from "axios"; + +import { isAxiosError } from "axios"; + +export const useAppRelease = () => { + const [release, setRelease] = useState({ + tagVersion: "", + }); + + useEffect(() => { + const updateStargazers = async () => { + try { + const { data } = await axios.get( + "https://api.github.com/repos/janhq/nitro/releases/latest" + ); + setRelease({ + tagVersion: data.tag_name, + }); + } catch (error) { + if (isAxiosError(error)) { + console.error("Failed to get stargazers:", error); + } + } + }; + updateStargazers(); + }, []); + + return { release }; +}; diff --git a/docs/src/hooks/useAppStars.js b/docs/src/hooks/useAppStars.js new file mode 100644 index 000000000..d4d374bc8 --- /dev/null +++ b/docs/src/hooks/useAppStars.js @@ -0,0 +1,30 @@ +import React, { useEffect, useState } from "react"; + +import axios from "axios"; +import { isAxiosError } from "axios"; + +export const useAppStars = () => { + const [stargazers, setStargazers] = useState({ + count: 0, + }); + + useEffect(() => { + const updateStargazers = async () => { + try { + const { data } = await axios.get( + "https://api.github.com/repos/janhq/nitro" + ); + setStargazers({ + count: data.stargazers_count, + }); + } catch (error) { + if (isAxiosError(error)) { + console.error("Failed to get stargazers:", error); + } + } + }; + updateStargazers(); + }, []); + + return { stargazers }; +}; diff --git a/docs/src/js/custom_toc.js b/docs/src/js/custom_toc.js new file mode 100644 index 000000000..7cda4e86a --- /dev/null +++ b/docs/src/js/custom_toc.js @@ -0,0 +1,9 @@ +document.addEventListener('DOMContentLoaded', function () { + const toc = document.querySelector('.table-of-contents'); + if (toc) { + const title = document.createElement('div'); + title.className = 'custom-toc-title'; + title.innerText = 'On this page'; + toc.insertBefore(title, toc.firstChild); + } +}); \ No newline at end of file diff --git a/docs/src/pages/index.js b/docs/src/pages/index.js new file mode 100644 index 000000000..4984dd58c --- /dev/null +++ b/docs/src/pages/index.js @@ -0,0 +1,144 @@ +import React from "react"; +import Dropdown from "@site/src/components/Elements/dropdown"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; + +import useBaseUrl from "@docusaurus/useBaseUrl"; +import Layout from "@theme/Layout"; +import AnnoncementBanner from "@site/src/components/Announcement"; +import { + CloudArrowUpIcon, + CursorArrowRaysIcon, + ShieldCheckIcon, + CpuChipIcon, + ClipboardDocumentIcon, + CubeTransparentIcon, + ComputerDesktopIcon, + FolderPlusIcon, +} from "@heroicons/react/24/outline"; + +import ThemedImage from "@theme/ThemedImage"; + +const features = [ + { + name: "Personal AI that runs on your computer", + desc: "Jan runs directly on your local machine, offering privacy, convenience and customizability.", + icon: ComputerDesktopIcon, + }, + { + name: "Private and offline, your data never leaves your machine", + desc: "Your conversations and data are with an AI that runs on your computer, where only you have access.", + icon: ShieldCheckIcon, + }, + { + name: "No subscription fees, the AI runs on your computer", + desc: "Say goodbye to monthly subscriptions or usage-based APIs. Jan runs 100% free on your own hardware.", + icon: CubeTransparentIcon, + }, + { + name: "Extendable via App and Plugin framework", + desc: "Jan has a versatile app and plugin framework, allowing you to customize it to your needs.", + icon: FolderPlusIcon, + }, +]; + +export default function Home() { + const { siteConfig } = useDocusaurusContext(); + return ( + <> + + +
+
+ +
+
+
+ {/* TODO: Add upcoming events here */} + {/* */} + +

+ Nitro +

+

+ Make deployment of AI models easier than ever before +

+ +
+ + +
+
+ +
+ {/*
*/} +
+ +
+
+
+
+
+ +
+

AI that you control

+

+ Nitro is a ... +

+
+ {features.map((feat, i) => { + return ( +
+
+ ); + })} +
+
+
+
+ + ); +} diff --git a/docs/src/styles/base.scss b/docs/src/styles/base.scss new file mode 100644 index 000000000..fb6388922 --- /dev/null +++ b/docs/src/styles/base.scss @@ -0,0 +1,45 @@ +@layer base { + html { + @apply scroll-smooth; + } + html[data-theme="light"] { + --ifm-background-color: white; + --ifm-color-primary: #2563eb; /* New Primary Blue */ + --ifm-color-primary-dark: #204fcf; /* Darker Blue */ + --ifm-color-primary-darker: #1b45b7; /* Even Darker Blue */ + --ifm-color-primary-darkest: #163c9d; /* Darkest Blue */ + --ifm-color-primary-light: #2974ff; /* Light Blue */ + --ifm-color-primary-lighter: #3280ff; /* Lighter Blue */ + --ifm-color-primary-lightest: #3a8bff; /* Lightest Blue */ + --ifm-code-font-size: 95%; + --ifm-navbar-link-hover-color: inherit; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + } + html[data-theme="dark"] { + --ifm-background-color: black; + --ifm-color-primary: #ffffff; /* New Primary Blue */ + --ifm-color-primary-dark: #204fcf; /* Darker Blue */ + --ifm-color-primary-darker: #1b45b7; /* Even Darker Blue */ + --ifm-color-primary-darkest: #163c9d; /* Darkest Blue */ + --ifm-color-primary-light: #2974ff; /* Light Blue */ + --ifm-color-primary-lighter: #3280ff; /* Lighter Blue */ + --ifm-color-primary-lightest: #3a8bff; /* Lightest Blue */ + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + } + body { + @apply text-sm; + @apply antialiased; + @apply bg-white dark:bg-black; + @apply text-gray-700 dark:text-gray-400; + } + img { + pointer-events: none; + } + + a { + &:hover { + color: inherit; + text-decoration: none; + } + } +} diff --git a/docs/src/styles/components.scss b/docs/src/styles/components.scss new file mode 100644 index 000000000..3583c258c --- /dev/null +++ b/docs/src/styles/components.scss @@ -0,0 +1,18 @@ +@layer components { + .el-blur-hero { + height: 200px; + background: linear-gradient( + 180deg, + hsl(296, 100%, 67%) 0%, + hsl(253, 100%, 57%) 100% + ); + z-index: 2; + border-bottom-left-radius: 100%; + border-bottom-right-radius: 100%; + border-top-left-radius: 100%; + border-top-right-radius: 100%; + filter: blur(100px); + -webkit-filter: blur(100px); + opacity: 0.5; + } +} diff --git a/docs/src/styles/main.scss b/docs/src/styles/main.scss new file mode 100644 index 000000000..ea6e4f723 --- /dev/null +++ b/docs/src/styles/main.scss @@ -0,0 +1,8 @@ +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; + +@import "./typography.scss"; +@import "./tweaks.scss"; +@import "./base.scss"; +@import "./components.scss"; diff --git a/docs/src/styles/tweaks.scss b/docs/src/styles/tweaks.scss new file mode 100644 index 000000000..14ec842a9 --- /dev/null +++ b/docs/src/styles/tweaks.scss @@ -0,0 +1,100 @@ +.redocusaurus { + div[data-section-id] { + min-height: auto; + } +} + +[class*="docItemCol_"] { + @apply p-4 lg:px-16 lg:py-4; +} + +[class*="breadcrumbsContainer_"] { + margin-bottom: 40px !important; +} + +.theme-doc-footer { + margin-top: 40px; + margin-bottom: 20px; +} + +.menu.thin-scrollbar { + padding: 32px 10px; +} + +[class*="iconExternalLink_"] { + display: none; +} + +.navbar { + @apply px-0 lg:h-16 border-b border-gray-200 dark:border-gray-800 bg-white/50 backdrop-blur-lg dark:bg-black/50 shadow-none; + + .navbar__toggle { + width: 24px; + } + + .navbar-sidebar__backdrop { + height: 100dvh; + } + + .navbar-sidebar { + height: 100dvh; + .navbar-sidebar__close { + width: 14px; + } + } + + .navbar__title { + @apply text-lg; + } + .navbar__brand { + margin-right: 24px; + &:hover { + color: inherit; + } + } + .navbar__inner { + @apply container; + } +} + +.breadcrumbs__item { + position: relative; + &:first-child { + .breadcrumbs__link { + vertical-align: middle; + margin-top: -2px; + } + } +} + +[class*="docMainContainer_"], +[class*="docSidebarContainer_"] { + @apply bg-gray-50 dark:bg-gray-950/95; +} + +.navbar-sidebar { + @apply bg-gray-50 dark:bg-gray-900; +} + +.theme-doc-sidebar-container { + @apply border-gray-200 dark:border-gray-800; +} + +.theme-doc-markdown { + a { + @apply text-blue-600 dark:text-blue-400; + } + ul { + list-style: revert; + } + ol { + list-style: decimal; + } + ul, + ol { + padding-left: 16px; + li { + @apply leading-loose; + } + } +} diff --git a/docs/src/styles/typography.scss b/docs/src/styles/typography.scss new file mode 100644 index 000000000..42953ac2b --- /dev/null +++ b/docs/src/styles/typography.scss @@ -0,0 +1,42 @@ +h1, +.h1 { + line-height: 48px; + font-size: 40px; + @apply font-bold text-black dark:text-white; +} +h2, +.h2 { + font-size: 32px; + @apply font-bold text-black dark:text-white; + line-height: 40px; +} +h3, +.h3 { + font-size: 28px; + @apply font-bold text-black dark:text-white; + line-height: 40px; +} +h4, +.h4 { + font-size: 24px; + @apply font-bold text-black dark:text-white; + line-height: 32px; +} +h5, +.h5 { + font-size: 20px; + @apply font-bold text-black dark:text-white; + line-height: 28px; +} +h6, +.h6 { + font-size: 16px; + @apply font-bold text-black dark:text-white; + line-height: 24px; +} +p { + line-height: 24px; +} +.paragraph { + line-height: 24px; +} diff --git a/docs/src/theme/Layout/Provider/index.js b/docs/src/theme/Layout/Provider/index.js new file mode 100644 index 000000000..1940672e2 --- /dev/null +++ b/docs/src/theme/Layout/Provider/index.js @@ -0,0 +1,21 @@ +import React from "react"; +import { composeProviders } from "@docusaurus/theme-common"; +import { + ColorModeProvider, + AnnouncementBarProvider, + DocsPreferredVersionContextProvider, + ScrollControllerProvider, + NavbarProvider, + PluginHtmlClassNameProvider, +} from "@docusaurus/theme-common/internal"; +const Provider = composeProviders([ + ColorModeProvider, + AnnouncementBarProvider, + ScrollControllerProvider, + DocsPreferredVersionContextProvider, + PluginHtmlClassNameProvider, + NavbarProvider, +]); +export default function LayoutProvider({ children }) { + return {children}; +} diff --git a/docs/src/theme/Layout/index.js b/docs/src/theme/Layout/index.js new file mode 100644 index 000000000..22c4cc131 --- /dev/null +++ b/docs/src/theme/Layout/index.js @@ -0,0 +1,53 @@ +import React from "react"; +import clsx from "clsx"; +import ErrorBoundary from "@docusaurus/ErrorBoundary"; +import { + PageMetadata, + SkipToContentFallbackId, + ThemeClassNames, +} from "@docusaurus/theme-common"; +import { useKeyboardNavigation } from "@docusaurus/theme-common/internal"; +import SkipToContent from "@theme/SkipToContent"; +import AnnouncementBar from "@theme/AnnouncementBar"; +import Navbar from "@theme/Navbar"; +import Footer from "@site/src/components/Footer"; +import LayoutProvider from "@theme/Layout/Provider"; +import ErrorPageContent from "@theme/ErrorPageContent"; +import styles from "./styles.module.scss"; +export default function Layout(props) { + const { + children, + noFooter, + wrapperClassName, + // Not really layout-related, but kept for convenience/retro-compatibility + title, + description, + } = props; + useKeyboardNavigation(); + return ( + + + + + + + + + +
+ }> + {children} + +
+ + {!noFooter &&