diff --git a/.gitignore b/.gitignore index b2d6de3..ed3fe72 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +.vercel diff --git a/README.md b/README.md index c8310a8..0c6c2c2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,41 @@ -# Documentation -Complete documentation about MetaCall infrastructure. +# Website -https://metacall.github.io/doc/ +This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. +### Installation -# TODO: Explain how to add new doc and build the project etc. +``` +$ 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. diff --git a/docs/getting-started.md b/docs/getting-started.md index d0cf6df..1bf96fa 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,7 +2,7 @@ sidebar_position: 1 --- -# Getting Started with Metacall +# Getting Started with MetaCall **Metacall** is a **polyglot** tool that allows calling *functions*, *methods*, *procedures* between different programming languages. diff --git a/docs/how-metacall-works.md b/docs/how-metacall-works.md index c8450bb..de1408f 100644 --- a/docs/how-metacall-works.md +++ b/docs/how-metacall-works.md @@ -2,7 +2,7 @@ sidebar_position: 2 --- -# How Metacall works +# How MetaCall works `Metacall` is a runtime that allows you to seamlessly connect and interoperate between multiple programming languages. It acts as a bridge, enabling you to call functions from one language in another without worrying about compatibility issues. diff --git a/docs/installating-metacall-cli/Docker.md b/docs/installating-metacall-cli/Docker.md index d7bc32c..3217593 100644 --- a/docs/installating-metacall-cli/Docker.md +++ b/docs/installating-metacall-cli/Docker.md @@ -1,5 +1,8 @@ --- sidebar_position: 4 +tags: + - machine-learning + - python --- Guide to install Metacall CLI on Docker. diff --git a/docs/installating-metacall-cli/Windows.md b/docs/installating-metacall-cli/Windows.md index d15655b..7850c52 100644 --- a/docs/installating-metacall-cli/Windows.md +++ b/docs/installating-metacall-cli/Windows.md @@ -2,4 +2,40 @@ sidebar_position: 3 --- -Guide to install Metacall CLI on Windows. \ No newline at end of file +Guide to install Metacall CLI on Windows. + +MetaCall is a powerful CLI tool that lets you run functions across different programming languages seamlessly. Follow these simple steps to install it on Linux. + +### Step 1 : Open Terminal ### + +Open the `Terminal` app on your Linux system. You can usually find it in your applications menu or by pressing `Ctrl + Alt + T`. + +### Step 2 : Run the Install Command ### + +Copy and paste the following command into your Terminal to install MetaCall CLI: + +``` + powershell -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://raw.githubusercontent.com/metacall/install/master/install.ps1')))" +``` + +### Step 3 : Verify Installation ### + +Once the installation is complete, verify it by running the `metacall` command: + +``` + metacall +``` + +If the installation was successful, you’ll see the following message: + +import WinInstall from "/static/img/win-install.png"; + + +
+To exit the MetaCall CLI, type `exit` in the Metacall CLI: + +import WinExit from '/static/img/win-un.png'; + + +
+You’re all set! Now you can start using MetaCall to run functions across multiple programming languages. 🚀 \ No newline at end of file diff --git a/docs/tutorials/Climatic.md b/docs/tutorials/Climatic.md new file mode 100644 index 0000000..e5c2e5e --- /dev/null +++ b/docs/tutorials/Climatic.md @@ -0,0 +1,608 @@ +--- +sidebar_position: 4 +tags: + + - python + - node.js + - vue.js + - machine-learning +--- +import StarRepo from '@site/src/components/StarRepo.js'; + + + +## Building a Polyglot Weather Dashboard with MetaCall +In this tutorial, you will learn how to build a **weather dashboard** by integrating **Node.js** for API handling and **Python** for weather analytics. This project demonstrates how to leverage multiple programming languages in a seamless manner using **MetaCall**. +## Tutorial Overview + +In this tutorial, you'll learn how to create a weather dashboard by integrating Node.js and Python using MetaCall. You will cover: + +- Installing MetaCall. +- Writing Python functions for weather analytics. +- Calling Python functions from a Node.js backend. +- Deploying the solution to the cloud for real-time weather data processing. + + + + +## Installing MetaCall +MetaCall enables the execution of functions from different programming languages in a single project. Before proceeding, ensure that **MetaCall** is installed. Follow the [MetaCall's installation guide](/docs/category/installating-metacall-cli). to set it up. + +### What We Are Building? + + +#### A **Weather dashboard** that combines different programming languages to provide weather insights. Here's how it works: + +- **Node.js Backend:** Handles API requests and serves data. +- **Python Analytics Module:** Performs data analysis using libraries like `pandas` and `NumPy`. +- **MetaCall Integration:** Executes Python functions inside the Node.js backend. +- **Vue.js Frontend (Optional):** Displays weather data in a user-friendly UI. + +### **Why Use Python in a Node.js Project?** +While JavaScript excels at handling API requests, Python offers advanced data processing libraries that are essential for weather analytics. By using MetaCall, you can integrate the best of both worlds: **Node.js** for API handling and **Python** for analytics. + +--- + +## Installing Project Dependencies +Before writing any code, let's install the necessary libraries. + + +### **Step 1: Install Node.js Dependencies** +Run the following command in your project folder: + +```sh +npm install express axios +``` + +### **Step 2: Install Python Dependencies** +For weather data analysis,u should download This File +[Requirements](https://github.com/metacall/weather-dashboard-example/blob/main/backend/requirements.txt) + + Run the following command in your project folder: + +```sh +metacall pip install -r requirements.txt +``` + +Now, we are ready to write some code! 🚀 + +--- + +## 📝 4. Writing the Python Weather Analysis Script +We'll write a simple Python Script to **analyze weather data** using `Python`. + focusing on weather analysis , trends and predictions . The implementation includes functions to summarize the weather, detect temperature trends, and predict future temperatures using machine learning techniques and give an analysis of the current weather. +## Functions Overview +This tutorial consists of three main functions: +1. `get_weather_summary(weather_data, predicted_temp_next_day)`: Generates a summary of today’s weather and tomorrow’s predicted temperature. +2. `detect_trend(temps)`: Detects whether the temperature is increasing, decreasing, or stable. +3. `get_weather_stats(weather_data)`: give an analysis of the current weather, predict temperature,detect temperature trends and provides a weather summary. + +### **Create a Python File (`weather_analysis.py`)** +```python +import statistics +import numpy as np +from sklearn.preprocessing import PolynomialFeatures +from sklearn.pipeline import make_pipeline +from sklearn.linear_model import LinearRegression +``` + +### 1. **Weather Analysis** +```python +def get_weather_stats(weather_data): + temps = [item["main"]["temp"] for item in weather_data["list"]] + avg_temp = round(statistics.mean(temps), 2) + + timestamps = np.arange(len(temps)).reshape(-1, 1) + + if len(temps) < 3: + return {"error": "Not enough data to predict", "language": "Python"} + + # Use Polynomial Regression + model = make_pipeline(PolynomialFeatures(degree=2), LinearRegression()) + model.fit(timestamps, temps) + + # Predict next day's temperature + next_time_index = np.array([[len(temps)]]).reshape(-1, 1) + predicted_temp = round(model.predict(next_time_index)[0], 2) + trend = detect_trend(temps) + weather_summary = get_weather_summary(weather_data, predicted_temp) + + return { + "average_temperature": round(np.mean(temps), 2), + "max_temp": round(np.max(temps), 2), + "min_temp": round(np.min(temps), 2), + "predicted_temp_next_day": round(predicted_temp, 2), + "trend": trend, + "summary": weather_summary["summary"], + "average_temperature": avg_temp + } +``` + +### Explanation +- Extracts temperature data from `weather_data` from `OpenWeather`. +- Uses polynomial regression (degree 2) for improved trend analysis. +- Predicts the next day’s temperature. +- Calls `detect_trend` to determine the general trend. +- Returns a structured weather report with key statistics and avg temps. + + +--- +### 2. Detecting Temperature Trends +```python +def detect_trend(temps): + """Detect whether the temperature trend is increasing, decreasing, or stable.""" + trend = np.polyfit(range(len(temps)), temps, 1)[0] + if trend > 0: + return "increasing" + elif trend < 0: + return "decreasing" + return "stable" +``` + +### Explanation +- Uses `numpy.polyfit` to compute a linear trend line. +- Determines whether the overall trend is increasing, decreasing, or stable. + +--- +### 3. Generating a Weather Summary +```python +def get_weather_summary(weather_data, predicted_temp_next_day): + """Generate a summary of today's weather and tomorrow's predicted temperature.""" + temps = [item["main"]["temp"] for item in weather_data["list"]] + + if len(temps) < 16: + return {"error": "Not enough data to predict", "language": "Python"} + + today_temps = temps[:8] + max_temp_today = int(round(max(today_temps))) + min_temp_today = int(round(min(today_temps))) + predicted_temp = int(round(predicted_temp_next_day)) + + # Identify temperature trend + is_steadily_increasing = all(today_temps[i] < today_temps[i + 1] for i in range(len(today_temps) - 1)) + is_steadily_decreasing = all(today_temps[i] > today_temps[i + 1] for i in range(len(today_temps) - 1)) + + if is_steadily_increasing: + summary = f"Weather Today: Temperatures will gradually rise, peaking at {max_temp_today}°C." + elif is_steadily_decreasing: + summary = f"Weather Today: Temperatures will gradually drop, reaching a low of {min_temp_today}°C." + else: + summary = f"Weather Today will be warmer with a high of {max_temp_today}°C and a low of {min_temp_today}°C." + + # Add tomorrow's prediction + summary += f" Tomorrow, the expected temperature will be around {predicted_temp}°C." + + return { + "summary": summary, + "max_temp_today": max_temp_today, + "min_temp_today": min_temp_today, + "predicted_temp_next_day": predicted_temp + } +``` + +### Explanation +- Extracts temperature data from `weather_data`. +- Identifies whether the temperature is increasing, decreasing, or normal. +- Constructs a human-readable summary of the day's weather and tomorrow's forecast. + +--- +## Example Usage +To use these functions, provide weather data in the following format: +```python +weather_data = { + "list": [ + {"main": {"temp": 15.0}}, + {"main": {"temp": 16.5}}, + {"main": {"temp": 18.0}}, + {"main": {"temp": 19.5}}, + {"main": {"temp": 20.0}}, + ] +} + +print(get_weather_stats(weather_data)) +``` + +### Sample Output +```json +{ + "average_temperature": 17.8, + "max_temp": 20.0, + "min_temp": 15.0, + "predicted_temp_next_day": 21.5, + "trend": "increasing", + "summary": "Weather Today: Temperatures will gradually rise, peaking at 20°C. Tomorrow, the expected temperature will be around 21.5°C." +} +``` +:::tip 🎉🎉 +Now, We Created The Weather Analysis Functions We Can Move To The Node.Js Part ,Congrats! +::: +## 🌦️ Connecting to a Live Weather API (OpenWeatherMap) +Instead of using static data, let’s fetch real-time weather data from **OpenWeatherMap**. + +### **Get an API Key** +1. Sign up at [OpenWeatherMap](https://openweathermap.org/). +2. Get your **API key** from the dashboard. +:::tip Info +Now, We Can Use This In Our `Main.js` File! +::: + +## 🔗 5. Calling Python Code from Node.js using MetaCall +Now, let’s integrate our Python function into a Node.js Code! + +### **Create a (`main.js`) File** +```javascript +const express = require('express'); +const axios = require('axios') +const { metacall } = require("metacall"); +const app = express(); +const PORT = process.env.PORT || 5000; +app.use(express.json()); +app.get('/', (req, res) => { + res.send('Hello, World!'); +}); + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); + +``` + +```javascript +const WEATHER_API_KEY = process.env.WEATHER_API_KEY; +const FORECAST_API_URL = "https://api.openweathermap.org/data/2.5/forecast"; +app.post("/analyze-weather", async (req, res) => { + try { + const { city } = req.body; + if (!city) return res.status(400).json({ error: "City is required" }); + + // Fetch Forecast Data from OpenWeatherMap + const response = await axios.get(`${FORECAST_API_URL}?q=${city}&appid=${WEATHER_API_KEY}&units=metric`); + const weatherData = response.data; + + // Call Python Function via MetaCall + const analytics = await metacall("get_weather_stats", weatherData); + + const forecast = weatherData.list.slice(0, 5).map(item => ({ + date: new Date(item.dt * 1000).toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }), + time: new Date(item.dt * 1000).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: true }), + temperature: item.main.temp, + description: item.weather[0].description, + icon: `https://openweathermap.org/img/wn/${item.weather[0].icon}@2x.png` + })); + + res.json({ + forecast, + city, + analytics: { + average_temperature: Math.floor(analytics.average_temperature), + max_temp: Math.floor(analytics.max_temp), + min_temp: Math.floor(analytics.min_temp), + predicted_temp_next_day: Math.floor(analytics.predicted_temp_next_day), + trend: analytics.trend, + condition: analytics.condition, + forechart: analytics.forecast_chart, + summary: analytics.summary + }, + language: analytics.language + }); + } catch (error) { + res.status(500).json({ error: "Failed to fetch weather data" }); + } +}); +``` + + +## How This Works +1. The user sends a `POST` request with the `city` name. +2. The API fetches weather data from OpenWeatherMap. +3. The fetched data is passed to a Python function via MetaCall. +4. The Python function analyzes the weather data and returns statistics. +5. The API formats the results and sends them back in JSON response. + +## Usage +Send a POST request to the API endpoint: +```sh +curl -X POST http://localhost:5000/analyze-weather -H "Content-Type: application/json" -d '{"city": "London"}' +``` +### We can Also Get AirQuality Data +```javascript +app.post("/air-quality", async (req, res) => { + const cityName = req.body.city; + + if (!cityName) { + return res.status(400).json({ error: 'City name is required' }); + } + + try { + // Step 1: Get city coordinates + const geoUrl = `https://api.openweathermap.org/geo/1.0/direct?q=${encodeURIComponent(cityName)}&limit=1&appid=${WEATHER_API_KEY}`; + const geoResponse = await axios.get(geoUrl); + const geoData = geoResponse.data; + + if (geoData.length === 0) { // Check if array is empty + return res.status(404).json({ error: 'City not found' }); + } + + // Extract coordinates from first result + const { lat, lon } = geoData[0]; + + // Step 2: Get air quality data + const airQualityUrl = `https://api.openweathermap.org/data/2.5/air_pollution?lat=${lat}&lon=${lon}&appid=${WEATHER_API_KEY}`; + const airQualityResponse = await axios.get(airQualityUrl); + const airQualityData = airQualityResponse.data; + + if (!airQualityData.list?.length) { + return res.status(500).json({ error: 'Failed to fetch air quality data' }); + } + + // Step 3: Return results + return res.json({ + city: cityName, + aqi: airQualityData.list[0].main.aqi, + airQualityData: airQualityData.list[0].components, + }); + + } catch (error) { + console.error('Error fetching data:', error); + return res.status(500).json({ error: 'Internal server error' }); + } +}); + +``` +## How This Works +1. The user sends a `POST` request with the `city` name. +2. The API fetches the city's coordinates from OpenWeatherMap using the geo-location API +3. The API then fetches air quality data based on the coordinates. +4. The fetched air quality data is returned in the response. + +## Usage +Send a POST request to the API endpoint: +```sh +curl -X POST http://localhost:3000/air-quality -H "Content-Type: application/json" -d '{"city": "London"}' +``` +:::info Info +Congrats! You created the main functions for the weather app. +You can see the full functions implementation [here](https://github.com/metacall/weather-dashboard-example). + +::: +--- + +## 🛠️ 7. Testing MetaCall FaaS Locally +Before deploying, let’s ensure our function works with MetaCall locally. + +Run the following command: + +```sh +metacall main.js +``` + +This verifies that MetaCall can execute our function without errors. + +--- + +## ☁️ 8. Deploying to MetaCall FaaS (Serverless Deployment) +Now, let's deploy our Python function to the **MetaCall Cloud** so it can be used anywhere! + +### **Step 1: Log in to MetaCall Cloud** +Go to [MetaCall Dashboard](https://dashboard.metacall.io) and log in or sign up. + +### **Step 2: Upload Your Python Script** +1. Navigate to the **Deployments** section. +2. Click **Upload Function** and select `weather_analysis.py`. + +### **Step 3: Get Your API Endpoint** +- MetaCall will generate a **public API URL** for your function. +- Copy this URL to use it in your Node.js backend. + +### **Step 4: Modify `main.js` to Use the Cloud API** +Replace the local MetaCall call with an HTTP request to your cloud function: +inside the weather/analyze +- from: +```javascript + const analytics = await metacall("get_weather_stats", weatherData); +``` +- to: +```javascript + const analytics = await axios.post('YOUR_METACALL_API_URL', { args: [weatherData] }); +``` + +### **Step 5: Run Your Backend Again** +```sh +metacall main.js +``` + +Now, your **Node.js backend is using the metacall Faas Function**! 🚀 + +--- +## Additional Steps +### Display Weather Data Inside Frontend with Vue.js +Now let's create the frontend with Vue.js to display the weather data in a user-friendly interface. +### Step 1: Create a Vue.js App +If you don’t have Vue CLI installed, you can install it with the following: +```sh +npm install -g @vue/cli +``` +Create a new Vue project: +```sh +vue create [projectname] +``` +Once the project is created, navigate to the project folder: +```sh +cd [projectname] +``` +### Step 2: Install Axios in Vue +Install Axios to make HTTP requests to the Node.js backend: +```sh +npm install axios +``` +### Step 3: Modify App.vue +add the following template content: +```html + + +``` +:::info info +Next, add the script to handle the logic and data fetching +::: +```js + +``` +### Styling(Optional) +For styling, you can add your custom styles inside the ` +``` +:::tip +This will style your weather dashboard. Customize it according to your preferences. +::: +--- +## Conclusion +Congratulations! 🎉 You’ve built a polyglot weather dashboard using Node.js, Python, and MetaCall for seamless cross-language execution. You learned how to: + +- Integrate **Node.js** with **Python** for weather analytics. +- Use **MetaCall** to run Python code within the Node.js backend. +- Fetch and process live weather data from an external API. +- Deploying to **MetaCall** FaaS (Serverless Deployment) +- Display weather predictions and analysis with Python’s data-processing capabilities. + +## Next Steps +Now that you've completed the core functionality, you can further enhance your weather dashboard by: + +- Adding more sophisticated weather analysis and forecasting models in Python. +- Enhancing the UI with **Vue.js** for real-time data updates. +- Deploying your project to the cloud to make it accessible anywhere. +- Experimenting with other data sources and incorporating machine learning models for more accurate predictions. + +## Get Involved +If you're interested in contributing to this project or exploring more about polyglot programming with MetaCall, feel free to check out the official **[MetaCall documentation](https://metacall.io/docs)** and **[GitHub repository](https://github.com/metacall)**. + +### See the Full Implementation +To explore the complete code and structure of this project, check out the full implementation on GitHub: +**[Weather Dashboard Project on GitHub](https://github.com/metacall/weather-dashboard-example)** + +### Share Your Work +Once you've customized the tutorial or added your own enhancements, share your project with the community! You can create a pull request or link to your repository in the comments. + +We hope this tutorial helped you understand how to seamlessly integrate Python and Node.js using MetaCall. Happy coding! 🚀 +### Don't forget to star the repo and share your experience! 😃 +--- diff --git a/docs/tutorials/_category_.json b/docs/tutorials/_category_.json new file mode 100644 index 0000000..af35b5b --- /dev/null +++ b/docs/tutorials/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Tutorials", + "position": 5, + "link": { + "type": "generated-index", + "description": "Tutorials For Metacall" + } +} diff --git a/docs/understanding-metacall-cli.md b/docs/understanding-metacall-cli.md index 520eb87..c7d6867 100644 --- a/docs/understanding-metacall-cli.md +++ b/docs/understanding-metacall-cli.md @@ -2,7 +2,7 @@ sidebar_position: 3 --- -# Understanding Metacall CLI +# Understanding MetaCall CLI This document will guide you through the basic commands of MetaCall CLI, explaining each one with simple examples to help you get started. diff --git a/docusaurus.config.js b/docusaurus.config.js index e215914..dd1e0d3 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -4,34 +4,31 @@ // There are various equivalent ways to declare your Docusaurus config. // See: https://docusaurus.io/docs/api/docusaurus-config -import { themes as prismThemes } from 'prism-react-renderer'; - -// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) +import { themes as prismThemes } from "prism-react-renderer"; +const { themes } = require("prism-react-renderer"); /** @type {import('@docusaurus/types').Config} */ const config = { - title: 'Metacall Tutorial', + title: 'MetaCall', tagline: 'Documentation for MetaCall', favicon: 'img/metacall-logo.png', + organizationName: "MetaCall", // Set the production url of your site here - url: 'https://github.com', + url: 'https://docs-ptc.netlify.app', // Set the // pathname under which your site is served // For GitHub pages deployment, it is often '//' - baseUrl: '/doc/', + baseUrl: '/', + - // GitHub pages deployment config. - // If you aren't using GitHub pages, you don't need these. - organizationName: 'metacall', // Usually your GitHub org/user name. - projectName: 'doc', // Usually your repo name. - deploymentBranch: 'gh-pages', + projectName: 'MetaCall', // Usually your repo name. - onBrokenLinks: 'ignore', + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', // Even if you don't use internationalization, 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'. + // may want to replace "en" with "zh-Hans". i18n: { defaultLocale: 'en', locales: ['en'], @@ -44,6 +41,12 @@ const config = { ({ docs: { sidebarPath: './sidebars.js', + + + tagsBasePath: "tags", + breadcrumbs: true, + + }, theme: { customCss: './src/css/custom.css', @@ -51,10 +54,12 @@ const config = { }), ], ], - + + themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + customCss: './src/css/custom.css', // Correct placement for customCss // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', navbar: { @@ -70,6 +75,16 @@ const config = { position: 'left', label: 'Documentation', }, + { + label: "Install", + href: "/docs/category/installating-metacall-cli", + position: "left", + }, + { + label: "Tutorials", + href: "/docs/category/tutorials", + position: "left", + }, { href: 'https://github.com/metacall', label: 'GitHub', @@ -77,50 +92,71 @@ const config = { }, ], }, + footer: { - style: 'dark', + style: "dark", links: [ { - title: 'Docs', + title: "Intro", items: [ { - label: 'Documentation', - to: '/docs/category/introduction', + label: "Getting Started", + to: "/docs/getting-started", + }, + { + label: "Install", + to: "/docs/category/installating-metacall-cli", }, + ], }, { - title: 'Community', + title: "Use MetaCall", items: [ { - label: 'Stack Overflow', - href: 'https://stackoverflow.com/questions/tagged/docusaurus', + label: "Configuration", + to: "/docs/running-bracket/configuration", }, { - label: 'Discord', - href: 'https://discordapp.com/invite/docusaurus', + label: "Deployment", + to: "/docs/deployment", }, + ], + }, + { + title: "Community", + items: [ { - label: 'X', - href: 'https://x.com/docusaurus', + label: "Examples", + to: "/docs/community/contributing", + }, + { + label: "Developing", + to: "/docs/community/development", }, ], }, { - title: 'More', + title: "More", items: [ { - label: 'GitHub', - href: 'https://github.com/facebook/docusaurus', + label: "GitHub", + href: "https://github.com/metacall/", + }, + + { + label: "Changelog", + href: "https://github.com/metacall/core/releases", }, ], }, ], - copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`, + copyright: `Copyright © ${new Date().getFullYear()} MetaCall. All Rights Reserved.`, }, prism: { - theme: prismThemes.github, - darkTheme: prismThemes.dracula, + theme: prismThemes.vsDark, + darkTheme: prismThemes.vsDark, + }, }), }; diff --git a/package-lock.json b/package-lock.json index 86f212d..3cf8745 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,17 @@ "dependencies": { "@docusaurus/core": "3.7.0", "@docusaurus/preset-classic": "3.7.0", + "@docusaurus/theme-search-algolia": "^3.7.0", + "@mantine/carousel": "^7.17.0", + "@mantine/core": "^7.17.0", "@mdx-js/react": "^3.0.0", + "@tabler/icons-react": "^3.30.0", "clsx": "^2.0.0", + "metacall": "^0.4.3", "prism-react-renderer": "^2.3.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "react-icons": "^5.5.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.7.0", @@ -3616,7 +3622,6 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.7.0.tgz", "integrity": "sha512-Al/j5OdzwRU1m3falm+sYy9AaB93S1XF1Lgk9Yc6amp80dNxJVplQdQTR4cYdzkGtuQqbzUA8+kaoYYO0RbK6g==", - "license": "MIT", "dependencies": { "@docsearch/react": "^3.8.1", "@docusaurus/core": "3.7.0", @@ -3786,6 +3791,54 @@ "node": ">=18.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3907,6 +3960,56 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "license": "MIT" }, + "node_modules/@mantine/carousel": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mantine/carousel/-/carousel-7.17.0.tgz", + "integrity": "sha512-NrgfUBa7tbtDFem6TAntZjQknymqhzZ/d52szheRu+3GIfd9d8qEPHV1sMFRQ3DkzMxiJfzI6G61GvW6yLOaGg==", + "peerDependencies": { + "@mantine/core": "7.17.0", + "@mantine/hooks": "7.17.0", + "embla-carousel-react": ">=7.0.0", + "react": "^18.x || ^19.x", + "react-dom": "^18.x || ^19.x" + } + }, + "node_modules/@mantine/core": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.0.tgz", + "integrity": "sha512-AU5UFewUNzBCUXIq5Jk6q402TEri7atZW61qHW6P0GufJ2W/JxGHRvgmHOVHTVIcuWQRCt9SBSqZoZ/vHs9LhA==", + "dependencies": { + "@floating-ui/react": "^0.26.28", + "clsx": "^2.1.1", + "react-number-format": "^5.4.3", + "react-remove-scroll": "^2.6.2", + "react-textarea-autosize": "8.5.6", + "type-fest": "^4.27.0" + }, + "peerDependencies": { + "@mantine/hooks": "7.17.0", + "react": "^18.x || ^19.x", + "react-dom": "^18.x || ^19.x" + } + }, + "node_modules/@mantine/core/node_modules/type-fest": { + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.35.0.tgz", + "integrity": "sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mantine/hooks": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.0.tgz", + "integrity": "sha512-vo3K49mLy1nJ8LQNb5KDbJgnX0xwt3Y8JOF3ythjB5LEFMptdLSSgulu64zj+QHtzvffFCsMb05DbTLLpVP/JQ==", + "peer": true, + "peerDependencies": { + "react": "^18.x || ^19.x" + } + }, "node_modules/@mdx-js/mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", @@ -4361,6 +4464,30 @@ "node": ">=14.16" } }, + "node_modules/@tabler/icons": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.30.0.tgz", + "integrity": "sha512-c8OKLM48l00u9TFbh2qhSODMONIzML8ajtCyq95rW8vzkWcBrKRPM61tdkThz2j4kd5u17srPGIjqdeRUZdfdw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-react": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.30.0.tgz", + "integrity": "sha512-9KZ9D1UNAyjlLkkYp2HBPHdf6lAJ2aelDqh8YYAnnmLF3xwprWKxxW8+zw5jlI0IwdfN4XFFuzqePkaw+DpIOg==", + "dependencies": { + "@tabler/icons": "3.30.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "react": ">= 16" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -7011,6 +7138,11 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "license": "MIT" }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, "node_modules/detect-port": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", @@ -7233,6 +7365,34 @@ "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", "license": "ISC" }, + "node_modules/embla-carousel": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.2.tgz", + "integrity": "sha512-xQ9oVLrun/eCG/7ru3R+I5bJ7shsD8fFwLEY7yPe27/+fDHCNj0OT5EoG5ZbFyOxOcG6yTwW8oTz/dWyFnyGpg==", + "peer": true + }, + "node_modules/embla-carousel-react": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.5.2.tgz", + "integrity": "sha512-Tmx+uY3MqseIGdwp0ScyUuxpBgx5jX1f7od4Cm5mDwg/dptEiTKf9xp6tw0lZN2VA9JbnVMl/aikmbc53c6QFA==", + "peer": true, + "dependencies": { + "embla-carousel": "8.5.2", + "embla-carousel-reactive-utils": "8.5.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.5.2.tgz", + "integrity": "sha512-QC8/hYSK/pEmqEdU1IO5O+XNc/Ptmmq7uCB44vKplgLKhB/l0+yvYx0+Cv0sF6Ena8Srld5vUErZkT+yTahtDg==", + "peer": true, + "peerDependencies": { + "embla-carousel": "8.5.2" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -8316,6 +8476,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-own-enumerable-property-symbols": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", @@ -10455,6 +10623,11 @@ "node": ">= 8" } }, + "node_modules/metacall": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/metacall/-/metacall-0.4.3.tgz", + "integrity": "sha512-fU/8C43UItoTnBRp7xUHuoyR0PFFaCSNfStSjE3evxXtZedTu+d2tatXtFFTbRVRG2zSrLjwBeKJZMvTZ+1PoA==" + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -14980,6 +15153,14 @@ "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -15015,6 +15196,60 @@ "webpack": ">=4.41.1 || 5.x" } }, + "node_modules/react-number-format": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz", + "integrity": "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ==", + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", + "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", @@ -15066,6 +15301,43 @@ "react": ">=15" } }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.6.tgz", + "integrity": "sha512-aT3ioKXMa8f6zHYGebhbdMD2L00tKeRX1zuVuDx9YQK/JLLRSaSxq3ugECEmUB9z2kvk6bFSIoRHLkkUv0RJiw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -16613,6 +16885,11 @@ "node": ">= 10" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -17256,6 +17533,89 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", + "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 15a15b5..35767d5 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,17 @@ "dependencies": { "@docusaurus/core": "3.7.0", "@docusaurus/preset-classic": "3.7.0", + "@docusaurus/theme-search-algolia": "^3.7.0", + "@mantine/carousel": "^7.17.0", + "@mantine/core": "^7.17.0", "@mdx-js/react": "^3.0.0", + "@tabler/icons-react": "^3.30.0", "clsx": "^2.0.0", + "metacall": "^0.4.3", "prism-react-renderer": "^2.3.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "react-icons": "^5.5.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.7.0", diff --git a/src/components/HomepageFeatures/index.js b/src/components/HomepageFeatures/index.js index 93403b9..c8d3477 100644 --- a/src/components/HomepageFeatures/index.js +++ b/src/components/HomepageFeatures/index.js @@ -32,7 +32,7 @@ const FeatureList = [ Learn from existing tutorials on how to use MetaCall in different scenarios. ), - goto: '/docs/category/tutorial---basics/', + goto: '/docs/category/tutorials', }, ]; diff --git a/src/components/StarRepo.js b/src/components/StarRepo.js new file mode 100644 index 0000000..54f96f5 --- /dev/null +++ b/src/components/StarRepo.js @@ -0,0 +1,42 @@ +import React, { useState, useEffect } from 'react'; +import { FaStar, FaRegStar } from 'react-icons/fa'; + +const StarRepo = ({ itemId }) => { + const [isStarred, setIsStarred] = useState(false); + const [isBrowser, setIsBrowser] = useState(false); + + // Check if we're in the browser environment + useEffect(() => { + setIsBrowser(typeof window !== 'undefined'); + }, []); + + useEffect(() => { + if (isBrowser) { + const starredItems = JSON.parse(localStorage.getItem('starredItems') || '[]'); + setIsStarred(starredItems.includes(itemId)); + } + }, [itemId, isBrowser]); + + const toggleStar = () => { + if (!isBrowser) return; + + let starredItems = JSON.parse(localStorage.getItem('starredItems') || '[]'); + + if (isStarred) { + starredItems = starredItems.filter(item => item !== itemId); + } else { + starredItems.push(itemId); + } + + localStorage.setItem('starredItems', JSON.stringify(starredItems)); + setIsStarred(!isStarred); + }; + + return ( +
+ {isStarred ? : } +
+ ); +}; + +export default StarRepo; \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index 2bc6a4c..15ddb3b 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -6,25 +6,76 @@ /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #2e8555; - --ifm-color-primary-dark: #29784c; - --ifm-color-primary-darker: #277148; - --ifm-color-primary-darkest: #205d3b; - --ifm-color-primary-light: #33925d; - --ifm-color-primary-lighter: #359962; - --ifm-color-primary-lightest: #3cad6e; - --ifm-code-font-size: 95%; + + + --ifm-color-primary: #4019cc; + --ifm-color-primary-dark: #a08de5; + --ifm-color-primary-darker: #927de2; + --ifm-color-primary-darkest: #674ad6; + --ifm-color-primary-light: #d8d1f5; + --ifm-color-primary-lighter: #e6e1f8; + --ifm-color-primary-lightest: #ffffff; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + --mantine-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; + + } /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme='dark'] { - --ifm-color-primary: #25c2a0; - --ifm-color-primary-dark: #21af90; - --ifm-color-primary-darker: #1fa588; - --ifm-color-primary-darkest: #1a8870; - --ifm-color-primary-light: #29d5b0; - --ifm-color-primary-lighter: #32d8b4; - --ifm-color-primary-lightest: #4fddbf; + color: #c1c2c5; + --ifm-color-primary: #bcafed; + --ifm-color-primary-dark: #a08de5; + --ifm-color-primary-darker: #927de2; + --ifm-color-primary-darkest: #674ad6; + --ifm-color-primary-light: #d8d1f5; + background-color: #1a1b1e; + --ifm-color-primary-lighter: #e6e1f8; + .card { + background-color: var(--ifm-card-background-color); + border-radius: var(--ifm-card-border-radius); + box-shadow: var(--ifm-global-shadow-lw); + display: flex +; + flex-direction: column; + overflow: hidden;} + + --ifm-color-primary-lightest: #ffffff; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + +} +.footer { + background-color: #141517 ; } +body { + + word-wrap: break-word; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: var(--mantine-moz-font-smoothing); + + + font-family: var(--mantine-font-family); + line-height: 1.55; + margin: 0; +} + +custom-tags { + margin-bottom: 20px; /* Space between tags and title */ +} + +.custom-tags .tag { + display: inline-block; + margin-right: 10px; + padding: 5px 15px; + background-color: #007bff; + color: white; + border-radius: 20px; /* This makes the tag look like a pill */ + font-size: 14px; + font-weight: bold; + text-transform: capitalize; +} + +.custom-tags .tag:hover { + background-color: #0056b3; + cursor: pointer; +} \ No newline at end of file diff --git a/static/img/availability-svgrepo-com.svg b/static/img/availability-svgrepo-com.svg new file mode 100644 index 0000000..3df05f4 --- /dev/null +++ b/static/img/availability-svgrepo-com.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/bracket-screenshot-design.png b/static/img/bracket-screenshot-design.png new file mode 100644 index 0000000..466c478 Binary files /dev/null and b/static/img/bracket-screenshot-design.png differ diff --git a/static/img/builder_preview.png b/static/img/builder_preview.png new file mode 100644 index 0000000..2cfa55c Binary files /dev/null and b/static/img/builder_preview.png differ diff --git a/static/img/courts_preview.png b/static/img/courts_preview.png new file mode 100644 index 0000000..0e542c5 Binary files /dev/null and b/static/img/courts_preview.png differ diff --git a/static/img/host-record-svgrepo-com.svg b/static/img/host-record-svgrepo-com.svg new file mode 100644 index 0000000..beee0e2 --- /dev/null +++ b/static/img/host-record-svgrepo-com.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/interface-control-svgrepo-com.svg b/static/img/interface-control-svgrepo-com.svg new file mode 100644 index 0000000..e4c6126 --- /dev/null +++ b/static/img/interface-control-svgrepo-com.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/logo.svg b/static/img/logo.svg index 9db6d0d..df3dd20 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -1 +1,110 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/multiple-defenses-svgrepo-com.svg b/static/img/multiple-defenses-svgrepo-com.svg new file mode 100644 index 0000000..11a9020 --- /dev/null +++ b/static/img/multiple-defenses-svgrepo-com.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/planning_preview.png b/static/img/planning_preview.png new file mode 100644 index 0000000..ba0213a Binary files /dev/null and b/static/img/planning_preview.png differ diff --git a/static/img/planning_preview_old.png b/static/img/planning_preview_old.png new file mode 100644 index 0000000..444410c Binary files /dev/null and b/static/img/planning_preview_old.png differ diff --git a/static/img/players_preview.png b/static/img/players_preview.png new file mode 100644 index 0000000..643ca13 Binary files /dev/null and b/static/img/players_preview.png differ diff --git a/static/img/preview.png b/static/img/preview.png new file mode 100644 index 0000000..af47504 Binary files /dev/null and b/static/img/preview.png differ diff --git a/static/img/schedule_preview.png b/static/img/schedule_preview.png new file mode 100644 index 0000000..25708b1 Binary files /dev/null and b/static/img/schedule_preview.png differ diff --git a/static/img/standings_preview.png b/static/img/standings_preview.png new file mode 100644 index 0000000..dabaedc Binary files /dev/null and b/static/img/standings_preview.png differ diff --git a/static/img/system-settings-svgrepo-com.svg b/static/img/system-settings-svgrepo-com.svg new file mode 100644 index 0000000..df53d7b --- /dev/null +++ b/static/img/system-settings-svgrepo-com.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/win-install.png b/static/img/win-install.png new file mode 100644 index 0000000..d85dce0 Binary files /dev/null and b/static/img/win-install.png differ diff --git a/static/img/win-un.png b/static/img/win-un.png new file mode 100644 index 0000000..00a76f6 Binary files /dev/null and b/static/img/win-un.png differ