Full Code of cube-js/awesome-tools for AI

master dc042cb6759d cached
167 files
238.5 KB
78.3k tokens
70 symbols
1 requests
Download .txt
Showing preview only (274K chars total). Download the full file or copy to clipboard to get everything.
Repository: cube-js/awesome-tools
Branch: master
Commit: dc042cb6759d
Files: 167
Total size: 238.5 KB

Directory structure:
gitextract_elt7bwjc/

├── .github/
│   └── workflows/
│       └── scheduled-data-update.yml
├── .gitignore
├── .netlify/
│   └── state.json
├── .nvmrc
├── LICENSE
├── README.md
├── components/
│   ├── Button/
│   │   ├── Button.jsx
│   │   ├── Button.module.scss
│   │   └── index.js
│   ├── ButtonLanding/
│   │   ├── ButtonLanding.jsx
│   │   └── ButtonLanding.module.css
│   ├── CTAButtons/
│   │   ├── CTAButtons.jsx
│   │   └── CTAButtons.module.css
│   ├── Card/
│   │   ├── Card.jsx
│   │   └── Card.module.scss
│   ├── Chip/
│   │   ├── Chip.jsx
│   │   ├── Chip.module.scss
│   │   └── index.js
│   ├── ExploreToolsCard/
│   │   ├── ExploreToolsCard.jsx
│   │   ├── ExploreToolsCard.module.scss
│   │   └── index.js
│   ├── Footer/
│   │   ├── Footer.jsx
│   │   ├── Footer.module.scss
│   │   └── index.js
│   ├── Gallery/
│   │   ├── Gallery.jsx
│   │   ├── Gallery.module.scss
│   │   └── index.js
│   ├── GetHelpCard/
│   │   ├── GetHelpCard.jsx
│   │   ├── GetHelpCard.module.scss
│   │   └── index.js
│   ├── GetStartedCard/
│   │   ├── GetStartedCard.jsx
│   │   ├── GetStartedCard.module.scss
│   │   └── index.js
│   ├── GlobalSignUp/
│   │   ├── GlobalSignUp.jsx
│   │   └── GlobalSignUp.module.css
│   ├── Header/
│   │   ├── Header.jsx
│   │   ├── Header.module.scss
│   │   └── index.js
│   ├── ListPage/
│   │   ├── ListPage.jsx
│   │   └── index.js
│   ├── Slider/
│   │   ├── Slider.jsx
│   │   ├── Slider.module.scss
│   │   └── index.js
│   ├── Text/
│   │   ├── AccentedText.jsx
│   │   ├── AccentedText.module.scss
│   │   ├── H1.jsx
│   │   ├── H1.module.scss
│   │   ├── H2.jsx
│   │   └── H2.module.scss
│   ├── ToolCard/
│   │   ├── ToolCard.jsx
│   │   ├── ToolCard.module.scss
│   │   └── index.js
│   ├── ToolPage/
│   │   ├── Description.jsx
│   │   ├── Description.module.scss
│   │   ├── DescriptionCards.jsx
│   │   ├── DescriptionCards.module.scss
│   │   ├── Header.jsx
│   │   ├── Header.module.scss
│   │   ├── HowToGetHelp.jsx
│   │   ├── HowToGetHelp.module.scss
│   │   ├── HowToGetStarted.jsx
│   │   ├── HowToGetStarted.module.scss
│   │   ├── Integrations.jsx
│   │   ├── Integrations.module.scss
│   │   ├── Popularity.jsx
│   │   ├── Popularity.module.scss
│   │   ├── ToolPage.jsx
│   │   └── ToolPageForFramework.jsx
│   └── ToolsNumberControl/
│       ├── ToolsNumberControl.jsx
│       ├── ToolsNumberControl.module.scss
│       └── index.js
├── copy/
│   └── tools/
│       ├── .example
│       ├── .extended.example
│       ├── ag-grid.yml
│       ├── amcharts.yml
│       ├── ant-design-charts.yml
│       ├── anychart.yml
│       ├── apexcharts.yml
│       ├── appsmith.yml
│       ├── billboard.yml
│       ├── c3.yml
│       ├── chartist.yml
│       ├── chartjs.yml
│       ├── cytoscape.yml
│       ├── d3.yml
│       ├── datasette.yml
│       ├── deck-gl.yml
│       ├── echarts.yml
│       ├── flot.yml
│       ├── frappe.yml
│       ├── fusioncharts.yml
│       ├── g2.yml
│       ├── g2plot.yml
│       ├── g6.yml
│       ├── google-charts.yml
│       ├── highcharts.yml
│       ├── kepler-gl.yml
│       ├── laue.yml
│       ├── layer-cake.yml
│       ├── leaflet.yml
│       ├── lightweight-charts.yml
│       ├── mapbox-gl.yml
│       ├── material-ui-data-grid.yml
│       ├── metabase.yml
│       ├── muze.yml
│       ├── ngx-charts.yml
│       ├── nivo.yml
│       ├── observable-plot.yml
│       ├── p5.yml
│       ├── pancake.yml
│       ├── perspective.yml
│       ├── plotly.yml
│       ├── plottable.yml
│       ├── pts.yml
│       ├── react-charts.yml
│       ├── reaflow.yml
│       ├── reaviz.yml
│       ├── recharts.yml
│       ├── redash.yml
│       ├── rough.yml
│       ├── roughviz.yml
│       ├── semiotic.yml
│       ├── stackgl.yml
│       ├── superset.yml
│       ├── three.yml
│       ├── toast-ui-chart.yml
│       ├── unovis.yml
│       ├── vega-lite.yml
│       ├── vega.yml
│       ├── victory.yml
│       ├── vis.yml
│       ├── visx.yml
│       ├── vizzu.yml
│       └── zingchart.yml
├── data/
│   ├── filter.js
│   ├── frameworks.js
│   ├── tools.js
│   ├── types.js
│   └── useSlackMembers.js
├── data-update-worker/
│   ├── .gitignore
│   ├── fetchData.js
│   ├── index.js
│   ├── notifySlack.js
│   └── package.json
├── netlify.toml
├── next-sitemap.config.js
├── next.config.js
├── package.json
├── pages/
│   ├── _app.js
│   ├── _document.js
│   ├── for/
│   │   ├── [framework]/
│   │   │   ├── charting-libraries.js
│   │   │   └── index.js
│   │   └── open-source.js
│   ├── index.js
│   └── tools/
│       └── [id]/
│           ├── [framework].js
│           └── index.js
├── public/
│   ├── browserconfig.xml
│   ├── robots.txt
│   ├── site.webmanifest
│   ├── sitemap-0.xml
│   └── sitemap.xml
├── styles/
│   ├── _variables.scss
│   ├── globals.scss
│   └── indexPage.scss
├── update-copy.sh
└── utils/
    ├── number.js
    └── tracking.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/scheduled-data-update.yml
================================================
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Scheduled data update

on:
  workflow_dispatch: null
  schedule:
    # * is a special character in YAML so you have to quote this string
    - cron: "30 10 * * *"
  # push:
  #   branches:
  #     - master

jobs:
  build:
    name: Update data on schedule
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: "18.x"
      - name: Restore cache
        uses: actions/cache@v2
        with:
          path: |
            node_modules
            */*/node_modules
          key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
      - name: Install
        run: yarn install
      - name: Run update job script
        run: export ACCESS_TOKEN_GITHUB=${{ secrets.ACCESS_TOKEN_GITHUB }} && export SLACK_WEBHOOK_URL=${{ secrets.SLACK_WEBHOOK_URL }} && sh ./update-copy.sh
      - name: Commit changes
        uses: EndBug/add-and-commit@v7 # You can change this to use a specific version
        with:
          author_name: Data Update Worker
          author_email: igor@cube.dev
          cwd: "."
          default_author: github_actor
          message: "chore(copy): update data on schedule"
          pull: "--no-rebase"
          push: true

      # - name: Build Next site
      #   run: sh ./build-site.sh
      # - name: Install Netlify CLI
      #   run: npm install -g netlify-cli
      # - name: Deploy to Netlify
      #   run: netlify deploy --dir=out --prod
      #   env:
      #     NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel

# Local Netlify folder
# .netlify

================================================
FILE: .netlify/state.json
================================================
{
	"siteId": "51f8094d-998a-424a-b471-6499f5bf2933"
}

================================================
FILE: .nvmrc
================================================
lts/*

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Cube Dev, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<h1><a href='https://awesome.cube.dev'>awesome.cube.dev</a> — charts, data grids, maps, etc.</h1>

Choose the best tool for your needs by type, framework, language, or license. Get started in an instant.

<p align="center"><img src='.github/screenshot.png'/></p>

Visit [awesome.cube.dev](https://awesome.cube.dev) or suggest an [improvement](https://github.com/cube-js/awesome-tools/issues).


================================================
FILE: components/Button/Button.jsx
================================================
import styles from "./Button.module.scss";
import Link from "next/link";

export default function Button(props) {
  return (
    <Link href={props.href} legacyBehavior>
      <a
        type="button"
        role="button"
        {...props}
        className={
          props.className
            ? `${props.className} ${styles.button}`
            : styles.button
        }
      >
        <span>{props.children}</span>
      </a>
    </Link>
  );
}


================================================
FILE: components/Button/Button.module.scss
================================================
@import "/styles/variables";

.button {
  font-family: CeraPro;
  font-size: 20px;
  // line-height: 25px;
  text-align: center;
  letter-spacing: 0.02em;
  color: $purple-02;
  border: 2px solid $purple-02;
  padding: 8px 22px;
  border-radius: 12px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  background: transparent;
  cursor: pointer;
  transition: background-color 0.3s ease-in-out, border-color 0.3s ease-in-out,
    color 0.3s ease-in-out;

  &:hover {
    background: rgba(202, 201, 255, 0.5);
    color: $purple-hover;
    border-color: $purple-hover;
  }

  &:active {
    background: rgba(202, 201, 255, 0.8);
    color: $purple-press;
    border-color: $purple-press;
  }

  &[disabled="disabled"] {
    user-select: none;
    pointer-events: none;
    cursor: not-allowed;
    border-color: $dark-05;
    color: $dark-05;
  }
}


================================================
FILE: components/Button/index.js
================================================
import Button from "./Button";
export default Button;


================================================
FILE: components/ButtonLanding/ButtonLanding.jsx
================================================
import * as React from 'react';
import { useEffect } from 'react';
import Link from 'next/link';
import classNames from 'classnames/bind';

import { useState } from 'react';

import styles from './ButtonLanding.module.css';

const cn = classNames.bind(styles);
const loader = (
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none">
    <path
      d="M8 15a7 7 0 0 1-7-7 .5.5 0 1 1 1 0 6 6 0 0 0 3.7 5.5 6 6 0 0 0 6.6-1.2 6 6 0 0 0 0-8.6A6 6 0 0 0 8 2a.5.5 0 1 1 0-1 7 7 0 0 1 7 7 7 7 0 0 1-7 7Z"
      fill="currentColor"
      stroke="currentColor"
      strokeWidth=".5"
    />
  </svg>
);

export const ButtonLanding = React.forwardRef(
  (
    {
      appearance = 'light',
      color = 'transparent',
      variant = 'default',
      type = 'button',
      size = 'm',
      disabled = false,
      pseudoHover = false,
      pseudoFocus = false,
      pseudoActive = false,
      isLoad = false,
      className = '',
      children,
      href = '',
      ...rest
    },
    ref
  ) => {
    const loaderAppearAnimationDuration = 700;

    const classNames = cn('Button', `Button--appearance-${appearance}`, className, {
      'Button--pink': color === 'pink',
      'Button--purple': color === 'purple',
      'Button--cherry': color === 'cherry',
      'Button--transparent': color === 'transparent',
      'Button--back': color === 'back',
      'Button--size-s': size === 's',
      'Button--size-m': size === 'm',
      'Button--size-l': size === 'l',
      'Button--variant-outline': variant === 'outline',
      'Button--pseudoHover': pseudoHover,
      'Button--pseudoFocus': pseudoFocus,
      'Button--pseudoActive': pseudoActive,
    });

    const [isLoaderVisible, setIsLoaderVisible] = useState(isLoad);

    useEffect(() => {
      if (isLoad === false) {
        setTimeout(() => {
          setIsLoaderVisible(false);
        }, loaderAppearAnimationDuration);
      } else {
        setIsLoaderVisible(true);
      }
    }, [isLoad]);

    let prefix;
    if (isLoad || isLoaderVisible) {
      const prefixClassName = cn('Button__prefix', 'Button__prefix--loader', {
        'Button__prefix--removing': isLoaderVisible !== isLoad && !isLoad,
      });
      prefix = <span className={prefixClassName}>{loader}</span>;
    }

    if (href) {
      if (href.startsWith('/')) {
        return (
          <Link href={href} passHref legacyBehavior>
            <a ref={ref} {...rest} className={classNames}>
              {children}
            </a>
          </Link>
        );
      }
      return (
        <a ref={ref} {...rest} href={href} className={classNames}>
          {children}
        </a>
      );
    }

    return (
      <button
        ref={ref}
        {...rest}
        className={classNames}
        type={type}
        disabled={disabled || isLoad}
        style={{ '--loader-time': loaderAppearAnimationDuration + 'ms' }}
      >
        {prefix}
        {children}
      </button>
    );
  }
);

export default ButtonLanding;


================================================
FILE: components/ButtonLanding/ButtonLanding.module.css
================================================
.Button {
  --dark: hsl(240, 32%, 10%);
  --dark_a70: rgba(15, 15, 35, 0.7);
  --dark_01: var(--dark);
  --dark_02: hsla(240, 14%, 23%);
  --dark_03: hsl(240, 8%, 45%);
  --dark_03_a50: hsl(240, 32%, 10%, 0.5);
  --dark_02_a75: hsla(240, 32%, 10%, 0.75);
  --dark_04: hsl(240, 9%, 69%);
  --dark_04_a30: hsl(240, 32%, 10%, 0.3);
  --dark_05_a12: hsl(240, 32%, 10%, 0.12);
  --dark_05: hsla(240, 16%, 91%, 1);
  --dark_06: hsl(240, 40%, 10%);

  --dark_bg: hsl(240, 12%, 97%, 1);
  --dark_bg_a04: hsla(240, 32%, 10%, 0.04);
  --dark_bg_a08: hsla(240, 32%, 10%, 0.08);

  --white: hsla(240, 0%, 100%, 1);
  --white_a01: hsla(240, 0%, 100%, 0.1);
  --white_a08: hsla(0, 0%, 100%, 0.08);
  --white_a12: hsla(240, 0%, 100%, 0.12);
  --white_a15: hsla(240, 0%, 100%, 0.15);
  --white_a24: hsla(240, 0%, 100%, 0.24);

  --gray_01: hsl(228, 6%, 31%, 1);
  --gray_02: hsl(225, 4%, 39%, 1);

  --purple: hsl(251, 94%, 66%, 1);
  --purple_03: hsla(241, 94%, 84%, 1);
  --purple_03_a60: hsl(241, 94%, 66%, 0.6);
  --purple_04_a30: hsl(241, 94%, 66%, 0.3);
  --purple_bg_02: hsl(240, 50%, 98%);
  --purple_bg_a08: hsla(244, 94%, 66%, 0.08);
  --purple_bright: hsl(251, 61%, 52%, 1);
  --purple_a12: hsla(251, 94%, 66%, 0.12);

  --pink: hsl(342, 69%, 53%, 1);
  --pink_03_a60: hsl(342, 69%, 53%, 0.6);
  --pink_04_a30: hsl(342, 69%, 53%, 0.3);
  --pink_bg_a10: hsl(342, 69%, 53%, 0.1);
  --pink_bright: hsl(342, 62%, 48%, 1);
  --pink_bright_02: var(--pink_bright);

  --cherry: var(--pink);
  --cherry_dark: var(--pink_bright);

  --white_a08_on_dark_02: #434353;
  
  --loader_time: 700ms;
  --hover_transition: 0.2s;

  transition: background-color var(--hover_transition), color var(--hover_transition),
    box-shadow var(--hover_transition), opacity var(--loader_time);
  font-family: inherit;
  font-weight: 700;
  border: none;
  margin: 0;

  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

.Button:hover {
  cursor: pointer;
}

.Button:disabled {
  opacity: 0.4;
  cursor: default;
}

/* transparent */

.Button--transparent {
  background-color: transparent;
  color: var(--dark);
}

.Button--transparent.Button--variant-outline {
  box-shadow: inset 0 0 0 1px var(--dark_05);
}

.Button--transparent.Button--variant-outline:hover,
.Button--transparent.Button--variant-outline.Button--pseudoHover {
  background-color: var(--dark_bg_a04);
}

.Button--transparent.Button--variant-outline:focus-visible,
.Button--transparent.Button--variant-outline.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--transparent.Button--variant-outline:active,
.Button--transparent.Button--variant-outline.Button--pseudoActive {
  background-color: var(--dark_bg_a04);
  box-shadow: inset 0 0 0 1px var(--dark_03);
}

/* transparent-dark */

.Button--appearance-dark.Button--transparent {
  background-color: transparent;
  color: var(--white);
}

.Button--appearance-dark.Button--transparent.Button--variant-outline {
  box-shadow: inset 0 0 0 1px var(--dark_03);
}

.Button--appearance-dark.Button--transparent.Button--variant-outline:hover,
.Button--appearance-dark.Button--transparent.Button--variant-outline.Button--pseudoHover {
  background-color: var(--white_a08);
}

.Button--appearance-dark.Button--transparent.Button--variant-outline:focus-visible,
.Button--appearance-dark.Button--transparent.Button--variant-outline.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--appearance-dark.Button--transparent.Button--variant-outline:active,
.Button--appearance-dark.Button--transparent.Button--variant-outline.Button--pseudoActive {
  background-color: var(--white_a08);
  box-shadow: inset 0 0 0 1px var(--dark_05);
}

/* purple */

.Button--purple {
  background-color: var(--purple);
  color: var(--white);
}

.Button--purple:hover,
.Button--purple.Button--pseudoHover {
  background-color: var(--purple_bright);
  color: var(--white);
}

.Button--purple:focus-visible,
.Button--purple.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--purple_04_a30);
}

.Button--purple:active,
.Button--purple.Button--pseudoActive {
  background-color: var(--purple);
  box-shadow: inset 0 0 0 1px var(--purple_bright);
  color: var(--white);
}

/* purple-outline */

.Button--purple.Button--variant-outline {
  background-color: var(--white);
  color: var(--purple_bright);
  box-shadow: inset 0 0 0 1px var(--purple_04_a30);
}

.Button--purple.Button--variant-outline:hover,
.Button--purple.Button--variant-outline.Button--pseudoHover {
  background-color: var(--purple_bg_a08);
  color: var(--purple_bright);
}

.Button--purple.Button--variant-outline:focus-visible,
.Button--purple.Button--variant-outline.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--purple_04_a30);
}

.Button--purple.Button--variant-outline:active,
.Button--purple.Button--variant-outline.Button--pseudoActive {
  background-color: var(--purple_bg_a08);
  box-shadow: inset 0 0 0 1px var(--purple_bright);
  color: var(--purple_bright);
}

/* autoprefixer: ignore next */
@supports not selector(:focus-visible) {
  .Button--purple:focus {
    box-shadow: 0 0 0 3px var(--purple_04_a30);
  }
}

/* pink */

.Button--pink {
  background-color: var(--pink);
  color: var(--white);
}

.Button--pink:hover,
.Button--pink.Button--pseudoHover {
  background-color: var(--pink_bright);
  color: var(--white);
}

.Button--pink:focus-visible,
.Button--pink.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--pink:active,
.Button--pink.Button--pseudoActive {
  background-color: var(--pink);
  box-shadow: inset 0 0 0 1px var(--pink_bright);
  color: var(--white);
}

/* pink-outline */

.Button--pink.Button--variant-outline {
  background-color: var(--white);
  color: var(--pink_bright);
  box-shadow: inset 0 0 0 1px var(--pink_04_a30);
}

.Button--pink.Button--variant-outline:hover,
.Button--pink.Button--variant-outline.Button--pseudoHover {
  background-color: var(--pink_bg_a10);
  color: var(--pink_bright);
}

.Button--pink.Button--variant-outline:focus-visible,
.Button--pink.Button--variant-outline.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--pink.Button--variant-outline:active,
.Button--pink.Button--variant-outline.Button--pseudoActive {
  background-color: var(--pink_bg_a10);
  box-shadow: inset 0 0 0 1px var(--pink_bright);
  color: var(--pink_bright);
}

/* pink-outline dark */

.Button--appearance-dark.Button--pink.Button--variant-outline {
  background-color: transparent;
  color: var(--white);
}

/* autoprefixer: ignore next */
@supports not selector(:focus-visible) {
  .Button--pink:focus {
    box-shadow: 0 0 0 3px var(--pink_04_a30);
  }
}

/* cherry */

.Button--cherry {
  background-color: var(--cherry);
  color: var(--white);
}

.Button--cherry:hover,
.Button--cherry.Button--pseudoHover {
  background-color: var(--cherry_dark);
}

.Button--cherry:focus-visible,
.Button--cherry.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--cherry:active,
.Button--cherry.Button--pseudoActive {
  background-color: var(--cherry);
  box-shadow: inset 0 0 0 1px var(--cherry_dark);
}

/* cherry-outline */

.Button--cherry.Button--variant-outline {
  color: var(--cherry);
  background-color: transparent;
  box-shadow: inset 0 0 0 1px var(--pink_03_a60);
}

.Button--cherry.Button--variant-outline:hover,
.Button--cherry.Button--variant-outline.Button--pseudoHover {
  background-color: var(--pink_bg_a10);
}

.Button--cherry.Button--variant-outline:focus-visible,
.Button--cherry.Button--variant-outline.Button--pseudoFocus {
  box-shadow: 0 0 0 3px var(--pink_04_a30);
}

.Button--cherry.Button--variant-outline:active,
.Button--cherry.Button--variant-outline.Button--pseudoActive {
  background-color: var(--pink_bg_a10);
  box-shadow: inset 0 0 0 1px var(--cherry);
}

/* cherry-outline dark */

.Button--appearance-dark.Button--cherry.Button--variant-outline {
  color: var(--white);
}

/* autoprefixer: ignore next */
@supports not selector(:focus-visible) {
  .Button--cherry:focus {
    box-shadow: 0 0 0 3px var(--pink_04_a30);
  }
}

/* sizes */

.Button--size-s {
  height: 40px;
  padding: 0 16px;
  font-size: 16px;
  border-radius: 8px;
}

.Button--size-m {
  height: 48px;
  padding: 0 24px;
  font-size: 16px;
  border-radius: 8px;
}

.Button--size-l {
  height: 64px;
  padding: 0 40px;
  font-size: 20px;
  font-style: normal;
  font-weight: 700;
  border-radius: 8px;
}

.Button__prefix--loader {
  animation-name: loader_appear;
  animation-duration: var(--loader_time);
  animation-fill-mode: forwards;

  width: 16px;
}

.Button__prefix--loader + * {
  margin-left: 8px;
}

.Button__prefix--removing {
  animation-name: loader_disappear;
}

.Button__prefix--loader svg {
  display: block;

  animation-name: loader_rotation;
  animation-duration: var(--loader_time);
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes loader_appear {
  0% {
    width: 0;
    margin-right: 0;
    opacity: 0;
  }
  33% {
    opacity: 0;
  }
  66% {
    width: 16px;
    margin-right: 8px;
  }
  100% {
    opacity: 1;
  }
}

@keyframes loader_disappear {
  100% {
    width: 0;
    margin-right: 0;
    opacity: 0;
  }
  66% {
    opacity: 0;
  }
  33% {
    width: 16px;
    margin-right: 8px;
  }
  0% {
    opacity: 1;
  }
}

@keyframes loader_rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}


================================================
FILE: components/CTAButtons/CTAButtons.jsx
================================================
import * as React from 'react';
import classnames from 'classnames/bind';
import classes from './CTAButtons.module.css';
import ButtonLanding from '../ButtonLanding/ButtonLanding';
import { trackClick } from '../../utils/tracking';

const cn = classnames.bind(classes);

export const CTAButtons = ({
  reverseButtonsOrder = false,
  signupCTAId,
  bookDemoCTAId,
}) => {
  const reverse = reverseButtonsOrder;

  const bookProps = {
    href: 'https://cube.dev/contact',
    onClick: bookDemoCTAId ? trackClick(bookDemoCTAId) : undefined,
    children: 'Request a demo',
  };

  const signupProps = {
    href: 'https://cubecloud.dev/auth/signup',
    onClick: signupCTAId ? trackClick(signupCTAId) : undefined,
    children: 'Try Free',
  };
  return (
    <>
      <ButtonLanding
        size="l"
        color="cherry"
        variant="default"
        className={classes.CTAButtons__button}
        {...(reverse ? bookProps : signupProps)}
      />

      <ButtonLanding
        size="l"
        color="cherry"
        variant="outline"
        appearance="dark"
        className={classes.CTAButtons__button}
        {...(reverse ? signupProps : bookProps)}
      />
    </>
  );
};


================================================
FILE: components/CTAButtons/CTAButtons.module.css
================================================
.CTAButtons__button {
  color: white;
}


================================================
FILE: components/Card/Card.jsx
================================================
import styles from "./Card.module.scss";
import { ReactSVG } from "react-svg";

export default function Card(props) {
  let Wrapper = "a";
  if (props.notLink) {
    Wrapper = "div";
  }
  return (
    <Wrapper
      href={props?.link}
      target="_blank"
      role="button"
      className={props.height ? styles.full : null}
    >
      <div
        big={props.isBig ? "big" : null}
        color={props.color ? props.color : null}
        className={
          props.className ? styles.card + " " + props.className : styles.card
        }
        height={props.height || null}
      >
        {props.icons &&
          props.icons.map((icon) => {
            return (
              <ReactSVG
                key={icon}
                className={styles.icon}
                wrapper="span"
                src={icon}
                width="100%"
                height="100%"
              />
            );
          })}
        {props.icon && (
          <ReactSVG
            className={styles.icon}
            wrapper="div"
            src={props.icon}
          ></ReactSVG>
        )}
        <div className={styles.text}>{props.text}</div>
        {props.description && (
          <div className={styles.description}>{props.description}</div>
        )}
        {props.smallText && (
          <div className={styles.smallText}>{props.smallText}</div>
        )}
        {props.footerText && (
          <div
            className={styles.footer}
            dangerouslySetInnerHTML={{ __html: props.footerText }}
          ></div>
        )}
      </div>
    </Wrapper>
  );
}


================================================
FILE: components/Card/Card.module.scss
================================================
@import "/styles/variables";

.card {
  width: 100%;
  padding: 32px;
  border-radius: 24px;
  border: 1px solid $dark-07;

  color: $dark;
  background-color: $dark-07;
  transition: background-color 0.3s ease-in-out, border-color 0.3s ease-in-out,
    color 0.3s ease-in-out;

  &:hover {
    background: $light;
    border-color: $purple-04;
  }

  &:active {
    background: #ececff;
    border-color: $purple-03;
  }
}
.card[color="orange"] {
  color: $orange;
  background-color: $orange-02;
  border-color: $orange-02;
  &:hover {
    background: #ffecda;
    border-color: #ffc2a5;
  }

  &:active {
    background: #ffe4cb;
    border-color: #ff905d;
  }
  &[disabled="disabled"] {
    user-select: none;
    pointer-events: none;
    cursor: not-allowed;
    border-color: $dark-05;
    color: $dark-05;
  }
}
.icon {
  width: 22px;
  height: 22px;
  margin-bottom: 10px;
  display: inline-flex;
  margin-right: 8px;
  svg {
    width: 100%;
    height: 100%;
  }
}
.text {
  // margin-top: 10px;
  font-size: 24px;
  line-height: 30px;
  font-weight: 500;
  // margin-bottom: 8px;
}
// .description {
//   //
// }
.smallText {
  margin-top: 8px;
}
.link {
  margin-top: 8px;
}
.footer {
  margin-top: 24px;
  color: $dark-02;
}
.card[color="orange"] {
  .footer {
    color: $orange;
  }
}
.card[big="big"] {
  width: 100%;
  padding: 48px 42px;
  border-radius: 24px;
  .text {
    font-size: 48px;
    line-height: 60px;
    margin-bottom: 0;
  }
  .icon {
    width: 24px;
    height: 24px;
    margin-bottom: 10px;
  }
}

// fix
.full {
  height: 100%;
}
.card[height="full"] {
  height: 100%;
}


================================================
FILE: components/Chip/Chip.jsx
================================================
import styles from "./Chip.module.scss";

export default function Chip(props) {
  return (
    <button
      type="button"
      onClick={props.onClick}
      className={
        props.className ? styles.chip + " " + props.className : styles.chip
      }
      active={props.active}
    >
      <span>
        {props.icon && (
          <img
            className={styles.icon}
            src={`/images/logo/${props.icon}`}
            alt={props.title}
          />
        )}
        <span>{props.title}</span>
      </span>
    </button>
  );
}


================================================
FILE: components/Chip/Chip.module.scss
================================================
@import "/styles/variables";

.chip {
  font-family: CeraPro;
  border: none;
  padding: 8px 16px;
  background-color: $dark-06;
  border: 1px solid $dark-06;
  border-radius: 40px;
  color: $dark-03;
  font-size: 24px;
  line-height: 30px;
  transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out,
    border-color 0.3s ease-in-out;
  cursor: pointer;
  display: flex;
  align-items: center;
  span {
    display: inline-flex;
    align-items: center;
  }
  img {
    width: 18px;
    height: 18px;
    margin-right: 8px;
    fill: red;
  }

  &:hover {
    @media (hover) {
      color: $purple-hover;
      border: 1px solid $purple-04;
    }
  }

  &[active="active"] {
    background-color: $light;
    color: $purple-hover;
    border: 1px solid $purple-04;
  }

  @media (max-width: 991.98px) {
    margin-top: 8px;
    margin-bottom: 8px;
  }
  @media (max-width: 767.98px) {
    padding: 4px 8px;
  }
}

.icon {
  display: inline-flex;
  margin-right: 8px;
  min-width: 22px;
  min-height: 22px;
  svg {
    width: 22px;
    height: 22px;
  }
}


================================================
FILE: components/Chip/index.js
================================================
import Chip from "./Chip";
export default Chip;


================================================
FILE: components/ExploreToolsCard/ExploreToolsCard.jsx
================================================
import styles from "./ExploreToolsCard.module.scss";
import { ReactSVG } from "react-svg";

export default function ExploreToolsCard(props) {
  return (
    <a
      className="col-6 col-md-6 col-lg-4 col-xl-2"
      onClick={props.onClick}
      role="button"
    >
      <div className={styles.exploreToolsCard} active={props.active || null}>
        <div className={styles.exploreToolsCard__wrap}>
          <h2
            className={styles.exploreToolsCard__text}
            dangerouslySetInnerHTML={{ __html: props.text.replace(' ', '<br/>') }}
          ></h2>
        </div>
        {props.image && (
          <ReactSVG
            wrapper="span"
            src={`/images/${props.image}`}
            className={styles.exploreToolsCard__image}
          />
        )}
      </div>
    </a>
  );
}


================================================
FILE: components/ExploreToolsCard/ExploreToolsCard.module.scss
================================================
@import "/styles/variables";

.exploreToolsCard {
  background: $dark-06;
  border: 1px solid $dark-06;
  transition: border 0.3s ease-in-out, background 0.3s ease-in-out;
  border-radius: 24px;
  overflow: hidden;
  cursor: pointer;
  margin-bottom: 16px;
  user-select: none;
  font-weight: 500;

  &[active="active"] {
    background-color: darken(#ecebff, 5%);
  }
  &__wrap {
    padding: 24px 24px 0px 24px;
    @media (max-width: 767.98px) {
      padding: 16px 16px 0 16px;
    }
  }

  &__text {
    font-size: 24px;
    font-weight: 500;
    line-height: 30px;
    color: $dark-03;
    margin: 0;
    transition: color 0.3s ease-in-out;
  }

  &__image {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    transition: color 0.3s ease-in-out;
    color: $dark-05;
    height: 64px;
  }

  &:hover {
    // fix mobile hover effect
    @media (hover) {
      border: 1px solid $purple-04;
      .exploreToolsCard__text {
        color: $purple-hover;
      }
      .exploreToolsCard__image {
        color: $purple-04;
      }
    }
  }

  &[active="active"] {
    background: $light;
    border: 1px solid $purple-04;
    .exploreToolsCard__text {
      color: $purple-hover;
    }
    .exploreToolsCard__image {
      color: $purple-04;
    }
  }

  &[disabled="disabled"] {
    .exploreToolsCard__text {
      color: $dark-07;
    }
  }
  @media (max-width: 767.98px) {
    margin-bottom: 8px;
  }
}


================================================
FILE: components/ExploreToolsCard/index.js
================================================
import ExploreToolsCard from "./ExploreToolsCard";
export default ExploreToolsCard;


================================================
FILE: components/Footer/Footer.jsx
================================================
import styles from "./Footer.module.scss";
import { ReactSVG } from "react-svg";

export default function Footer() {
  return (
    <footer className={styles.footer + " container custom-container"}>
      <div>
        <ReactSVG
          className={styles.footer__logo}
          src="/images/logo/cubejs-logo.svg"
        />
      </div>
      <div className={styles.info}>
        <p>
          Created and maintained in open source
          <br />
          by{" "}
          <a href="https://cube.dev/" target="_blank">
            Cube Dev
          </a>
          , the creators of{" "}
          <a href="https://github.com/cube-js/cube.js" target="_blank">
            Cube
          </a>
        </p>
        <p>
          Want to add a new tool or update the info?{" "}
          <br className="xs-hidden" />
          We appreciate{" "}
          <a
            href="https://github.com/cube-js/awesome-tools/issues"
            target="_blank"
          >
            issues
          </a>{" "}
          and{" "}
          <a
            href="https://github.com/cube-js/awesome-tools/pulls"
            target="_blank"
          >
            pull requests
          </a>
        </p>
      </div>
    </footer>
  );
}


================================================
FILE: components/Footer/Footer.module.scss
================================================
@import "/styles/variables";

.footer {
  margin-top: 90px;
  border-top: 2px solid #e7e9ed;
  padding-top: 64px;
  padding-bottom: 80px;
}
.info {
  margin-top: 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  p {
    margin: 0;
    font-size: 16px;
    line-height: 28px;
    color: $dark-03;
  }
  a {
    color: $dark;
  }
  @media (max-width: 767.98px) {
    flex-direction: column;
    align-items: flex-start;
    p:last-child {
      margin-top: 16px;
    }
  }
}


================================================
FILE: components/Footer/index.js
================================================
import Footer from "./Footer";
export default Footer;


================================================
FILE: components/Gallery/Gallery.jsx
================================================
import dynamic from "next/dynamic";
import styles from "./Gallery.module.scss";
import H2 from "../Text/H2";
const Slider = dynamic(() => import("../../components/Slider"));

export default function Gallery(props) {
  return (
    <div className={styles.gallery + " row"}>
      <div className="col-sm-3">
        <H2>Gallery</H2>
        {props.link && (
          <div className="mt-sm">
            <a href={props.link} className="link" target="_blank">
              All examples →
            </a>
          </div>
        )}
      </div>
      <div className={styles.sliderWrap + " col-sm-9"}>
        <Slider slidesData={props.gallery} />
      </div>
    </div>
  );
}


================================================
FILE: components/Gallery/Gallery.module.scss
================================================
.gallery {
  margin-bottom: 104px;
  @media (max-width: 767.98px) {
    margin-bottom: 48px;
  }
}
.sliderWrap {
  @media (max-width: 767.98px) {
    margin-top: 24px;
  }
}


================================================
FILE: components/Gallery/index.js
================================================
import Gallery from "./Gallery";
export default Gallery;


================================================
FILE: components/GetHelpCard/GetHelpCard.jsx
================================================
import styles from "./GetHelpCard.module.scss";
import Link from "next/link";

export default function Card(props) {
  return (
    <Link href={props.href} legacyBehavior>
      <a target="_blank">
        <div
          className={
            props.className ? styles.card + " " + props.className : styles.card
          }
        >
          {props.icon && (
            <div
              className={styles.icon}
              style={{ backgroundImage: `url(${props.icon})` }}
            ></div>
          )}
          {props.title && <div className={styles.title}>{props.title}</div>}
          {props.footer && <div className={styles.footer}>{props.footer}</div>}
        </div>
      </a>
    </Link>
  );
}


================================================
FILE: components/GetHelpCard/GetHelpCard.module.scss
================================================
@import "/styles/variables";
.card {
  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);
  transition: box-shadow 0.32s ease-in-out;
  border-radius: 32px;
  background: #ffffff;
  padding: 32px;
  cursor: pointer;
  height: 100%;
  &:hover {
    box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.5);
  }
}
.icon {
  width: 64px;
  height: 64px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.title {
  margin-top: 16px;
  font-size: 24px;
  font-weight: 500;
  line-height: 30px;
  color: $dark;
}
.footer {
  margin-top: 8px;
  font-size: 14px;
  line-height: 18px;
  letter-spacing: 0.02em;
  color: $dark;
}


================================================
FILE: components/GetHelpCard/index.js
================================================
import GetHelpCard from "./GetHelpCard";
export default GetHelpCard;


================================================
FILE: components/GetStartedCard/GetStartedCard.jsx
================================================
import styles from "./GetStartedCard.module.scss";
import { ReactSVG } from "react-svg";

export default function Card(props) {
  return (
    <a href={props.link} target="_blank">
      <div
        className={
          props.className ? styles.card + " " + props.className : styles.card
        }
      >
        {props.icon && (
          <ReactSVG
            className={styles.icon}
            wrapper="div"
            src={props.icon}
          ></ReactSVG>
        )}
        {props.type && <div className={styles.type}>{props.type}</div>}
        {props.title && <div className={styles.title}>{props.title}</div>}
        {props.link && (
          <div className={styles.link}>
            <span className="link">Read more →</span>
          </div>
        )}
      </div>
    </a>
  );
}


================================================
FILE: components/GetStartedCard/GetStartedCard.module.scss
================================================
@import "/styles/variables";

.card {
  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);
  transition: box-shadow 0.32s ease-in-out;
  border-radius: 32px;
  padding: 32px;
  height: 100%;
  // margin-bottom: 32px;
  &:hover {
    box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.5);
  }
  &:nth-child(3) {
    margin-top: 32px;
  }
}
.type {
  margin-top: 16px;
  font-size: 16px;
  line-height: 26px;
  text-transform: uppercase;
  color: $dark;
}
.title {
  font-size: 24px;
  line-height: 30px;
  font-weight: 500;
  color: $dark;
  margin-top: 16px;
}
.link {
  margin-top: 24px;
  margin-bottom: 23px;
}


================================================
FILE: components/GetStartedCard/index.js
================================================
import GetStartedCard from "./GetStartedCard";
export default GetStartedCard;


================================================
FILE: components/GlobalSignUp/GlobalSignUp.jsx
================================================
import * as React from 'react';
import classnames from 'classnames/bind';
import classes from './GlobalSignUp.module.css';

const cn = classnames.bind(classes);


export const GlobalSignUp = ({ className, children }) => {
  return (
    <div
      style={
          {
            '--section_padding_top': `48px`,
            '--section_padding_bottom': `48px`,
          }
        }
        className={cn(
          'Section',
          `Section--appearance-dark`,
          `Section--gap-xl`,
          cn('GlobalSignUp', className)
        )}
    >
      <div
        className={cn(
          'SectionContent',
          `SectionContent--align-none`,
          `SectionContent--size-m`,
          `Section--gap-none`,
          classes.GlobalSignUp__content
        )}
      >
        <h2 className={classes.GlobalSignUp__title}>Deliver better data, faster—with Cube.</h2>
        <div className={classes.GlobalSignUp__buttons}>{children}</div>
      </div>
    </div>
  );
};


================================================
FILE: components/GlobalSignUp/GlobalSignUp.module.css
================================================
.GlobalSignUp {
  background-color: hsl(240, 32%, 10%);
  overflow: hidden;
  position: relative;
}

.GlobalSignUp::before {
  content: "";
  position: absolute;
  width: 100%;
  min-width: 600px;
  /* stylelint-disable-next-line */
  padding-bottom: 100%;
  right: -40%;
  top: 50%;
  transform: translateY(-50%);
  background-image: radial-gradient(#ac0053 30%, #ac005300 65%);
  opacity: 0.6;
  z-index: 0;
}

@media (max-width: 639px) {
  .GlobalSignUp::before {
    background-image: radial-gradient(#ac0053 40%, #ac005300 75%);
    right: 50%;
    transform: translateX(50%) translateY(-5%);
  }
}

.GlobalSignUp > * {
  z-index: 1;
}

.GlobalSignUp__content {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 16px;
}

.GlobalSignUp__content a {
  color: white;
}

.GlobalSignUp__title {
  font-size: 32px;
  line-height: 44px;
  font-weight: 700;
  font-family: CeraPro;
  flex-grow: 1;
  margin: 0;
}

.GlobalSignUp__buttons {
  display: flex;
  gap: 16px;
}

@media (min-width: 640px) {
  .GlobalSignUp__buttons > * {
    flex-grow: 1;
    flex-basis: 0;
  }
}

@media (max-width: 979px) {
  .GlobalSignUp__content {
    flex-direction: column;
  }
  .GlobalSignUp__buttons {
    width: 100%;
  }

  .GlobalSignUp__title {
    text-align: center;
  }
}

@media (max-width: 639px) {
  .GlobalSignUp__buttons {
    flex-direction: column;
  }
}


.Section {
  --section_padding_top: 0px;
  --section_padding_bottom: 0px;
  display: flex;
  flex-flow: column;
  overflow: hidden;
  padding: var(--section_padding_top) 0 var(--section_padding_bottom);
}

.Section--gap-l {
  gap: 32px;
}

.Section--gap-xl {
  gap: 48px;
}

.Section--gap-2xl {
  gap: 64px;
}

.Section--gap-3xl {
  gap: 80px;
}

@media (min-width: 640px) {
  .Section--rounded {
    border-radius: 32px;
    margin: 16px;
  }
}

@media (min-width: 1980px) {
  .Section--rounded {
    max-width: calc(1980px - 32px);
    width: 100%;
    margin: 16px auto;
  }
}

.Section--bordered-bottom {
  box-shadow: inset 0 -1px 0 rgba(192, 192, 234, 0.4);
}

.Section--appearance-light {
  background-color: white;
}

.Section--hero.Section--appearance-light {
  background-color: ¿hsl(240, 12%, 97%, 1);;
}

.Section--appearance-dark {
  background-color: hsla(240, 14%, 23%);
  color: white;
}

.Section--transparent {
  background-color: transparent;
}

/*  */

.Section--absoluteTop {
  position: relative;
  overflow: visible;
}

.Section--absoluteTop > * {
  position: absolute !important;
  top: 0;
  left: 0;
  right: 0;
}

.Section--absoluteTop + .Section {
  padding-top: calc(var(--section_padding_top) + var(--topbar_height));
}

/* content */

.SectionContent {
  width: 100%;
  margin: 0 auto;
  padding: 0 24px;
}

.SectionContent--size-xs {
  max-width: calc(800px + 2 * 24px);
}

.SectionContent--size-s {
  max-width: calc(1040px + 2 * 24px);
}

.SectionContent--size-m {
  max-width: calc(1120px + 2 * 24px);
}

.SectionContent--size-l {
  max-width: calc(1248px + 2 * 24px);
}

.SectionContent--align-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.SectionContent.Section--gap-xl,
.SectionContent.Section--gap-2xl,
.SectionContent.Section--gap-3xl {
  display: flex;
  flex-flow: column;
}


================================================
FILE: components/Header/Header.jsx
================================================
import styles from "./Header.module.scss";
import { useRouter } from "next/router";
import Link from "next/link";

export default function Header() {
  const router = useRouter();
  const isRoot = router.pathname === "/";

  return (
    <header className={styles.header}>
      <div className={styles.header__logo + " container custom-container"}>
        <a href="https://cube.dev/" target="_blank" aria-label="Cube">
          <span className={styles.header__logo}>
            <img src={`/images/logo/cubejs-logo.svg`} alt="Cube" />
          </span>
        </a>
        <ConditionalWrapper
          condition={!isRoot}
          wrapper={(children) => <Link href="/">{children}</Link>}
        >
          <span
            className={styles.header__text}
            active={!isRoot ? "active" : ""}
          >
            <img
              src={`/images/logo/cubejs-awesome-tools.svg`}
              alt="Awesome tools"
            />
          </span>
        </ConditionalWrapper>
      </div>
    </header>
  );
}

const ConditionalWrapper = ({ condition, wrapper, children }) => (
  <>{condition ? wrapper(children) : children}</>
);


================================================
FILE: components/Header/Header.module.scss
================================================
.header {
  padding: 24px 0;

  &__logo {
    display: flex;
    align-items: center;
    min-height: 28px;
  }

  &__text {
    margin-left: 8px;

    &[active="active"] {
      cursor: pointer;
    }
  }
}


================================================
FILE: components/Header/index.js
================================================
import Header from "./Header";
export default Header;


================================================
FILE: components/ListPage/ListPage.jsx
================================================
import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import { useRouter } from "next/router";
import { filter, setParamsFromRouter } from "../../data/filter";
import allFrameworks from "../../data/frameworks";
import allTypes from "../../data/types";
import Chip from "../Chip";
import ExploreToolsCard from "../ExploreToolsCard";
import H1 from "../Text/H1";
import AccentedText from "../Text/AccentedText";
import { NextSeo } from "next-seo";
import ToolCard from "../ToolCard";
import ToolsNumberControl from "../ToolsNumberControl";

export default function ListPage({
  tools,
  framework,
  title,
  showType = true,
  showCompatibleWith = true,
  showLicense = true,
}) {
  const router = useRouter();
  const query = router.query;
  const [isFirstLoad, setLoad] = useState(false);
  const [exploreTools, setExploreTools] = useState([]);
  const [frameworks, setFrameworks] = useState([]);
  const [languages, setLanguages] = useState([]);
  const [licenses, setLicenses] = useState([]);
  const [renders, setRenders] = useState([]);

  const isFiltered =
    exploreTools.length ||
    frameworks.length ||
    languages.length ||
    licenses.length ||
    renders.length;

  useEffect(() => {
    if (Object.keys(query).length && !isFirstLoad) {
      setParamsFromRouter(
        query,
        setExploreTools,
        setFrameworks,
        setLanguages,
        setLicenses,
        setRenders
      );
      setLoad(true);
    }
  }, [query]);

  useEffect(() => {
    router.push(
      {
        query: {
          ...(framework && { framework }),
          tools: exploreTools,
          ...(!framework && { frameworks }),
          languages,
          licenses,
          renders,
        },
      },
      undefined,
      { scroll: false }
    );
  }, [framework, exploreTools, frameworks, languages, licenses, renders]);

  const filteredTools = isFiltered
    ? filter(tools, frameworks, languages, licenses, renders, exploreTools)
    : tools;

  const setItem = (array, set, item) => {
    const index = array.indexOf(item);
    if (index === -1) {
      set([...array, item]);
      // return true;
    } else {
      array.splice(index, 1);
      set([...array]);
      // return false;
    }
  };

  return (
    <>
      <NextSeo
        title={`${title} — the awesome list`}
        description={`${title} for application developers: charting libraries, data grids, maps, etc.`}
      />

      <div className="container custom-container">
        <main>
          <H1>
            {title} <br className="xl-hidden" /> for application developers
          </H1>

          {showType && (
            <div className="row mb-md">
              {Object.values(allTypes).map((type, i) => (
                <ExploreToolsCard
                  key={type.slug}
                  onClick={() =>
                    setItem(exploreTools, setExploreTools, type.slug)
                  }
                  active={exploreTools.includes(type.slug) ? "active" : null}
                  text={type.name}
                  image={type.image}
                />
              ))}
            </div>
          )}

          {showCompatibleWith && (
            <div className="flex flex-wrap-row flex-items-center mb-sm">
              <AccentedText className="mr-xs">Compatible with</AccentedText>

              {Object.values(allFrameworks).map((framework) => (
                <Chip
                  key={framework.slug}
                  className="mr-xs"
                  icon={framework.icon}
                  title={framework.name}
                  active={frameworks.includes(framework.slug) ? "active" : null}
                  onClick={() =>
                    setItem(frameworks, setFrameworks, framework.slug)
                  }
                />
              ))}
            </div>
          )}

          <div className="flex flex-wrap-row flex-items-center mb-sm">
            <AccentedText className="mr-xs">With support for</AccentedText>

            <Chip
              icon="typescript.svg"
              title="TypeScript"
              active={languages.includes("typescript") ? "active" : null}
              onClick={() => setItem(languages, setLanguages, "typescript")}
            />
            {showLicense && (
              <AccentedText className="mr-xs ml-xs">and</AccentedText>
            )}
            {showLicense && (
              <>
                <Chip
                  className="mr-xs"
                  icon="open-source.svg"
                  title="open source"
                  active={licenses.includes("open-source") ? "active" : null}
                  onClick={() => setItem(licenses, setLicenses, "open-source")}
                />
                <Chip
                  icon="proprietary.svg"
                  title="proprietary"
                  active={licenses.includes("proprietary") ? "active" : null}
                  onClick={() => setItem(licenses, setLicenses, "proprietary")}
                />
                <AccentedText className="ml-xs">license</AccentedText>
              </>
            )}
          </div>
          <div className="flex flex-wrap-row flex-items-center">
            <AccentedText className="mr-xs">Rendering</AccentedText>

            <Chip
              title="Canvas"
              className="mr-xs"
              active={renders.includes("canvas") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "canvas")}
            />
            <Chip
              title="SVG"
              className="mr-xs"
              active={renders.includes("svg") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "svg")}
            />
            <Chip
              title="HTML"
              active={renders.includes("html") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "html")}
            />
          </div>

          <div className="number-control-wrap">
            <ToolsNumberControl
              filteredTools={filteredTools}
              isChanged={isFiltered}
              clearFilters={() => {
                clearFilters([
                  setExploreTools,
                  setFrameworks,
                  setLanguages,
                  setLicenses,
                  setRenders,
                ]);
              }}
            />
          </div>

          <div className="row">
            {filteredTools &&
              filteredTools.map((tool) => (
                <div className="col-xl-6 mb-md" key={tool.id}>
                  {/* to lazy load on scroll need to set heigth */}
                  <ToolCard {...tool} />
                </div>
              ))}
          </div>
        </main>
      </div>
    </>
  );
}

function clearFilters(arrayOfFunctions) {
  arrayOfFunctions.forEach((fn) => {
    fn([]);
  });
}


================================================
FILE: components/ListPage/index.js
================================================
import ListPage from "./ListPage";
export default ListPage;


================================================
FILE: components/Slider/Slider.jsx
================================================
// App.js
import React, { useState, useEffect } from "react";
import styles from "./Slider.module.scss";
// import "./App.css";

import Slider from "react-slick";

import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

function getSettingsThumbs(slidesToShow) {
  return {
    slidesToShow: Math.min(4, slidesToShow),
    slidesToScroll: 1,
    asNavFor: ".slider-for",
    dots: false,
    centerMode: false,
    swipeToSlide: true,
    focusOnSelect: true,
  };
}

function App(props) {
  const [nav1, setNav1] = useState(null);
  const [nav2, setNav2] = useState(null);
  const [slider1, setSlider1] = useState(null);
  const [slider2, setSlider2] = useState(null);

  useEffect(() => {
    setNav1(slider1);
    setNav2(slider2);
  });

  const settingsMain = {
    slidesToShow: 1,
    slidesToScroll: 1,
    arrows: false,
    fade: true,
    asNavFor: ".slider-nav",
  };

  return (
    <div className={styles.slider}>
      <div className={styles.sliderWrapper}>
        <Slider
          {...settingsMain}
          asNavFor={nav2}
          ref={(slider) => setSlider1(slider)}
        >
          {props.slidesData &&
            props.slidesData.map((slide, i) => (
              <div className={styles.slickSlide} key={slide}>
                <img
                  className={styles.slickSlideImage}
                  src={slide}
                  alt={`Preview ${i}`}
                />
              </div>
            ))}
        </Slider>
        <div className={styles.thumbnailSliderWrap}>
          <Slider
            {...getSettingsThumbs(props.slidesData.length)}
            asNavFor={nav1}
            ref={(slider) => setSlider2(slider)}
          >
            {props.slidesData &&
              props.slidesData.map((slide, i) => (
                <div className={styles.slickSlide} key={slide}>
                  <img
                    className={styles.slickSlideImage}
                    src={slide}
                    alt={`Thumbnail ${i}`}
                  />
                </div>
              ))}
          </Slider>
        </div>
      </div>
    </div>
  );
}

export default App;


================================================
FILE: components/Slider/Slider.module.scss
================================================
.thumbnailSliderWrap {
  margin-top: 27px;
  // height: 85px;
  @media (max-width: 767.98px) {
    margin-top: 16px;
  }
}
.slickSlide {
  text-align: center;
}
.sliderWrapper {
  .slickSlide img {
    border: 2px solid #e7e7e7;
    box-sizing: border-box;
    border-radius: 16px;
    width: 100%;
    @media (max-width: 767.98px) {
      width: 100%;
    }
  }
}
.thumbnailSliderWrap {
  max-height: 111px;
  overflow: hidden;
  @media (max-width: 1200px) {
    height: 70px;
  }
  @media (max-width: 767.98px) {
    height: 50px;
  }
  .slickSlide img {
    cursor: pointer;
    // width: 90%;
    max-width: 213px;
    border: 1px solid #d5d5e2;
    border-radius: 8px;
    outline: none;
    max-height: 111px;
    @media (max-width: 1400px) {
      width: 90%;
    }
    @media (max-width: 1200px) {
      max-height: 70px;
    }
    @media (max-width: 767.98px) {
      max-height: 50px;
    }
  }
}


================================================
FILE: components/Slider/index.js
================================================
import Slider from "./Slider";
export default Slider;


================================================
FILE: components/Text/AccentedText.jsx
================================================
import styles from "./AccentedText.module.scss";

export default function AccentedText(props) {
  return (
    <span
      className={
        props.className
          ? styles.accented + " " + props.className
          : styles.accented
      }
    >
      {props.children}
    </span>
  );
}


================================================
FILE: components/Text/AccentedText.module.scss
================================================
.accented {
  font-size: 24px;
  line-height: 30px;
}


================================================
FILE: components/Text/H1.jsx
================================================
import styles from "./H1.module.scss";

export default function H1(props) {
  return <h1 className={styles.title}>{props.children}</h1>;
}


================================================
FILE: components/Text/H1.module.scss
================================================
@import "/styles/variables";

.title {
  font-style: normal;
  font-weight: 700;
  font-size: 64px;
  line-height: 72px;
  margin: 24px 0;

  @media (max-width: 767.98px) {
    font-size: 32px;
    line-height: 44px;
  }
}


================================================
FILE: components/Text/H2.jsx
================================================
import styles from "./H2.module.scss";

export default function H2(props) {
  return (
    <h2
      {...props}
      className={
        props.className ? styles.h2 + " " + props.className : styles.h2
      }
    >
      {props.children}
    </h2>
  );
}


================================================
FILE: components/Text/H2.module.scss
================================================
@import "/styles/variables";

.h2 {
  font-size: 40px;
  line-height: 50px;
  color: $dark;
  margin: 0;
  @media (max-width: 767.98px) {
    font-size: 26px;
    line-height: 36px;
  }
}


================================================
FILE: components/ToolCard/ToolCard.jsx
================================================
import styles from "./ToolCard.module.scss";
import dayjs from "dayjs";
import dayjsUtc from "dayjs/plugin/utc";
import Link from "next/link";
import abbreviateNumber from "../../utils/number";

dayjs.extend(dayjsUtc);

export default function ToolCard(props) {
  let shadow = getShadowByLabel(props?.feature_label);
  let language = null;
  if (props.languages && props.languages.length > 0) {
    language = props?.languages?.includes("TypeScript")
      ? "TypeScript"
      : "JavaScript";
  }

  return (
    <Link href={"/tools/" + props.id} className="full-height" legacyBehavior>
      <a className="full-height">
        <div className={styles.toolCard} shadow={shadow}>
          <div className="flex flex-items-center">
            <img
              className={styles.toolCard__logo}
              src={`/images/logo/${props.logo}`}
              alt={`${props.title} logo`}
            />
            <div className="flex flex-column">
              <h2 className={styles.toolCard__title}>
                {props.title || ""}
                {props.developer && (
                  <span className={styles.toolCard__developer}>
                    &nbsp;by&nbsp;{props.developer}
                  </span>
                )}
              </h2>
            </div>
          </div>
          <p
            className={styles.toolCard__description}
            dangerouslySetInnerHTML={{ __html: props.description }}
          ></p>
          <div className="flex flex-wrap-row">
            {props?.github_data && (
              <div className="flex flex-column">
                <span className={styles.features}>GitHub stars</span>
                <div className={styles.github}>
                  <img
                    className={styles.icon}
                    src={`/images/logo/github.svg`}
                    alt={`${props.title} logo`}
                  />
                  <span className={styles.features__text}>
                    {abbreviateNumber(props?.github_data?.stars) || "-"}
                  </span>
                </div>
              </div>
            )}

            {props.frameworks && props.frameworks.length > 0 && (
              <div className="flex flex-column">
                <span className={styles.features}>Framework</span>
                <div className={styles.framework}>
                  {props.frameworks &&
                    props.frameworks.map((framework, i) => {
                      return (
                        <div
                          className={styles.framework__wrapper}
                          key={`${framework}_${i}`}
                        >
                          {framework !== "Universal" ? (
                            <img
                              className={styles.icon}
                              src={`/images/logo/${framework.toLowerCase()}.svg`}
                              alt={`${props.title} logo`}
                            />
                          ) : null}
                          {props.frameworks.length === 1 && (
                            <span className={styles.features__text}>
                              {framework === "vanilla-js"
                                ? "vanilla JS"
                                : framework}
                            </span>
                          )}
                        </div>
                      );
                    })}
                </div>
              </div>
            )}

            {language && (
              <div className="flex flex-column">
                <span className={styles.features}>Language</span>
                <div className={styles.language}>
                  <div className={styles.language__wrapper}>
                    {language ? (
                      <img
                        className={styles.icon}
                        src={`/images/logo/${language.toLowerCase()}.svg`}
                        alt={`${props.title} logo`}
                      />
                    ) : null}
                    <span className={styles.features__text}>{language}</span>
                  </div>
                </div>
              </div>
            )}

            {props?.github_data?.last_release?.date && (
              <div className="flex flex-column">
                <span className={styles.features}>Last release</span>
                <div>
                  <span className={styles.features__text}>
                    {dayjs(props?.github_data?.last_release?.date)
                      .utc()
                      .format("MMM DD, YYYY") || "-"}
                  </span>
                </div>
              </div>
            )}
          </div>
          {props.feature_label && (
            <div className={styles.toolCard__achievement}>
              <img
                className={styles.toolCard__achievement__icon}
                src={`/images/${props.feature_label}.svg`}
                alt={`${props.title} logo`}
              />
            </div>
          )}
        </div>
      </a>
    </Link>
  );
}

function getShadowByLabel(label) {
  if (!label) {
    return "gray";
  }

  return label;
}


================================================
FILE: components/ToolCard/ToolCard.module.scss
================================================
@import "/styles/variables";

.toolCard {
  cursor: pointer;
  padding: 32px;
  color: $dark;
  background: #ffffff;
  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);
  border-radius: 40px;
  position: relative;
  max-width: 600px;
  height: 100%;
  transition: box-shadow 0.3s ease-in-out;
  margin: 0 auto;

  @media (max-width: 767.98px) {
    padding: 24px;
  }

  &:hover {
    box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.5);
  }

  &__logo {
    width: 60px;
    height: 60px;
    border: 1px solid rgba(213, 213, 226, 0.5);
    border-radius: 16px;
  }

  &__title {
    font-weight: 700;
    font-size: 26px;
    line-height: 36px;
    margin: 0 0 0 16px;
  }

  &__developer {
    color: $dark-03;
  }

  &__description {
    font-size: 18px;
    line-height: 24px;
    font-style: normal;
    font-weight: normal;
    max-width: 424px;
    min-height: 48px;
    margin-top: 24px;
    margin-bottom: 48px;
    @media (min-width: 1200px) and (max-width: 1400px) {
      max-width: 400px;
    }
    @media (min-width: 767.98px) and (max-width: 1200px) {
      max-width: 290px;
    }
    @media (max-width: 767.98px) {
      margin-bottom: 16px;
      margin-top: 16px;
    }
  }

  &__achievement {
    position: absolute;
    right: 32px;
    top: 32px;
    @media (max-width: 767.98px) {
      right: 0;
      top: 0;
      transform: scale3d(0.5, 0.5, 0.5);
    }

    &__icon {
      width: 104px;
      height: 104px;
    }
  }
}

.features {
  color: $dark-03;
  font-size: 12px;
  line-height: 15px;
  padding-bottom: 5px;
  min-width: 94px;
  margin-right: 40px;
  &__text {
    text-transform: capitalize;
    font-size: 16px;
    font-weight: 500;
  }
  @media (max-width: 1400px) {
    margin-right: 20px;
  }
  @media (max-width: 767.98px) {
    margin-right: 40px;
  }
}
.github {
  display: flex;
  align-items: center;
  .icon {
    width: 16px;
    height: 16px;
    margin-right: 5px;
  }
}
.language {
  display: flex;
  align-items: center;
  &__wrapper {
    display: flex;
    align-items: center;
  }
  .icon {
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    margin-right: 5px;
  }
}
.framework {
  display: flex;
  align-items: center;
  &__wrapper {
    display: flex;
    align-items: center;
    @media (max-width: 767.98px) {
      margin-bottom: 8px;
    }
  }
  .icon {
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    margin-right: 5px;
  }
}

.toolCard[shadow="well-documented"] {
  box-shadow: 16px 24px 80px rgba(255, 133, 95, 0.3);
  &:hover {
    box-shadow: 16px 24px 80px rgba(255, 133, 95, 0.5);
  }
}
.toolCard[shadow="easy-to-start-with"] {
  box-shadow: -16px 24px 80px rgba(66, 204, 173, 0.3);
  &:hover {
    box-shadow: -16px 24px 80px rgba(66, 204, 173, 0.5);
  }
}
.toolCard[shadow="full-fledged"] {
  box-shadow: 0px 24px 80px rgba(255, 124, 226, 0.4);
  &:hover {
    box-shadow: 0px 24px 80px rgba(255, 124, 226, 0.5);
  }
}
.toolCard[shadow="easy-to-customize"] {
  box-shadow: 0px 24px 80px rgba(115, 159, 243, 0.4);
  &:hover {
    box-shadow: 0px 24px 80px rgba(115, 159, 243, 0.5);
  }
}
.toolCard[shadow="very-popular"] {
  box-shadow: 0px 24px 80px rgba(255, 194, 123, 0.4);
  &:hover {
    box-shadow: 0px 24px 80px rgba(255, 194, 123, 0.5);
  }
}
.toolCard[shadow="gray"] {
  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);
  &:hover {
    box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.5);
  }
}


================================================
FILE: components/ToolCard/index.js
================================================
import ToolCard from "./ToolCard";
export default ToolCard;


================================================
FILE: components/ToolPage/Description.jsx
================================================
import styles from "./Description.module.scss";

export default function Description(props) {
  return (
    <div className={styles.description}>
      <div className={styles.description__text}>{props.description}</div>
      {props.based && (
        <div className={styles.based}>
          <span>Based on</span>
          {props.based.map((tag) => (
            <span key={tag} className={styles.based__tag}>
              {tag}
            </span>
          ))}
        </div>
      )}
    </div>
  );
}


================================================
FILE: components/ToolPage/Description.module.scss
================================================
@import "/styles/variables";

.description {
  margin-top: 24px;
  &__text {
    font-size: 22px;
    line-height: 28px;
    color: $dark;
    font-style: normal;
    font-weight: normal;
  }
}
.based {
  display: flex;
  align-items: center;
  color: $dark-03;
  font-size: 16px;
  line-height: 20px;
  margin-top: 24px;

  &__tag {
    margin-left: 8px;
    color: #8381ee;
  }
}


================================================
FILE: components/ToolPage/DescriptionCards.jsx
================================================
import styles from "./DescriptionCards.module.scss";
import Card from "../Card/Card";

const getLicense = (props) => {
  let isOpen = false;
  let isPrice = false;
  let smallText = "";
  let icon = "/images/logo/proprietary.svg";
  let link = props?.links?.pricing;

  props?.licenses?.forEach((obj) => {
    if (obj.type === "open-source") {
      isOpen = true;
      smallText = obj.title;
      link = obj.link;
      icon = "/images/logo/open-source.svg";
    } else {
      isPrice = true;
      link = obj.link;
    }
  });

  if (isOpen && isPrice) {
    return {
      icons: ["/images/logo/proprietary.svg", "/images/logo/open-source.svg"],
      text: "Open-source and proprietary licenses",
      link: props?.links?.pricing || link,
      smallText: props?.links?.pricing ? "Priсing page →" : "License →",
    };
  }
  if (isOpen) {
    return {
      text: "Open-source license",
      smallText: `${smallText} →`,
      link,
      icon,
    };
  }
  if (isPrice) {
    return {
      text: "Proprietary license",
      link: props?.links?.pricing || link,
      smallText: props?.links?.pricing ? "Priсing page →" : "License →",
      icon,
    };
  }
};

const getFrameworks = (props) => {
  if (props?.frameworks?.length === 1) {
    let fr = props.frameworks[0];
    return {
      icon: `/images/logo/${fr.toLowerCase()}.svg`,
      text: `${fr === 'vanilla-js' ? 'Vanilla JS' : capitalizeFirstLetter(fr)} only`,
      link: `https://github.com/${props.slugs.github}`,
      smallText: `GitHub repository →`,
    };
  }

  let frameworksOnly = props.frameworks.filter((fr) => fr !== "vanilla-js");

  return {
    text: frameworksOnly.map((s, index) => {
      return (
        <span key={s}>
          {capitalizeFirstLetter(s)}
          {index === frameworksOnly.length - 1 ? " " : ", "}
        </span>
      );
    }),
    icons: props.frameworks.map((fr) => `/images/logo/${fr}.svg`),
    smallText: `GitHub repository →`,
    link: `https://github.com/${props.slugs.github}`,
  };
};

const getLanguage = (languages, slugs) => {
  let hasTS = languages.includes("TypeScript");
  let hasDT = slugs.npm_types !== undefined

  let icon = "/images/logo/javascript.svg";
  let text = "JavaScript only";
  let smallText = "No TypeScript support";
  let color = "orange";
  let link = undefined;

  if (hasTS) {
    icon = "/images/logo/typescript.svg";
    text = "TypeScript support";
    smallText = hasDT ? "DefinitelyTyped definitions →" : "*.d.ts files →";
    color = "gray";
    link = hasDT ? `https://www.npmjs.com/package/${slugs.npm_types}` : `https://github.com/search?q=repo%3A${encodeURIComponent(slugs.github)}+filename%3A.d.ts&type=Code`;
  }

  return {
    icon,
    text,
    smallText,
    color,
    link,
  };
};

export default function DescriptionCards(props) {
  return (
    <div className={styles.descriptionCards + " row"}>
      {props.licenses && (
        <div className={styles.cardWrap + " col-xl-4 col-lg-4 col-md-12"}>
          <Card height="full" {...getLicense(props)} />
        </div>
      )}
      {props.frameworks && props.slugs.github && (
        <div className={styles.cardWrap + " col-xl-4 col-lg-4 col-md-12"}>
          <Card height="full" color="gray" {...getFrameworks(props)} />
        </div>
      )}
      {props.languages && (
        <div className={styles.cardWrap + " col-xl-4 col-lg-4 col-md-12"}>
          <Card height="full" {...getLanguage(props.languages, props.slugs)} />
        </div>
      )}
    </div>
  );
}

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}


================================================
FILE: components/ToolPage/DescriptionCards.module.scss
================================================
.descriptionCards {
  margin-top: 40px;
  display: flex;
  margin-bottom: 104px;
  @media (max-width: 767.98px) {
    margin-bottom: 48px;
  }
}
.cardWrap {
  @media (max-width: 991.98px) {
    margin-bottom: 16px;
  }
}


================================================
FILE: components/ToolPage/Header.jsx
================================================
import styles from "./Header.module.scss";
import Button from "../Button";

export default function Header(props) {
  return (
    <div className={styles.header}>
      <div className={styles.title}>
        <img
          className={styles.title__img}
          src={`/images/logo/${props.logo}`}
          alt={`${props.title} logo`}
        />
        <h1 className={styles.title__text}>
          {props.title}
          {props.developer && (
            <span className={styles.title__developer}>
              &nbsp;by&nbsp;{props.developer}
            </span>
          )}
          {props.framework && (
            <span className={styles.title__framework}>
              &nbsp;for&nbsp;{props.framework}&nbsp;developers
            </span>
          )}
        </h1>
        {props.achievement && (
          <div>
            <img
              className={styles.achievement}
              src={`/images/${props.achievement}.svg`}
              alt="tool label"
            />
          </div>
        )}
      </div>
      <div className={styles.buttons}>
        {props.github && (
          <Button target="_blank" href={`https://github.com/${props.github}`}>
            GitHub
          </Button>
        )}
        {props.website && (
          <Button target="_blank" href={props.website}>
            Website
          </Button>
        )}
      </div>
    </div>
  );
}


================================================
FILE: components/ToolPage/Header.module.scss
================================================
@import "/styles/variables";

.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  @media (max-width: 767.98px) {
    flex-direction: column;
  }
}
.title {
  display: flex;
  position: relative;
  @media (max-width: 767.98px) {
    flex-wrap: wrap;
    margin-bottom: 16px;
    width: 100%;
  }
  &__img {
    border: 1px solid rgba(213, 213, 226, 0.5);
    border-radius: 24px;
    width: 77px;
    height: 77px;
  }
  &__text {
    display: flex;
    align-items: center;
    margin: 0 0 0 16px;
    font-size: 40px;
    line-height: 40px;
    color: $dark;
  }
  &__developer {
    color: $dark-03;
  }
  &__framework {
    color: $dark-03;
  }
}
.buttons {
  display: flex;
  a:first-child {
    margin-right: 8px;
  }
}

.achievement {
  margin-top: -56px;
  @media (max-width: 767.98px) {
    position: absolute;
    top: -56px;
    right: 0;
    margin: 0;
    // margin: 0;
    transform: scale3d(0.5, 0.5, 0.5);
  }
  // height: 104px;
  // width: 104px;
}


================================================
FILE: components/ToolPage/HowToGetHelp.jsx
================================================
import styles from "./HowToGetHelp.module.scss";
import GetHelpCard from "../GetHelpCard";
import H2 from "../Text/H2";
import abbreviateNumber from "../../utils/number";

export default function HowToGetHelp(props) {
  const cards = [
    {
      href: props.links.slack,
      title: `${props.name} Slack →`,
      icon: "/images/logo/slack-big.svg",
    },
    {
      href: props.links.docs,
      title: `${props.name} docs →`,
      icon: `/images/logo/${props.logo}`,
    },
    {
      href: props.stackoverflow,
      title: "Stack Overflow →",
      icon: "/images/logo/stackoverflow-64.svg",
      footer: `${abbreviateNumber(
        props?.stackoverflow_data?.questions_count
      )} questions`,
    },
    {
      href: "https://slack.cube.dev/",
      title: "Cube Slack →",
      icon: "/images/logo/slack-big.svg",
      footer: `${abbreviateNumber(props.slackMembers)} followers`,
    },
  ];
  return (
    <div className={styles.HowToGetHelp}>
      <div className="row mb-md">
        <div className={styles.textWrap + " col-lg-3"}>
          <H2>
            How to
            <br />
            Get Help
          </H2>
        </div>
        {cards
          .filter((card) => card.href)
          .map((card, index) => {
            let className = " col-lg-4";
            // if (index === 0) {
            //   className = "col-lg-4";
            // }
            if (index === 1) {
              className = " col-lg-5";
            }
            if (index === 2) {
              className = " col-lg-5 offset-lg-3";
            }
            // let className = " col-lg-5";
            // if (index % 2 === 0 && index !== 0) {
            //   className = " col-lg-5 offset-lg-3";
            // }
            // if (index % 2 !== 0) {
            //   className = " col-lg-4";
            // }
            return card.href ? (
              <div key={card.title} className={styles.cardWrap + className}>
                <GetHelpCard {...card} />
              </div>
            ) : null;
          })}
      </div>
    </div>
  );
}


================================================
FILE: components/ToolPage/HowToGetHelp.module.scss
================================================
.HowToGetHelp {
  margin-bottom: 104px;
  @media (max-width: 767.98px) {
    margin-bottom: 48px;
  }
}
.cardWrap {
  margin-bottom: 26px;
  @media (max-width: 991.98px) {
    margin-bottom: 24px;
  }
}
.textWrap {
  @media (max-width: 991.98px) {
    margin-bottom: 24px;
  }
}


================================================
FILE: components/ToolPage/HowToGetStarted.jsx
================================================
import styles from "./HowToGetStarted.module.scss";
import GetStartedCard from "../GetStartedCard";
import H2 from "../Text/H2";

export default function HowToGetStarted(props) {
  return (
    <div className={styles.HowToGetStarted + " row"}>
      <div className="col-sm-3">
        <H2>
          How to
          <br />Get Started
        </H2>
      </div>
      {props.content.map((obj, index) => {
        const icon =
          obj.type === "official"
            ? "/images/logo/official.svg"
            : "/images/logo/cubejs-big.svg";
          
        const className =
          styles.cardWrap + " " +
          (index === 0 ? "col-sm-5" : "col-sm-4") +
          (index !== 0 && index % 2 === 0 ? " offset-lg-3" : "");

        return (
          <div key={index} className={className}>
            <GetStartedCard
              icon={icon}
              type={obj.type === "official" ? "Official tutorial" : "Community guide"}
              title={obj.title}
              link={obj.link}
            />
          </div>
        );
      })}

      {/* <div className="col-sm-4">
        <GetStartedCard />
      </div> */}
    </div>
  );
}


================================================
FILE: components/ToolPage/HowToGetStarted.module.scss
================================================
.HowToGetStarted {
  margin-bottom: 104px;
}
.cardWrap {
  margin-bottom: 26px;
  @media (max-width: 991.98px) {
    margin-bottom: 24px;
  }
}

================================================
FILE: components/ToolPage/Integrations.jsx
================================================
import styles from "./Integrations.module.scss";
import Card from "../Card/Card";
import H2 from "../Text/H2";
import frameworks from '../../data/frameworks';

export default function Integrations(props) {
  const integrations = props.integrations || [ props.integration ]

  return (
    <div className={styles.integration + " row"}>
      <div className="col-lg-3">
        <H2>
          {props.integration ? frameworks[props.integration.framework].name : "Framework"} Support
        </H2>
      </div>
      <div className={styles.cards + " col-lg-9 row"}>
        {integrations.map(integration => {
          const framework = frameworks[integration.framework]
          const link = integration.links?.website
            ? integration.links.website
            : `https://github.com/${integration.slugs.github}`;

          return (
            <div className={styles.cardWrap + (props.integration ? " col-xl-12 col-lg-12 col-md-12" : " col-xl-6 col-lg-6 col-md-12")}>
              <Card
                key={integration.framework}
                link={link}
                icon={`/images/logo/${framework.icon}`}
                text={integration.slugs.npm}
                smallText={`${framework.name} components`}
              />
            </div>
          );
        })}
      </div>
    </div>
  );
}


================================================
FILE: components/ToolPage/Integrations.module.scss
================================================
.integration {
  margin-bottom: 104px;
  @media (max-width: 767.98px) {
    margin-bottom: 48px;
  }
}
.cards {
  display: flex;
}
.cardWrap {
  margin-bottom: 24px;
}

================================================
FILE: components/ToolPage/Popularity.jsx
================================================
import styles from "./Popularity.module.scss";
import Card from "../Card/Card";
import H2 from "../Text/H2";
import dayjs from "dayjs";
import abbreviateNumber from "../../utils/number";

export default function Popularity(props) {
  return (
    <div className={styles.popularity + " row"}>
      <div className="col-lg-3">
        <H2>
          Popularity
          <br />& Relevance
        </H2>
      </div>
      <div className={styles.bigCardWrap + " col-lg-3"}>
        <Card
          isBig={true}
          link={`https://github.com/${props?.slugs?.github}/stargazers`}
          color={
            props?.positions?.stars / props?.positions?.total > 0.67
              ? "orange"
              : null
          }
          icon="/images/logo/github-big.svg"
          text={abbreviateNumber(props?.github?.stars) || 0}
          description="GitHub stars"
          footerText={`${props?.positions?.stars} of ${props?.positions?.total} place`}
        />
      </div>
      <div className={styles.bigCardWrap + " col-lg-3"}>
        <Card
          isBig={true}
          color={props?.percentages?.stale_issues > 50 ? "orange" : null}
          link={`https://github.com/${props?.slugs?.github}/issues`}
          icon="/images/edit.svg"
          text={props?.github?.issues}
          description="open issues"
          footerText={`${props?.percentages?.stale_issues?.toFixed(
            0
          )}&thinsp;% older than 1 year`}
        />
      </div>
      <div className={styles.smallCardWrap + " col-lg-3"}>
        <Card
          link={`https://github.com/${props?.slugs?.github}/graphs/contributors`}
          className="mb-md"
          color="gray"
          text={abbreviateNumber(props?.github?.contributors)}
          description="contributors"
        />
        {props?.github?.last_release?.date && (
          <Card
            link={props?.github?.last_release?.link}
            color="gray"
            text={
              dayjs(props?.github?.last_release?.date).format(
                "MMM DD, YYYY"
              ) || "-"
            }
            description="last release date"
          />
        )}
      </div>
    </div>
  );
}


================================================
FILE: components/ToolPage/Popularity.module.scss
================================================
.popularity {
  margin-bottom: 104px;
  @media (max-width: 767.98px) {
    margin-bottom: 48px;
  }
}
.bigCardWrap {
  @media (max-width: 991.98px) {
    margin-top: 24px;
  }
}
.smallCardWrap {
  @media (max-width: 991.98px) {
    margin-top: 24px;
  }
}


================================================
FILE: components/ToolPage/ToolPage.jsx
================================================
import React from "react";
import dynamic from "next/dynamic";
import { NextSeo } from 'next-seo';
import Header from "./Header";
import Description from "./Description";
import DescriptionCards from "./DescriptionCards";

import useSlackMembers from "../../data/useSlackMembers";
import types from '../../data/types';
import Integrations from './Integrations';

const Gallery = dynamic(() => import("../Gallery"));
const Popularity = dynamic(() => import("./Popularity"));
const HowToGetStarted = dynamic(() => import("./HowToGetStarted"));
const HowToGetHelp = dynamic(() => import("./HowToGetHelp"));

export default function ToolPage(props) {
  const type = types[props.types[0]];
  const slackMembers = useSlackMembers();

  return (
    <>
      <NextSeo
        title={`${props.title} — ${type.descriptor}`}
        description={`${props.title} examples, tutorials, compatibility, and popularity`}
      />

      <div className="container custom-container mt-lg">
        <main>
          <Header
            logo={props.logo}
            title={props.title}
            developer={props.developer}
            website={props?.links?.website}
            github={props?.slugs?.github}
            achievement={props?.feature_label}
          />
          <Description based={props.based_on} description={props.description} />
          <DescriptionCards
            licenses={props.licenses}
            frameworks={props.frameworks}
            languages={props.languages}
            links={props.links}
            slugs={props.slugs}
          />
          {props.gallery && props.gallery.length !== 0 && (
            <Gallery gallery={props.gallery} link={props?.links?.examples} />
          )}
          {props.github_data && (
            <Popularity
              slugs={props.slugs}
              github={props.github_data}
              positions={props.positions}
              percentages={props.percentages}
            />
          )}
          {props.integrations?.length > 0 && (
            <Integrations integrations={props.integrations} />
          )}
          {props.content && props.content.length > 0 && (
            <HowToGetStarted content={props.content} />
          )}
          <HowToGetHelp
            slackMembers={slackMembers}
            logo={props.logo}
            name={props.title}
            links={props.links}
            positions={props.positions}
            stackoverflow={
              props?.tags?.stackoverflow
                ? `https://stackoverflow.com/questions/tagged/${encodeURIComponent(
                  props?.tags?.stackoverflow.join(" or "),
                )}`
                : null
            }
            stackoverflow_data={props.stackoverflow_data}
          />
        </main>
      </div>
    </>
  );
}

================================================
FILE: components/ToolPage/ToolPageForFramework.jsx
================================================
import React from "react";
import dynamic from "next/dynamic";
import { NextSeo } from 'next-seo';
import Header from "./Header";
import Description from "./Description";
import DescriptionCards from "./DescriptionCards";

import useSlackMembers from "../../data/useSlackMembers";
import frameworks from '../../data/frameworks';
import types from '../../data/types';
import Integrations from './Integrations';

const Gallery = dynamic(() => import("../Gallery"));
const Popularity = dynamic(() => import("./Popularity"));
const HowToGetStarted = dynamic(() => import("./HowToGetStarted"));
const HowToGetHelp = dynamic(() => import("./HowToGetHelp"));

export default function ToolPageForFramework(props) {
  const type = types[props.types[0]];
  const framework = frameworks[props.framework];
  const integration = props.integrations?.find(i => i.framework === props.framework);
  const slackMembers = useSlackMembers();

  return (
    <>
      <NextSeo
        title={`${props.title} — ${type.descriptor} for ${framework.name} developers`}
        description={`${props.title} support in ${framework.name}${integration && ` with ${integration.slugs.npm}`}, examples, tutorials, compatibility, and popularity`}
      />

      <div className="container custom-container mt-lg">
        <main>
          <Header
            logo={props.logo}
            title={props.title}
            framework={framework.name}
            developer={props.developer}
            website={props?.links?.website}
            github={props?.slugs?.github}
            achievement={props?.feature_label}
          />
          <Description description={props.description} />
          <DescriptionCards
            licenses={props.licenses}
            frameworks={props.frameworks}
            languages={props.languages}
            links={props.links}
            slugs={props.slugs}
          />
          {integration && (
            <Integrations integration={integration} />
          )}
          {props.gallery && props.gallery.length !== 0 && (
            <Gallery gallery={props.gallery} link={props?.links?.examples} />
          )}
          {props.github_data && (
            <Popularity
              slugs={props.slugs}
              github={props.github_data}
              positions={props.positions}
              percentages={props.percentages}
            />
          )}
          {props.content && props.content.length > 0 && (
            <HowToGetStarted content={props.content} />
          )}
          <HowToGetHelp
            slackMembers={slackMembers}
            logo={props.logo}
            name={props.title}
            links={props.links}
            positions={props.positions}
            stackoverflow={
              props?.tags?.stackoverflow
                ? `https://stackoverflow.com/questions/tagged/${encodeURIComponent(
                  props?.tags?.stackoverflow.join(" or "),
                )}`
                : null
            }
            stackoverflow_data={props.stackoverflow_data}
          />
        </main>
      </div>
    </>
  );
}

================================================
FILE: components/ToolsNumberControl/ToolsNumberControl.jsx
================================================
import styles from "./ToolsNumberControl.module.scss";
import { ReactSVG } from "react-svg";
export default function ToolsNumberControl(props) {
  let text = "awesome tools — and counting!";
  if (props.isChanged) {
    text = props.filteredTools.length === 1
      ? "awesome tool matching your criteria"
      : "awesome tools matching your criteria";
  }
  return (
    <div className={styles.toolsControl}>
      <div className={styles.toolsControl__text}>
        {props.filteredTools.length}&nbsp;{text}
      </div>
      {props.isChanged !== 0 && (
        <button
          className={styles.toolsControl__button}
          role="button"
          onClick={props.clearFilters}
        >
          <span>Clear filter</span>
          <ReactSVG
            wrapper="span"
            className={styles.clear}
            src="/images/clear.svg"
          />
        </button>
      )}
    </div>
  );
}


================================================
FILE: components/ToolsNumberControl/ToolsNumberControl.module.scss
================================================
@import "/styles/variables";

.toolsControl {
  min-height: 34px;
  display: flex;
  align-items: center;
  @media (max-width: 767.98px) {
    align-items: flex-start;
    flex-direction: column;
  }

  &__button {
    cursor: pointer;
    display: flex;
    align-items: center;
    font-family: CeraPro;
    margin-left: 16px;
    padding: 0px 12px;
    background: rgba(255, 193, 211, 0.24);
    border-radius: 20px;
    border: none;
    font-size: 20px;
    line-height: 30px;
    color: $pink-hover;

    @media (max-width: 767.98px) {
      margin-top: 4px;
      margin-left: 0;
      padding: 0px 8px;
      font-size: 16px;
    }
  }

  &__text {
    font-size: 20px;
    line-height: 30px;
    color: $dark-03;
    white-space: nowrap;

    @media (max-width: 767.98px) {
      font-size: 16px;
    }
  }
}
.clear {
  margin-left: 8px;
}


================================================
FILE: components/ToolsNumberControl/index.js
================================================
import ToolsNumberControl from "./ToolsNumberControl";
export default ToolsNumberControl;


================================================
FILE: copy/tools/.example
================================================
title: AG Grid
description: Self-proclaimed best JavaScript grid in the world
logo: ag-grid.svg
developer: Google

based_on:
  - d3

licenses:
  - type: open-source
    title: Apache 2.0
    link: https://github.com/apache/echarts/blob/master/LICENSE

types:
  - 3d
  - app
  - charts
  - grid
  - low-level
  - maps

renders:
  - svg
  - html
  - canvas

features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0

gallery:
  - /images/slider/reaflow-1.png
  - /images/slider/reaflow-2.png
  - /images/slider/reaflow-3.png
  - /images/slider/reaflow-4.png
  - /images/slider/reaflow-5.png

languages:
  - JavaScript
  - TypeScript

frameworks:
  - vanilla-js
  - react
  - angular
  - vue
  - svelte

slugs:
  github: ag-grid/ag-grid
  npm: ag-grid-community
  npm_types: "@types/mapbox-gl"

tags:
  stackoverflow:
    - ag-grid
    - aggrid
  twitter:
    - aggrid
    - ag_grid

links:
  website: https://www.ag-grid.com
  examples: https://www.ag-grid.com/example.php
  docs: https://www.ag-grid.com/javascript-grid/
  pricing: null
  slack: https://slack.example.com

content:
  - type: official
    title: "JavaScript Grid: Get Started with AG Grid"
    link: https://www.ag-grid.com/javascript-grid/getting-started/
  - type: cube
    title: React Pivot Table with AG Grid and Cube.js
    link: https://react-pivot-table.cube.dev

github_data:
  stars: 7200
  contributors: 84
  issues: 17
  stale_issues: 0
  last_release:
    date: "2021-04-30T00:00:00Z"
    link: https://github.com/ag-grid/ag-grid/releases/tag/v25.2.0

stackoverflow_data:
  questions_count: 37620

================================================
FILE: copy/tools/.extended.example
================================================
# Everything from .example and also the following fields

positions:
  total: 45
  stars: 3

percentages:
  stale_issues: 32

================================================
FILE: copy/tools/ag-grid.yml
================================================
title: AG Grid
description: Self-proclaimed best JavaScript grid in the world
logo: ag-grid.svg
based_on: null
licenses:
  - type: proprietary
  - type: open-source
    title: MIT
types:
  - grid
renders:
  - html
features:
  easy-to-customize: 1
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/ag-grid-1.png
  - /images/slider/ag-grid-2.png
  - /images/slider/ag-grid-3.png
  - /images/slider/ag-grid-5.png
  - /images/slider/ag-grid-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: ag-grid/ag-grid
  npm: ag-grid-community
tags:
  stackoverflow:
    - ag-grid
  twitter:
    - aggrid
    - ag_grid
links:
  website: 'https://www.ag-grid.com'
  examples: 'https://www.ag-grid.com/example.php'
  docs: 'https://www.ag-grid.com/javascript-grid/'
  pricing: 'https://www.ag-grid.com/license-pricing.php'
  slack: null
content:
  - type: official
    title: 'JavaScript Grid: Get Started with AG Grid'
    link: 'https://www.ag-grid.com/javascript-grid/getting-started/'
  - type: cube
    title: React Pivot Table with AG Grid and Cube.js
    link: 'https://react-pivot-table.cube.dev'
github_data:
  stars: 13513
  contributors: 193
  issues: 39
  stale_issues: 1
  last_release:
    date: '2025-02-20T08:36:33Z'
    link: 'https://github.com/ag-grid/ag-grid/releases/tag/v33.1.1'
stackoverflow_data:
  questions_count: 5142


================================================
FILE: copy/tools/amcharts.yml
================================================
title: amCharts
description: JavaScript charts & maps for all data visualization needs
logo: amcharts.svg
based_on: null
licenses:
  - type: proprietary
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/amcharts-1.png
  - /images/slider/amcharts-2.png
  - /images/slider/amcharts-3.png
  - /images/slider/amcharts-4.png
  - /images/slider/amcharts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: amcharts/amcharts4
  npm: '@amcharts/amcharts4'
tags:
  stackoverflow:
    - amcharts
    - amcharts4
  twitter:
    - amcharts
    - amcharts4
links:
  website: 'https://www.amcharts.com'
  examples: 'https://www.amcharts.com/demos/'
  docs: 'https://www.amcharts.com/docs/v4/'
  pricing: 'https://www.amcharts.com/online-store/'
  slack: null
content:
  - type: official
    title: Starting from Basics of amCharts 4
    link: 'https://www.amcharts.com/docs/v4/getting-started/basics/'
github_data:
  stars: 1157
  contributors: 6
  issues: 31
  stale_issues: 30
  last_release:
    date: '2024-06-18T09:36:19Z'
    link: 'https://github.com/amcharts/amcharts4/releases/tag/4.10.39'
stackoverflow_data:
  questions_count: 3221


================================================
FILE: copy/tools/ant-design-charts.yml
================================================
title: Ant Design Charts
description: 'React charting library, based on G2Plot, G6, X6, L7'
logo: antv.svg
developer: AntV
based_on:
  - g2plot
  - g6
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/ant-design/ant-design-charts/blob/master/LICENSE'
types:
  - charts
  - maps
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 1
gallery:
  - /images/slider/ant-design-charts-1.png
  - /images/slider/ant-design-charts-2.png
  - /images/slider/ant-design-charts-3.png
  - /images/slider/ant-design-charts-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: ant-design/ant-design-charts
  npm: '@an-design/charts'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://charts.ant.design/en'
  examples: 'https://charts.ant.design/en/examples/gallery'
  docs: 'https://charts.ant.design/en/docs/manual/introduction'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://charts.ant.design/en/docs/manual/getting-started'
github_data:
  stars: 2001
  contributors: 72
  issues: 336
  stale_issues: 156
  last_release:
    date: '2024-12-13T09:23:24Z'
    link: 'https://github.com/ant-design/ant-design-charts/releases/tag/2.2.5'
stackoverflow_data: null


================================================
FILE: copy/tools/anychart.yml
================================================
title: AnyChart
description: Interactive JavaScript charts
logo: anychart.svg
developer: null
based_on: null
licenses:
  - type: proprietary
    link: 'https://www.anychart.com/support/pages/faq/'
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/anychart-1.png
  - /images/slider/anychart-2.png
  - /images/slider/anychart-3.png
  - /images/slider/anychart-4.png
  - /images/slider/anychart-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: AnyChart/AnyChart
  npm: anychart
tags:
  stackoverflow:
    - anychart
  twitter:
    - AnyChart
links:
  website: 'https://www.anychart.com'
  examples: 'https://www.anychart.com/products/anychart/gallery/'
  docs: 'https://www.anychart.com/products/anychart/docs/'
  pricing: 'https://www.anychart.com/buy/'
  slack: null
content:
  - type: official
    title: Getting Started with AnyChart
    link: 'https://github.com/AnyChart/AnyChart#getting-started'
  - type: official
    title: Chartopedia
    link: 'https://www.anychart.com/chartopedia/usage-type/'
github_data:
  stars: 383
  contributors: 21
  issues: 18
  stale_issues: 13
  last_release:
    date: '2024-09-25T05:29:05Z'
    link: 'https://github.com/AnyChart/AnyChart/releases/tag/v8.13.0'
stackoverflow_data:
  questions_count: 474


================================================
FILE: copy/tools/apexcharts.yml
================================================
title: ApexCharts
description: Modern & interactive open-source charts
logo: apexcharts.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/apexcharts/apexcharts.js/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/apexcharts-1.png
  - /images/slider/apexcharts-2.png
  - /images/slider/apexcharts-3.png
  - /images/slider/apexcharts-4.png
  - /images/slider/apexcharts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
  - svelte
slugs:
  github: apexcharts/apexcharts.js
  npm: apexcharts
tags:
  stackoverflow:
    - apexcharts
  twitter:
    - ApexCharts
links:
  website: 'https://apexcharts.com'
  examples: 'https://apexcharts.com/javascript-chart-demos/'
  docs: 'https://apexcharts.com/docs/installation/'
  pricing: null
  slack: null
content:
  - type: official
    title: Creating your first JavaScript chart
    link: 'https://apexcharts.com/docs/creating-first-javascript-chart/'
github_data:
  stars: 14647
  contributors: 224
  issues: 297
  stale_issues: 218
  last_release:
    date: '2025-02-19T11:09:43Z'
    link: 'https://github.com/apexcharts/apexcharts.js/releases/tag/v4.5.0'
stackoverflow_data:
  questions_count: 1087


================================================
FILE: copy/tools/appsmith.yml
================================================
title: Appsmith
description: Low-code tool for building internal apps using pre-built UI widgets
logo: appsmith.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/appsmithorg/appsmith/blob/release/LICENSE'
types:
  - app
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/appsmith-1.png
  - /images/slider/appsmith-2.png
  - /images/slider/appsmith-3.png
  - /images/slider/appsmith-5.png
  - /images/slider/appsmith-5.png
languages: null
frameworks: null
slugs:
  github: appsmithorg/appsmith
  npm: null
  npm_types: null
tags:
  stackoverflow:
    - appsmith
  twitter:
    - appsmith
links:
  website: 'https://www.appsmith.com'
  examples: 'https://www.appsmith.com/widgets'
  docs: 'https://docs.appsmith.com/'
  pricing: 'https://www.appsmith.com/pricing'
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://docs.appsmith.com/#getting-started-with-appsmith'
  - type: cube
    title: Building an Appsmith Dashboard with Cube
    link: 'https://cube.dev/blog/building-an-appsmith-dashboard-with-cube'
github_data:
  stars: 35807
  contributors: 366
  issues: 4138
  stale_issues: 2524
  last_release:
    date: '2025-02-19T09:48:52Z'
    link: 'https://github.com/appsmithorg/appsmith/releases/tag/v1.62'
stackoverflow_data:
  questions_count: 27


================================================
FILE: copy/tools/billboard.yml
================================================
title: Billboard.js
description: 'Re-usable, easy interface JavaScript chart library based on D3.js'
logo: billboard.svg
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/naver/billboard.js/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/billboard-1.png
  - /images/slider/billboard-2.png
  - /images/slider/billboard-3.png
  - /images/slider/billboard-4.png
  - /images/slider/billboard-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
slugs:
  github: naver/billboard.js
  npm: billboard.js
tags:
  stackoverflow:
    - billboard.js
  twitter:
    - BillboardJS
links:
  website: 'https://naver.github.io/billboard.js/'
  examples: 'https://naver.github.io/billboard.js/demo/'
  docs: 'https://naver.github.io/billboard.js/release/latest/doc/'
  pricing: null
  slack: null
content: null
github_data:
  stars: 5878
  contributors: 190
  issues: 146
  stale_issues: 139
  last_release:
    date: '2025-01-07T08:55:27Z'
    link: 'https://github.com/naver/billboard.js/releases/tag/3.14.3'
stackoverflow_data:
  questions_count: 66


================================================
FILE: copy/tools/c3.yml
================================================
title: C3.js
description: D3.js-based reusable chart library
logo: c3.svg
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/c3js/c3/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/c3-1.png
  - /images/slider/c3-2.png
  - /images/slider/c3-3.png
  - /images/slider/c3-4.png
  - /images/slider/c3-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: c3js/c3
  npm: c3
  npm_types: '@types/c3'
tags:
  stackoverflow:
    - c3.js
  twitter:
    - c3js
links:
  website: 'https://c3js.org'
  examples: 'https://c3js.org/examples.html'
  docs: 'https://c3js.org/reference.html'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started with c3.js
    link: 'https://c3js.org/gettingstarted.html'
github_data:
  stars: 9347
  contributors: 169
  issues: 726
  stale_issues: 723
  last_release:
    date: '2020-08-08T09:14:36Z'
    link: 'https://github.com/c3js/c3/releases/tag/v0.7.20'
stackoverflow_data:
  questions_count: 1116


================================================
FILE: copy/tools/chartist.yml
================================================
title: Chartist
description: Simple responsive SVG charts
logo: chartist.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/chartist-js/chartist/blob/main/LICENSE-MIT'
  - type: open-source
    title: WTFPL
    link: 'https://github.com/gionkunz/chartist-js/blob/main/LICENSE-WTFPL'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 1
  easy-to-start-with: 2
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/chartist-1.png
  - /images/slider/chartist-2.png
  - /images/slider/chartist-3.png
  - /images/slider/chartist-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: chartist-js/chartist
  npm: chartist
tags:
  stackoverflow:
    - chartist.js
links:
  website: 'https://gionkunz.github.io/chartist-js/'
  examples: 'https://gionkunz.github.io/chartist-js/examples.html'
  docs: 'https://gionkunz.github.io/chartist-js/api-documentation.html'
  pricing: null
content:
  - type: official
    title: A quick start guide for Chartist
    link: 'https://github.com/chartist-js/chartist#quickstart'
github_data:
  stars: 13360
  contributors: 89
  issues: 198
  stale_issues: 197
  last_release:
    date: '2022-11-03T11:45:38Z'
    link: 'https://github.com/chartist-js/chartist/releases/tag/v1.3.0'
stackoverflow_data:
  questions_count: 235


================================================
FILE: copy/tools/chartjs.yml
================================================
title: Chart.js
description: Simple yet flexible JavaScript charting for designers & developers
logo: chartjs.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/chartjs/Chart.js/blob/master/LICENSE.md'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 2
  easy-to-start-with: 3
  full-fledged: 0
  very-popular: 1
  well-documented: 1
gallery:
  - /images/slider/chartjs-1.png
  - /images/slider/chartjs-2.png
  - /images/slider/chartjs-3.png
  - /images/slider/chartjs-4.png
  - /images/slider/chartjs-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: chartjs/Chart.js
  npm: chart.js
tags:
  stackoverflow:
    - chart.js
    - react-chartjs
    - react-chartjs-2
  twitter:
    - chartjs
links:
  website: 'https://www.chartjs.org'
  examples: 'https://www.chartjs.org/docs/latest/samples/bar/vertical.html'
  docs: 'https://www.chartjs.org/docs/latest/'
  pricing: null
  slack: 'https://chartjs-slack.herokuapp.com'
content:
  - type: official
    title: Awesome Chart.js — a curated list of things related to Chart.js
    link: 'https://github.com/chartjs/awesome'
  - type: cube
    title: Chart.js Example with Dynamic Dataset
    link: 'https://cube.dev/blog/chart-js-example-with-dynamic-dataset/'
github_data:
  stars: 65416
  contributors: 514
  issues: 442
  stale_issues: 331
  last_release:
    date: '2025-02-19T15:45:55Z'
    link: 'https://github.com/chartjs/Chart.js/releases/tag/v4.4.8'
stackoverflow_data:
  questions_count: 13463
integrations:
  - framework: react
    slugs:
      github: reactchartjs/react-chartjs-2
      npm: react-chartjs-2
    links:
      website: 'https://react-chartjs-2.js.org'
  - framework: angular
    slugs:
      github: valor-software/ng2-charts
      npm: ng2-charts
    links:
      website: 'https://valor-software.com/ng2-charts/'
  - framework: vue
    slugs:
      github: apertureless/vue-chartjs
      npm: vue-chartjs
    links:
      website: 'https://vue-chartjs.org'
  - framework: svelte
    slugs:
      github: SauravKanchan/svelte-chartjs
      npm: svelte-chartjs
    links:
      website: 'https://saurav.tech/mdbsvelte/?path=/story/charts--examples'


================================================
FILE: copy/tools/cytoscape.yml
================================================
title: Cytoscape.js
description: Graph theory (network) library for visualisation and analysis
logo: cytoscape.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/cytoscape/cytoscape.js/blob/unstable/LICENSE'
types:
  - low-level
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/cytoscape-1.png
  - /images/slider/cytoscape-2.png
  - /images/slider/cytoscape-3.png
  - /images/slider/cytoscape-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: cytoscape/cytoscape.js
  npm: cytoscape
  npm_types: '@types/cytoscape'
tags:
  stackoverflow:
    - cytoscape.js
  twitter: null
links:
  website: 'https://js.cytoscape.org'
  examples: 'https://js.cytoscape.org/#demos'
  docs: 'https://js.cytoscape.org/#notation'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://js.cytoscape.org/#getting-started'
github_data:
  stars: 10279
  contributors: 155
  issues: 14
  stale_issues: 2
  last_release:
    date: '2025-02-26T19:47:13Z'
    link: 'https://github.com/cytoscape/cytoscape.js/releases/tag/v3.31.1'
stackoverflow_data:
  questions_count: 1283


================================================
FILE: copy/tools/d3.yml
================================================
title: D3.js
description: JavaScript library for manipulating documents based on data
logo: d3.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: BSD
    link: 'https://github.com/d3/d3/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
  - html
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 2
  very-popular: 1
  well-documented: 0
gallery:
  - /images/slider/d3-1.png
  - /images/slider/d3-2.png
  - /images/slider/d3-3.png
  - /images/slider/d3-4.png
  - /images/slider/d3-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: d3/d3
  npm: d3
  npm_types: '@types/d3'
tags:
  stackoverflow:
    - d3.js
  twitter:
    - D3js
links:
  website: 'https://d3js.org'
  examples: 'https://observablehq.com/@d3/gallery'
  docs: 'https://github.com/d3/d3/wiki'
  pricing: null
  slack: 'https://d3-slackin.herokuapp.com'
content:
  - type: official
    title: 'Learn D3: Introduction'
    link: 'https://observablehq.com/@d3/learn-d3'
  - type: cube
    title: D3 Dashboard Tutorial
    link: 'https://d3-dashboard.cube.dev'
github_data:
  stars: 109948
  contributors: 152
  issues: 9
  stale_issues: 6
  last_release:
    date: '2024-03-12T22:18:19Z'
    link: 'https://github.com/d3/d3/releases/tag/v7.9.0'
stackoverflow_data:
  questions_count: 39316


================================================
FILE: copy/tools/datasette.yml
================================================
title: Datasette
description: Open-source multi-tool for exploring and publishing data
logo: datasette.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/simonw/datasette/blob/main/LICENSE'
types:
  - app
renders: null
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/datasette-1.png
  - /images/slider/datasette-2.png
  - /images/slider/datasette-3.png
  - /images/slider/datasette-4.png
languages: null
frameworks: null
slugs:
  github: simonw/datasette
  npm: null
  npm_types: null
tags:
  stackoverflow:
    - datasette
  twitter: null
links:
  website: 'https://datasette.io'
  examples: 'https://datasette.io/examples'
  docs: 'https://docs.datasette.io/en/stable/'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://docs.datasette.io/en/stable/getting_started.html'
github_data:
  stars: 9831
  contributors: 81
  issues: 565
  stale_issues: 500
  last_release:
    date: '2025-02-06T19:14:10Z'
    link: 'https://github.com/simonw/datasette/releases/tag/1.0a17'
stackoverflow_data:
  questions_count: 4


================================================
FILE: copy/tools/deck-gl.yml
================================================
title: deck.gl
description: WebGL-powered visualization framework for large-scale datasets
logo: deck-gl.svg
developer: Uber
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/visgl/deck.gl/blob/master/LICENSE'
types:
  - low-level
  - maps
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/deck-gl-1.jpg
  - /images/slider/deck-gl-2.jpg
  - /images/slider/deck-gl-3.jpg
  - /images/slider/deck-gl-4.jpg
  - /images/slider/deck-gl-5.jpg
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - vue
slugs:
  github: visgl/deck.gl
  npm: deck.gl
  npm_types: '@danmarshall/deckgl-typings'
tags:
  stackoverflow:
    - deck.gl
  twitter:
    - deckgl
links:
  website: 'https://deck.gl'
  examples: 'https://deck.gl/examples'
  docs: 'https://deck.gl/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://deck.gl/docs/get-started/using-standalone'
github_data:
  stars: 12524
  contributors: 283
  issues: 350
  stale_issues: 226
  last_release:
    date: '2025-02-27T07:02:11Z'
    link: 'https://github.com/visgl/deck.gl/releases/tag/v9.1.4'
stackoverflow_data:
  questions_count: 258


================================================
FILE: copy/tools/echarts.yml
================================================
title: Apache ECharts
description: Open-source JavaScript visualization library
logo: echarts.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/apache/echarts/blob/master/LICENSE'
types:
  - charts
  - maps
  - 3d
renders:
  - svg
  - canvas
features:
  easy-to-customize: 2
  easy-to-start-with: 1
  full-fledged: 2
  very-popular: 0
  well-documented: 2
gallery:
  - /images/slider/echarts-1.png
  - /images/slider/echarts-2.png
  - /images/slider/echarts-3.png
  - /images/slider/echarts-4.png
  - /images/slider/echarts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: apache/echarts
  npm: ag-grid-community
  npm_types: '@types/echarts'
tags:
  stackoverflow:
    - echarts
  twitter:
    - ECharts
links:
  website: 'https://echarts.apache.org/en/index.html'
  examples: 'https://echarts.apache.org/examples/en/index.html'
  docs: 'https://echarts.apache.org/en/api.html#echarts'
  pricing: null
  slack: null
content:
  - type: official
    title: Get started with ECharts in 5 minutes
    link: >-
      https://echarts.apache.org/en/tutorial.html#Get%20Started%20with%20ECharts%20in%205%20minutes
  - type: cube
    title: Building an Apache ECharts dashboard with React and Cube
    link: >-
      https://cube.dev/blog/building-an-apache-echarts-dashboard-with-react-and-cube/
  - type: cube
    title: Building an Apache ECharts Dashboard with Angular and Cube
    link: >-
      https://cube.dev/blog/building-an-apache-echarts-dashboard-with-angular-and-cube/
  - type: cube
    title: Building an Apache ECharts Dashboard with Vue 3 and Cube
    link: >-
      https://cube.dev/blog/building-an-apache-echarts-dashboard-with-vue-3-and-cube/
github_data:
  stars: 61997
  contributors: 293
  issues: 2029
  stale_issues: 1406
  last_release:
    date: '2024-12-28T06:52:31Z'
    link: 'https://github.com/apache/echarts/releases/tag/5.6.0'
stackoverflow_data:
  questions_count: 1480
integrations:
  - framework: react
    slugs:
      github: hustcc/echarts-for-react
      npm: echarts-for-react
    links:
      website: 'https://git.hust.cc/echarts-for-react/'
  - framework: angular
    slugs:
      github: xieziyu/ngx-echarts
      npm: ngx-echarts
    links:
      website: 'https://xieziyu.github.io/ngx-echarts/'
  - framework: vue
    slugs:
      github: ecomfe/vue-echarts
      npm: vue-echarts
    links:
      website: 'https://vue-echarts.dev'


================================================
FILE: copy/tools/flot.yml
================================================
title: Flot
description: Attractive JavaScript charts for jQuery
logo: flot.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/flot/flot/blob/master/LICENSE.txt'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
slugs:
  github: flot/flot
  npm: flot
  npm_types: '@types/flot'
tags:
  stackoverflow:
    - flot
  twitter: null
links:
  website: 'http://www.flotcharts.org'
  examples: 'http://www.flotcharts.org/flot/examples/'
  docs: 'https://github.com/flot/flot/blob/master/API.md'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://github.com/flot/flot/blob/master/README.md#installation'
github_data:
  stars: 5940
  contributors: 93
  issues: 457
  stale_issues: 453
  last_release:
    date: '2014-04-21T20:53:45Z'
    link: 'https://github.com/flot/flot/releases/tag/v0.8.3'
stackoverflow_data:
  questions_count: 2059


================================================
FILE: copy/tools/frappe.yml
================================================
title: Frappe
description: >-
  GitHub-inspired simple and modern SVG charts for the web with zero
  dependencies
logo: frappe.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/frappe/charts/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
frameworks:
  - vanilla-js
  - react
  - vue
  - svelte
slugs:
  github: frappe/charts
  npm: frappe-charts
tags:
  stackoverflow:
    - frappe
  twitter: null
links:
  website: 'https://frappe.io/charts'
  examples: 'https://frappe.io/charts'
  docs: 'https://frappe.io/charts/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://frappe.io/charts/docs'
github_data:
  stars: 14984
  contributors: 55
  issues: 125
  stale_issues: 122
  last_release:
    date: '2022-04-27T10:43:31Z'
    link: 'https://github.com/frappe/charts/releases/tag/v1.6.3'
stackoverflow_data:
  questions_count: 220


================================================
FILE: copy/tools/fusioncharts.yml
================================================
title: FusionCharts
description: JavaScript charts for web & mobile
logo: fusioncharts.svg
developer: null
based_on: null
licenses:
  - type: proprietary
    link: >-
      https://www.ideracorp.com/Legal/FusionCharts/MasterISVSoftwareSubscriptionAgreement
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/fusioncharts-1.png
  - /images/slider/fusioncharts-2.png
  - /images/slider/fusioncharts-3.png
  - /images/slider/fusioncharts-4.png
  - /images/slider/fusioncharts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
  - svelte
slugs:
  github: fusioncharts/fusioncharts-dist
  npm: fusioncharts
  npm_types: '@types/fusioncharts'
tags:
  stackoverflow:
    - fusioncharts
  twitter:
    - FusionCharts
links:
  website: 'https://www.fusioncharts.com/fusioncharts'
  examples: 'https://www.fusioncharts.com/charts'
  docs: 'https://www.fusioncharts.com/dev/fusioncharts'
  pricing: 'https://www.fusioncharts.com/buy'
  slack: null
content:
  - type: official
    title: Create a Chart Using FusionCharts
    link: >-
      https://www.fusioncharts.com/dev/getting-started/plain-javascript/your-first-chart-using-plain-javascript
github_data:
  stars: 85
  contributors: 9
  issues: 40
  stale_issues: 34
  last_release:
    date: '2024-11-12T14:58:42Z'
    link: 'https://github.com/fusioncharts/fusioncharts-dist/releases/tag/4.1.0'
stackoverflow_data:
  questions_count: 799


================================================
FILE: copy/tools/g2.yml
================================================
title: G2
description: Highly interactive data-driven visualization grammar for statistical charts
logo: antv.svg
developer: AntV
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/antvis/G2/blob/master/LICENSE'
types:
  - charts
  - maps
renders:
  - svg
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 1
gallery:
  - /images/slider/g2-1.png
  - /images/slider/g2-2.png
  - /images/slider/g2-3.png
  - /images/slider/g2-4.png
  - /images/slider/g2-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: antvis/G2
  npm: '@antv/g2'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://g2.antv.vision/en'
  examples: 'https://g2.antv.vision/en/examples/gallery'
  docs: 'https://g2.antv.vision/en/docs/manual/about-g2'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://g2.antv.vision/en/docs/manual/getting-started'
github_data:
  stars: 12209
  contributors: 207
  issues: 214
  stale_issues: 80
  last_release:
    date: '2025-02-11T08:23:42Z'
    link: 'https://github.com/antvis/G2/releases/tag/5.2.11'
stackoverflow_data: null


================================================
FILE: copy/tools/g2plot.yml
================================================
title: G2Plot
description: Interactive and responsive charting library based on the grammar of graphics
logo: antv.svg
developer: AntV
based_on:
  - g2
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/antvis/G2Plot/blob/master/LICENSE'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 1
gallery:
  - /images/slider/g2plot-1.png
  - /images/slider/g2plot-2.png
  - /images/slider/g2plot-3.png
  - /images/slider/g2plot-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - vue
slugs:
  github: antvis/G2Plot
  npm: '@antv/g2plot'
tags:
  stackoverflow:
    - g2plot
  twitter:
    - G2Plot
links:
  website: 'https://g2plot.antv.vision/en'
  examples: 'https://g2plot.antv.vision/en/examples/gallery'
  docs: 'https://g2plot.antv.vision/en/docs/manual/introduction'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://g2plot.antv.vision/en/docs/manual/getting-started'
github_data:
  stars: 2584
  contributors: 67
  issues: 438
  stale_issues: 393
  last_release:
    date: '2024-07-30T08:47:03Z'
    link: 'https://github.com/antvis/G2Plot/releases/tag/2.4.32'
stackoverflow_data:
  questions_count: 10


================================================
FILE: copy/tools/g6.yml
================================================
title: G6
description: Graph visualization engine with simplicity and convenience
logo: antv.svg
developer: AntV
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/antvis/G6/blob/master/LICENSE'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 1
gallery:
  - /images/slider/g6-1.png
  - /images/slider/g6-2.png
  - /images/slider/g6-3.png
  - /images/slider/g6-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: antvis/G6
  npm: '@antv/g6'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://g6.antv.vision/en'
  examples: 'https://g6.antv.vision/en/examples/gallery'
  docs: 'https://g6.antv.vision/en/docs/manual/introduction'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://g6.antv.vision/en/docs/manual/getting-started'
github_data:
  stars: 11338
  contributors: 171
  issues: 158
  stale_issues: 3
  last_release:
    date: '2025-02-14T08:55:41Z'
    link: 'https://github.com/antvis/G6/releases/tag/5.0.43'
stackoverflow_data: null


================================================
FILE: copy/tools/google-charts.yml
================================================
title: Google Charts
description: Interactive charts for browsers and mobile devices
logo: google-charts.png
developer: null
based_on: null
licenses:
  - type: proprietary
    link: 'https://developers.google.com/chart/terms'
types:
  - charts
  - maps
renders:
  - svg
  - html
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/google-charts-1.png
  - /images/slider/google-charts-2.png
  - /images/slider/google-charts-3.png
  - /images/slider/google-charts-4.png
  - /images/slider/google-charts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  npm_types: '@types/google.visualization'
tags:
  stackoverflow:
    - google-visualization
  twitter:
    - googlecharts
links:
  website: 'https://developers.google.com/chart'
  examples: 'https://developers.google.com/chart/interactive/docs/gallery'
  docs: 'https://developers.google.com/chart/interactive/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://developers.google.com/chart/interactive/docs/quick_start'
  - type: cube
    title: "Google Charts Dashboard: a Tutorial with an Artistic Touch of MoMA \U0001F5BC"
    link: 'https://cube.dev/blog/google-charts-dashboard/'
  - type: cube
    title: Building a Dashboard with a React Wrapper for Google Charts
    link: 'https://cube.dev/blog/react-google-charts-dashboard/'
github_data: null
stackoverflow_data:
  questions_count: 9023
integrations:
  - framework: react
    slugs:
      github: RakanNimer/react-google-charts
      npm: react-google-charts
    links:
      website: 'https://react-google-charts.com'
  - framework: angular
    slugs:
      github: FERNman/angular-google-charts
      npm: angular-google-charts
    links:
      website: null
  - framework: vue
    slugs:
      github: devstark-com/vue-google-charts
      npm: vue-google-charts
    links:
      website: null


================================================
FILE: copy/tools/highcharts.yml
================================================
title: Highcharts
description: Modern SVG-based multi-platform charting library
logo: highcharts.svg
developer: null
based_on: null
licenses:
  - type: proprietary
    license: 'https://github.com/highcharts/highcharts/blob/master/license.txt'
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 1
  easy-to-start-with: 0
  full-fledged: 1
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/highcharts-1.png
  - /images/slider/highcharts-2.png
  - /images/slider/highcharts-3.png
  - /images/slider/highcharts-4.png
  - /images/slider/highcharts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: highcharts/highcharts
  npm: highcharts
tags:
  stackoverflow:
    - highcharts
  twitter:
    - highcharts
links:
  website: 'https://www.highcharts.com'
  examples: 'https://www.highcharts.com/demo'
  docs: 'https://www.highcharts.com/docs/index'
  pricing: 'https://shop.highsoft.com'
  slack: null
content:
  - type: cube
    title: React Highcharts Example with Cube.js
    link: 'https://cube.dev/blog/react-highcharts-example/'
github_data:
  stars: 12176
  contributors: 264
  issues: 849
  stale_issues: 465
  last_release:
    date: null
    link: null
stackoverflow_data:
  questions_count: 26238


================================================
FILE: copy/tools/kepler-gl.yml
================================================
title: Kepler.gl
description: Open-source geospatial analysis tool for large-scale data sets
logo: kepler-gl.svg
developer: Uber
based_on:
  - mapbox-gl
  - deck-gl
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/keplergl/kepler.gl/blob/master/LICENSE'
types:
  - maps
renders:
  - svg
  - html
  - canvas
  - webgl
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
slugs:
  github: keplergl/kepler.gl
  npm: kepler.gl
tags:
  stackoverflow:
    - kepler.gl
  twitter:
    - KeplerGL
links:
  website: 'https://kepler.gl'
  examples: 'https://docs.kepler.gl/examples'
  docs: 'https://docs.kepler.gl/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://vis.academy/#/kepler.gl/setup'
  - type: community
    title: Exploring Geospatial Data with Kepler.gl
    link: >-
      https://medium.com/vis-gl/exploring-geospatial-data-with-kepler-gl-cf655839628f
github_data:
  stars: 10596
  contributors: 130
  issues: 498
  stale_issues: 444
  last_release:
    date: '2025-01-29T16:00:29Z'
    link: 'https://github.com/keplergl/kepler.gl/releases/tag/v3.1.0'
stackoverflow_data:
  questions_count: 77


================================================
FILE: copy/tools/laue.yml
================================================
title: Laue
description: Modern charts for Vue.js
logo: laue.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/QingWei-Li/laue/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/laue-1.png
  - /images/slider/laue-2.png
  - /images/slider/laue-3.png
  - /images/slider/laue-4.png
  - /images/slider/laue-5.png
languages:
  - JavaScript
frameworks:
  - vue
slugs:
  github: qingwei-li/laue
  npm: laue
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://laue.js.org'
  examples: 'https://laue.js.org/examples'
  docs: 'https://laue.js.org/api'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick start with Laue
    link: 'https://laue.js.org/guide#quick-started'
github_data:
  stars: 263
  contributors: 8
  issues: 15
  stale_issues: 15
  last_release:
    date: '2018-10-31T15:52:54Z'
    link: 'https://github.com/QingWei-Li/laue/releases/tag/v0.2.0'
stackoverflow_data: null


================================================
FILE: copy/tools/layer-cake.yml
================================================
title: Layer Cake
description: Graphics framework for Svelte
logo: layer-cake.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/mhkeller/layercake/blob/master/LICENSE'
types:
  - charts
  - low-level
  - maps
renders:
  - svg
  - html
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
frameworks:
  - svelte
slugs:
  github: mhkeller/layercake
  npm: layercake
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://layercake.graphics'
  examples: 'https://layercake.graphics'
  docs: 'https://layercake.graphics/guide'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://layercake.graphics/guide#getting-started'
github_data:
  stars: 1516
  contributors: 11
  issues: 7
  stale_issues: 2
  last_release:
    date: '2024-10-19T23:08:21Z'
    link: 'https://github.com/mhkeller/layercake/releases/tag/v8.4.0'
stackoverflow_data: null


================================================
FILE: copy/tools/leaflet.yml
================================================
title: Leaflet
description: JavaScript library for mobile-friendly interactive maps
logo: leafletjs.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: BSD
    link: 'https://github.com/Leaflet/Leaflet/blob/main/LICENSE'
types:
  - maps
renders:
  - svg
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/leaflet-1.png
  - /images/slider/leaflet-2.png
  - /images/slider/leaflet-3.png
  - /images/slider/leaflet-4.png
  - /images/slider/leaflet-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: leaflet/leaflet
  npm: leaflet
  npm_types: '@types/leaflet'
tags:
  stackoverflow:
    - leaflet
  twitter:
    - leafletjs
links:
  website: 'https://leafletjs.com'
  examples: 'https://leafletjs.com/examples.html'
  docs: 'https://leafletjs.com/reference-1.7.1.html'
  pricing: null
  slack: null
content:
  - type: official
    title: leafletjs Quick Start Guide
    link: 'https://leafletjs.com/examples/quick-start/'
github_data:
  stars: 42153
  contributors: 987
  issues: 404
  stale_issues: 377
  last_release:
    date: '2023-05-18T11:12:03Z'
    link: 'https://github.com/Leaflet/Leaflet/releases/tag/v1.9.4'
stackoverflow_data:
  questions_count: 12948


================================================
FILE: copy/tools/lightweight-charts.yml
================================================
title: Lightweight Charts
description: Financial lightweight charts built with HTML5 canvas
logo: lightweight-charts.svg
developer: TradingView
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/tradingview/lightweight-charts/blob/master/LICENSE'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - vue
  - angular
slugs:
  github: tradingview/lightweight-charts
  npm: lightweight-charts
tags:
  stackoverflow:
    - lightweight-charts
  twitter:
    - lightweightcharts
links:
  website: 'https://www.tradingview.com/lightweight-charts/'
  examples: 'https://www.tradingview.com/lightweight-charts/'
  docs: 'https://tradingview.github.io/lightweight-charts/'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://tradingview.github.io/lightweight-charts/docs'
  - type: official
    title: Customization
    link: >-
      https://tradingview.github.io/lightweight-charts/tutorials/customization/intro
  - type: official
    title: Framework integrations
    link: >-
      https://tradingview.github.io/lightweight-charts/tutorials#framework-integrations
github_data:
  stars: 10832
  contributors: 55
  issues: 97
  stale_issues: 50
  last_release:
    date: '2025-02-26T14:27:04Z'
    link: 'https://github.com/tradingview/lightweight-charts/releases/tag/v5.0.3'
stackoverflow_data:
  questions_count: 162


================================================
FILE: copy/tools/mapbox-gl.yml
================================================
title: Mapbox GL JS
description: >-
  Interactive, thoroughly customizable maps in the browser, powered by vector
  tiles and WebGL
logo: mapbox-gl.png
developer: null
based_on: null
licenses:
  - type: proprietary
    link: 'https://github.com/mapbox/mapbox-gl-js/blob/main/LICENSE.txt'
types:
  - maps
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/mapbox-gl-1.png
  - /images/slider/mapbox-gl-2.png
  - /images/slider/mapbox-gl-3.png
  - /images/slider/mapbox-gl-4.png
  - /images/slider/mapbox-gl-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: mapbox/mapbox-gl-js
  npm: mapbox-gl
  npm_types: '@types/mapbox-gl'
tags:
  stackoverflow:
    - mapbox
    - mapbox-gl-js
  twitter:
    - mapbox
links:
  website: 'https://docs.mapbox.com/mapbox-gl-js/api/'
  examples: 'https://docs.mapbox.com/mapbox-gl-js/example/'
  docs: 'https://docs.mapbox.com/mapbox-gl-js/api/'
  pricing: null
  slack: null
content:
  - type: official
    title: Tutorials
    link: 'https://docs.mapbox.com/help/tutorials/?product=Mapbox+GL+JS'
  - type: cube
    title: JavaScript Map Data Visualization with Mapbox
    link: 'https://mapbox-guide.cube.dev'
github_data:
  stars: 11440
  contributors: 440
  issues: 1316
  stale_issues: 1152
  last_release:
    date: '2025-02-13T16:41:06Z'
    link: 'https://github.com/mapbox/mapbox-gl-js/releases/tag/v3.10.0'
stackoverflow_data:
  questions_count: 9204


================================================
FILE: copy/tools/material-ui-data-grid.yml
================================================
title: MUI X Data Grid
description: Fast and extendable data table and data grid for React
logo: material-ui.svg
developer: MUI
based_on: null
licenses:
  - type: proprietary
    title: MUI X Premium
    link: >-
      https://github.com/mui/mui-x/blob/master/packages/grid/x-data-grid-premium/LICENSE
  - type: proprietary
    title: MUI X Pro
    link: >-
      https://github.com/mui/mui-x/blob/master/packages/grid/x-data-grid-pro/LICENSE
  - type: open-source
    title: MIT
    link: 'https://github.com/mui/mui-x/blob/master/packages/grid/x-data-grid/LICENSE'
types:
  - grid
renders:
  - html
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/mui-x-data-grid-1.png
  - /images/slider/mui-x-data-grid-2.png
  - /images/slider/mui-x-data-grid-3.png
  - /images/slider/mui-x-data-grid-4.png
  - /images/slider/mui-x-data-grid-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: mui/mui-x
  npm: '@mui/x-data-grid'
tags:
  stackoverflow:
    - mui-x
  twitter:
    - MUI_hq
links:
  website: 'https://mui.com/x/react-data-grid/'
  examples: 'https://mui.com/x/react-data-grid/#mit-version-free-forever'
  docs: 'https://mui.com/x/react-data-grid/'
  pricing: 'https://mui.com/pricing/'
  slack: null
content:
  - type: cube
    title: Material UI Dashboard with React
    link: 'https://material-ui-dashboard.cube.dev'
github_data:
  stars: 4692
  contributors: 440
  issues: 1308
  stale_issues: 787
  last_release:
    date: '2025-02-28T16:07:27Z'
    link: 'https://github.com/mui/mui-x/releases/tag/v8.0.0-alpha.13'
stackoverflow_data:
  questions_count: 261


================================================
FILE: copy/tools/metabase.yml
================================================
title: Metabase
description: 'Easy, open-source way to ask questions and learn from data'
logo: metabase.png
developer: null
based_on: null
licenses:
  - type: proprietary
    link: 'https://github.com/metabase/metabase/blob/master/LICENSE.txt'
  - type: open-source
    title: AGPL
    link: 'https://github.com/metabase/metabase/blob/master/LICENSE.txt'
types:
  - app
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/metabase-1.png
  - /images/slider/metabase-2.png
  - /images/slider/metabase-3.png
  - /images/slider/metabase-4.png
  - /images/slider/metabase-5.png
languages: null
frameworks: null
slugs:
  github: metabase/metabase
tags:
  stackoverflow:
    - metabase
  twitter:
    - Metabase
links:
  website: 'https://www.metabase.com'
  examples: >-
    https://www.metabase.com/learn/getting-started/getting-started/tour-of-metabase.html
  docs: 'https://www.ag-grid.com/javascript-grid/'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting started with Metabase
    link: >-
      https://www.metabase.com/learn/getting-started/getting-started/getting-started.html
  - type: cube
    title: Connecting Metabase to Cube.js
    link: 'https://github.com/pyrooka/metabase-cubejs-driver#usage'
github_data:
  stars: 41031
  contributors: 441
  issues: 3803
  stale_issues: 2364
  last_release:
    date: '2025-02-25T19:30:05Z'
    link: 'https://github.com/metabase/metabase/releases/tag/v0.52.13'
stackoverflow_data:
  questions_count: 382


================================================
FILE: copy/tools/muze.yml
================================================
title: Muze
description: Free library for creating exploratory data visualizations using WebAssembly
logo: muze.svg
developer: Charts.com
based_on: null
licenses:
  - type: proprietary
    title: EULA
    link: 'https://github.com/chartshq/muze/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/muze-1.png
  - /images/slider/muze-2.png
  - /images/slider/muze-3.png
  - /images/slider/muze-4.png
  - /images/slider/muze-5.png
languages:
  - JavaScript
frameworks:
  - vanilla-js
  - react
slugs:
  github: chartshq/muze
  npm: muze
tags:
  stackoverflow:
    - muze
  twitter: null
links:
  website: 'https://muzejs.org'
  examples: 'https://muzejs.org/demos/wa/latest'
  docs: 'https://muzejs.org/docs/wa/latest/introduction'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started with Muze
    link: >-
      https://muzejs.org/docs/wa/latest/introduction?id=getting-started-with-muze
  - type: cube
    title: 'Tableau-like Charts with MuzeJS, Cube.js, and React'
    link: 'https://cube.dev/blog/react-muzejs-tutorial/'
github_data:
  stars: 1185
  contributors: 21
  issues: 4
  stale_issues: 4
  last_release:
    date: '2020-07-31T14:11:59Z'
    link: 'https://github.com/chartshq/muze/releases/tag/v2.0.0'
stackoverflow_data:
  questions_count: 0


================================================
FILE: copy/tools/ngx-charts.yml
================================================
title: ngx-charts
description: Declarative charting framework for Angular
logo: ngx-charts.svg
developer: Swimlane
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/swimlane/ngx-charts/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/ngx-charts-1.png
  - /images/slider/ngx-charts-2.png
  - /images/slider/ngx-charts-3.png
  - /images/slider/ngx-charts-4.png
  - /images/slider/ngx-charts-5.png
languages:
  - TypeScript
frameworks:
  - angular
slugs:
  github: swimlane/ngx-charts
  npm: '@swimlane/ngx-charts'
tags:
  stackoverflow:
    - ngx-charts
  twitter:
    - ngxcharts
links:
  website: 'https://swimlane.github.io/ngx-charts/'
  examples: 'https://swimlane.github.io/ngx-charts/'
  docs: 'https://swimlane.gitbook.io/ngx-charts'
  pricing: null
  slack: null
content: null
github_data:
  stars: 4312
  contributors: 133
  issues: 712
  stale_issues: 688
  last_release:
    date: null
    link: null
stackoverflow_data:
  questions_count: 247


================================================
FILE: copy/tools/nivo.yml
================================================
title: nivo
description: Supercharged React components to easily build dataviz apps
logo: nivo.png
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
types:
  - charts
  - maps
renders:
  - svg
  - html
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/nivo-1.png
  - /images/slider/nivo-2.png
  - /images/slider/nivo-3.png
  - /images/slider/nivo-4.png
  - /images/slider/nivo-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: plouc/nivo
  npm: null
tags:
  stackoverflow:
    - nivo-react
  twitter:
    - nivo
links:
  website: 'https://nivo.rocks'
  examples: 'https://nivo.rocks/storybook/'
  docs: 'https://nivo.rocks/components'
  pricing: null
  slack: null
content:
  - type: cube
    title: Building a nivo Dashboard with Cube
    link: 'https://cube.dev/blog/building-a-nivo-dashboard-with-cube'
github_data:
  stars: 13415
  contributors: 220
  issues: 89
  stale_issues: 56
  last_release:
    date: '2024-11-11T01:52:42Z'
    link: 'https://github.com/plouc/nivo/releases/tag/v0.88.0'
stackoverflow_data:
  questions_count: 84


================================================
FILE: copy/tools/observable-plot.yml
================================================
title: Observable Plot
description: Concise API for exploratory data visualization
logo: observable.png
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: ISC
    link: 'https://github.com/observablehq/plot/blob/main/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/observable-plot-1.png
  - /images/slider/observable-plot-2.png
  - /images/slider/observable-plot-3.png
  - /images/slider/observable-plot-4.png
  - /images/slider/observable-plot-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: observablehq/plot
  npm: '@observablehq/plot'
tags:
  stackoverflow:
    - observablehq
  twitter:
    - observablehq
links:
  website: 'https://observablehq.com/plot'
  examples: 'https://observablehq.com/@observablehq/plot-gallery'
  docs: 'https://observablehq.com/plot'
  pricing: null
  slack: 'https://observable-community.slack.com/ssb/redirect'
content:
  - type: official
    title: Getting Started
    link: 'https://observablehq.com/plot/getting-started'
github_data:
  stars: 4605
  contributors: 26
  issues: 250
  stale_issues: 204
  last_release:
    date: '2025-02-14T16:05:17Z'
    link: 'https://github.com/observablehq/plot/releases/tag/v0.6.17'
stackoverflow_data:
  questions_count: 136


================================================
FILE: copy/tools/p5.yml
================================================
title: p5.js
description: >-
  JavaScript library for creative coding that makes coding accessible and
  inclusive
logo: p5.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: GNU LGPL 2.1
    link: 'https://github.com/processing/p5.js/blob/main/license.txt'
types:
  - low-level
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/p5-1.png
  - /images/slider/p5-2.png
  - /images/slider/p5-3.png
  - /images/slider/p5-4.png
  - /images/slider/p5-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: processing/p5.js
  npm: p5
  npm_types: '@types/p5'
tags:
  stackoverflow:
    - p5.js
  twitter:
    - p5js
    - p5xjs
links:
  website: 'https://p5js.org'
  examples: 'https://p5js.org/examples/'
  docs: 'https://p5js.org/examples/'
  pricing: null
  slack: null
content:
  - type: official
    title: Get Started with p5.js
    link: 'https://p5js.org/get-started/'
github_data:
  stars: 22172
  contributors: 796
  issues: 302
  stale_issues: 201
  last_release:
    date: '2025-02-25T21:27:36Z'
    link: 'https://github.com/processing/p5.js/releases/tag/v2.0.0-beta.3'
stackoverflow_data:
  questions_count: 3185


================================================
FILE: copy/tools/pancake.yml
================================================
title: Pancake
description: 'Responsive charts, JavaScript optional'
logo: pancake.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/Rich-Harris/pancake/blob/master/package.json#L24'
types:
  - charts
renders:
  - svg
  - html
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
frameworks:
  - svelte
slugs:
  github: Rich-Harris/pancake
  npm: '@sveltejs/pancake'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://pancake-charts.surge.sh'
  examples: 'https://pancake-charts.surge.sh'
  docs: null
  pricing: null
  slack: null
content:
  - type: official
    title: 'A new technique for making responsive, JavaScript-free charts'
    link: >-
      https://dev.to/richharris/a-new-technique-for-making-responsive-javascript-free-charts-gmp
github_data:
  stars: 1303
  contributors: 2
  issues: 17
  stale_issues: 17
  last_release:
    date: null
    link: null
stackoverflow_data: null


================================================
FILE: copy/tools/perspective.yml
================================================
title: Perspective
description: >-
  Interactive analytics and data visualization component, especially well-suited
  for large and/or streaming datasets
logo: finos.svg
developer: J.P. Morgan
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/finos/perspective/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
  - html
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/perspective-1.png
  - /images/slider/perspective-2.png
  - /images/slider/perspective-3.png
  - /images/slider/perspective-4.png
  - /images/slider/perspective-5.png
languages:
  - JavaScript
  - Python
frameworks:
  - vanilla-js
slugs:
  github: finos/perspective
  npm: '@finos/perspective'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://perspective.finos.org'
  examples: 'https://perspective.finos.org'
  docs: 'https://perspective.finos.org/docs/js'
  pricing: null
  slack: null
content:
  - type: official
    title: JavaScript User Guide
    link: 'https://perspective.finos.org/docs/js'
  - type: official
    title: Python User Guide
    link: 'https://perspective.finos.org/docs/python'
github_data:
  stars: 8836
  contributors: 98
  issues: 97
  stale_issues: 69
  last_release:
    date: '2025-02-10T05:23:05Z'
    link: 'https://github.com/finos/perspective/releases/tag/v3.3.4'
stackoverflow_data: null


================================================
FILE: copy/tools/plotly.yml
================================================
title: Plotly
description: 'High-level, declarative charting library'
logo: plotly.svg
developer: null
based_on:
  - d3
  - stackgl
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/plotly/plotly.js/blob/master/LICENSE'
types:
  - charts
  - maps
  - 3d
renders:
  - svg
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/plotly-1.png
  - /images/slider/plotly-2.png
  - /images/slider/plotly-3.png
  - /images/slider/plotly-4.png
  - /images/slider/plotly-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: plotly/plotly.js
  npm: plotly.js
  npm_types: '@types/plotly.js'
tags:
  stackoverflow:
    - plotly
    - plotly.js
  twitter:
    - plotly
    - plotlyjs
links:
  website: 'https://plotly.com/javascript/'
  examples: 'https://plotly.com/javascript/'
  docs: 'https://www.ag-grid.com/javascript-grid/'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started in JavaScript
    link: 'https://plotly.com/javascript/getting-started/'
github_data:
  stars: 17388
  contributors: 295
  issues: 634
  stale_issues: 472
  last_release:
    date: '2025-02-18T16:55:38Z'
    link: 'https://github.com/plotly/plotly.js/releases/tag/v3.0.1'
stackoverflow_data:
  questions_count: 15318


================================================
FILE: copy/tools/plottable.yml
================================================
title: Plottable
description: Library of modular chart components built on D3.js
logo: plottable.svg
developer: Palantir
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/palantir/plottable/blob/develop/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: palantir/plottable
  npm: plottable
tags:
  stackoverflow:
    - plottable
  twitter:
    - aggrid
    - ag_grid
links:
  website: 'http://plottablejs.org'
  examples: 'http://plottablejs.org/examples/'
  docs: 'http://plottablejs.org/docs/modules/plottable.html'
  pricing: null
  slack: null
content:
  - type: official
    title: Quick Start
    link: 'https://github.com/palantir/plottable/blob/develop/README.md#quick-start'
github_data:
  stars: 2989
  contributors: 85
  issues: 305
  stale_issues: 305
  last_release:
    date: '2021-11-22T14:30:28Z'
    link: 'https://github.com/palantir/plottable/releases/tag/v3.13.0'
stackoverflow_data:
  questions_count: 44


================================================
FILE: copy/tools/pts.yml
================================================
title: Pts
description: Library for visualization and creative-coding
logo: pts.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/williamngan/pts/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
  - html
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/pts-1.png
  - /images/slider/pts-2.png
  - /images/slider/pts-3.png
  - /images/slider/pts-4.png
  - /images/slider/pts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: williamngan/pts
  npm: pts
tags:
  stackoverflow: null
  twitter:
    - ptsjs
links:
  website: 'https://ptsjs.org'
  examples: 'https://ptsjs.org/demo/'
  docs: 'https://ptsjs.org/docs/'
  pricing: null
  slack: null
content:
  - type: official
    title: Get started with Pts.js
    link: 'https://ptsjs.org/guide/get-started-0100'
github_data:
  stars: 5225
  contributors: 24
  issues: 48
  stale_issues: 42
  last_release:
    date: '2022-12-08T09:43:45Z'
    link: 'https://github.com/williamngan/pts/releases/tag/v0.11.3'
stackoverflow_data: null


================================================
FILE: copy/tools/react-charts.yml
================================================
title: React Charts
description: 'Simple, immersive & interactive charts for React'
logo: react-charts.svg
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/TanStack/react-charts/blob/main/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: TanStack/react-charts
  npm: react-charts
tags:
  stackoverflow:
    - react-charts
  twitter:
    - ReactCharts
links:
  website: 'https://react-charts.tanstack.com'
  examples: 'https://react-charts.tanstack.com/examples/simple'
  docs: 'https://react-charts.tanstack.com/docs/overview'
  pricing: null
  slack: null
content:
  - type: official
    title: Installation
    link: 'https://react-charts.tanstack.com/docs/installation'
github_data:
  stars: 3043
  contributors: 32
  issues: 60
  stale_issues: 52
  last_release:
    date: '2023-11-02T22:14:26Z'
    link: 'https://github.com/TanStack/react-charts/releases/tag/v3.0.0-beta.57'
stackoverflow_data:
  questions_count: 11


================================================
FILE: copy/tools/reaflow.yml
================================================
title: reaflow
description: 'React library for building workflow editors, flow charts, and diagrams'
logo: reaflow.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/reaviz/reaflow/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/reaflow-1.png
  - /images/slider/reaflow-2.png
  - /images/slider/reaflow-3.png
  - /images/slider/reaflow-4.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: reaviz/reaflow
  npm: reaflow
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://reaflow.dev'
  examples: 'https://reaflow.dev/?path=/story/demos-basic--custom-elements'
  docs: 'https://reaflow.dev/?path=/story/docs-introduction--page'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://reaflow.dev/?path=/story/docs-getting-started-installing--page'
github_data:
  stars: 2248
  contributors: 27
  issues: 86
  stale_issues: 78
  last_release:
    date: null
    link: null
stackoverflow_data: null


================================================
FILE: copy/tools/reaviz.yml
================================================
title: REAVIZ
description: >-
  Modular chart library that leverages React natively while using D3.js under
  the hood
logo: reaviz.png
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/reaviz/reaviz/blob/master/LICENSE'
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: reaviz/reaviz
  npm: reaviz
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://reaviz.io'
  examples: 'https://reaviz.io/?path=/story/docs-intro--page'
  docs: 'https://reaviz.io/?path=/story/docs-intro--page'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://reaviz.io/?path=/story/docs-getting-started-quick-start--page'
github_data:
  stars: 1092
  contributors: 28
  issues: 36
  stale_issues: 27
  last_release:
    date: null
    link: null
stackoverflow_data: null


================================================
FILE: copy/tools/recharts.yml
================================================
title: Recharts
description: Composable charting library built on React components
logo: recharts.png
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/recharts/recharts/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 1
  easy-to-start-with: 3
  full-fledged: 0
  very-popular: 1
  well-documented: 3
gallery:
  - /images/slider/recharts-1.png
  - /images/slider/recharts-2.png
  - /images/slider/recharts-3.png
  - /images/slider/recharts-4.png
  - /images/slider/recharts-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: recharts/recharts
  npm: recharts
tags:
  stackoverflow:
    - recharts
  twitter:
    - recharts
links:
  website: 'https://recharts.org/en-US/'
  examples: 'https://recharts.org/en-US/examples'
  docs: 'https://recharts.org/en-US/api'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting started
    link: 'https://recharts.org/en-US/guide/getting-started'
  - type: cube
    title: Building a Recharts Dashboard with Cube
    link: 'https://cube.dev/blog/building-a-recharts-dashboard-with-cube/'
  - type: cube
    title: 'React Dashboard: an Ultimate Guide'
    link: 'https://react-dashboard.cube.dev'
github_data:
  stars: 24690
  contributors: 351
  issues: 444
  stale_issues: 348
  last_release:
    date: '2025-02-26T04:14:36Z'
    link: 'https://github.com/recharts/recharts/releases/tag/v3.0.0-alpha.8'
stackoverflow_data:
  questions_count: 783


================================================
FILE: copy/tools/redash.yml
================================================
title: Redash
description: Collaborative visualization and dashboarding platform
logo: redash.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: BSD
    link: 'https://github.com/getredash/redash/blob/master/LICENSE'
types:
  - app
renders: null
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages: null
frameworks: null
slugs:
  github: getredash/redash
  npm: null
  npm_types: null
tags:
  stackoverflow:
    - redash
  twitter:
    - redash
links:
  website: 'https://redash.io'
  examples: 'https://redash.io/help/user-guide/visualizations/visualization-types'
  docs: 'https://redash.io/help/open-source/setup'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://redash.io/help/user-guide/getting-started'
github_data:
  stars: 27000
  contributors: 525
  issues: 595
  stale_issues: 525
  last_release:
    date: '2025-01-08T19:06:48Z'
    link: 'https://github.com/getredash/redash/releases/tag/v25.1.0'
stackoverflow_data:
  questions_count: 138


================================================
FILE: copy/tools/rough.yml
================================================
title: Rough.js
description: 'Graphics library for drawing with a hand-drawn, sketchy appearance'
logo: rough.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/rough-stuff/rough/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/rough-1.png
  - /images/slider/rough-2.png
  - /images/slider/rough-3.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - vue
slugs:
  github: rough-stuff/rough
  npm: roughjs
tags:
  stackoverflow: null
  twitter:
    - roughjs
links:
  website: 'https://roughjs.com'
  examples: null
  docs: 'https://github.com/rough-stuff/rough/wiki'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://roughjs.com'
github_data:
  stars: 20139
  contributors: 13
  issues: 34
  stale_issues: 29
  last_release:
    date: '2019-03-14T19:05:30Z'
    link: 'https://github.com/rough-stuff/rough/releases/tag/v3.1.0'
stackoverflow_data: null


================================================
FILE: copy/tools/roughviz.yml
================================================
title: roughViz.js
description: >-
  JavaScript library for creating sketchy/hand-drawn styled charts, based on
  D3.js, Rough.js, and Handy
logo: roughviz.png
developer: null
based_on:
  - d3
  - rough
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/jwilber/roughViz/blob/master/LICENSE'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/roughviz-1.png
  - /images/slider/roughviz-2.png
languages:
  - JavaScript
frameworks:
  - vanilla-js
  - react
  - vue
slugs:
  github: jwilber/roughViz
  npm: rough-viz
tags:
  stackoverflow: null
  twitter:
    - roughViz
links:
  website: null
  examples: null
  docs: 'https://github.com/jwilber/roughViz#api'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://github.com/jwilber/roughViz#installation'
github_data:
  stars: 6762
  contributors: 16
  issues: 10
  stale_issues: 10
  last_release:
    date: null
    link: null
stackoverflow_data: null


================================================
FILE: copy/tools/semiotic.yml
================================================
title: Semiotic
description: Data visualization framework for React
logo: semiotic.png
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/nteract/semiotic/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/semiotic-1.png
  - /images/slider/semiotic-2.png
  - /images/slider/semiotic-3.png
  - /images/slider/semiotic-4.png
  - /images/slider/semiotic-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: nteract/semiotic
  npm: semiotic
tags:
  stackoverflow:
    - semiotic
  twitter: null
links:
  website: 'https://semiotic.nteract.io'
  examples: 'https://semiotic.nteract.io/examples'
  docs: 'https://semiotic.nteract.io/api'
  pricing: null
  slack: null
content: null
github_data:
  stars: 2444
  contributors: 31
  issues: 33
  stale_issues: 33
  last_release:
    date: '2020-01-21T03:13:12Z'
    link: 'https://github.com/nteract/semiotic/releases/tag/v1.20.5'
stackoverflow_data:
  questions_count: 4


================================================
FILE: copy/tools/stackgl.yml
================================================
title: stackgl
description: Open software ecosystem for WebGL
logo: stackgl.svg
developer: null
based_on: null
licenses: null
types:
  - low-level
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/stackgl-1.jpg
  - /images/slider/stackgl-2.jpg
  - /images/slider/stackgl-3.jpg
  - /images/slider/stackgl-4.jpg
  - /images/slider/stackgl-5.jpg
languages:
  - JavaScript
frameworks:
  - vanilla-js
slugs:
  github: stackgl/shader-school
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'http://stack.gl'
  examples: 'http://stack.gl/#examples'
  docs: 'http://stack.gl/packages/'
  pricing: null
  slack: null
content: null
github_data:
  stars: 4342
  contributors: 22
  issues: 44
  stale_issues: 44
  last_release:
    date: null
    link: null
stackoverflow_data: null


================================================
FILE: copy/tools/superset.yml
================================================
title: Apache Superset
description: Modern data exploration and visualization platform
logo: superset.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/apache/superset/blob/master/LICENSE.txt'
types:
  - app
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/superset-1.png
  - /images/slider/superset-2.png
  - /images/slider/superset-3.png
  - /images/slider/superset-4.png
  - /images/slider/superset-5.png
languages: null
frameworks: null
slugs:
  github: apache/superset
tags:
  stackoverflow:
    - superset
    - apache-superset
  twitter:
    - ApacheSuperset
links:
  website: 'https://superset.apache.org'
  examples: 'https://superset.apache.org/gallery'
  docs: 'https://superset.apache.org/docs/intro'
  pricing: null
  slack: >-
    https://apache-superset.slack.com/join/shared_invite/zt-l5f5e0av-fyYu8tlfdqbMdz_sPLwUqQ
content:
  - type: official
    title: What is Apache Superset?
    link: 'https://superset.apache.org/docs/intro'
  - type: cube
    title: Building a metrics dashboard with Superset and Cube
    link: 'https://cube.dev/blog/building-metrics-dashboard-with-superset/'
github_data:
  stars: 64736
  contributors: 1275
  issues: 766
  stale_issues: 203
  last_release:
    date: '2025-02-04T19:04:37Z'
    link: 'https://github.com/apache/superset/releases/tag/5.0.0rc1'
stackoverflow_data:
  questions_count: 1417


================================================
FILE: copy/tools/three.yml
================================================
title: three.js
description: JavaScript 3D library
logo: threejs.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/mrdoob/three.js/blob/dev/LICENSE'
types:
  - 3d
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 1
  well-documented: 0
gallery:
  - /images/slider/three-1.jpg
  - /images/slider/three-2.jpg
  - /images/slider/three-3.jpg
  - /images/slider/three-4.jpg
  - /images/slider/three-5.jpg
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: mrdoob/three.js
  npm: three
  npm_types: '@types/three'
tags:
  stackoverflow:
    - three.js
  twitter:
    - threejs
links:
  website: 'https://threejs.org'
  examples: 'https://threejs.org/examples/#webgl_animation_cloth'
  docs: 'https://threejs.org/docs/index.html'
  pricing: null
  slack: null
content:
  - type: official
    title: Creating a scene in three.js
    link: >-
      https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene
github_data:
  stars: 104617
  contributors: 2359
  issues: 428
  stale_issues: 296
  last_release:
    date: '2025-02-27T09:33:44Z'
    link: 'https://github.com/mrdoob/three.js/releases/tag/r174'
stackoverflow_data:
  questions_count: 21272


================================================
FILE: copy/tools/toast-ui-chart.yml
================================================
title: TOAST UI Chart
description: Beautiful chart for data visualization
logo: toast-ui-chart.png
developer: null
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/nhn/tui.chart/blob/main/LICENSE'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - vue
slugs:
  github: nhn/tui.chart
  npm: tui-chart
tags:
  stackoverflow:
    - toast-ui-chart
  twitter: null
links:
  website: 'https://ui.toast.com/tui-chart'
  examples: >-
    https://nhn.github.io/tui.chart/latest/tutorial-example01-01-area-chart-basic
  docs: 'https://nhn.github.io/tui.chart/latest/'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started
    link: 'https://github.com/nhn/tui.chart/blob/main/docs/en/getting-started.md'
github_data:
  stars: 5363
  contributors: 12
  issues: 19
  stale_issues: 15
  last_release:
    date: '2022-12-21T03:06:57Z'
    link: 'https://github.com/nhn/tui.chart/releases/tag/v4.6.1'
stackoverflow_data:
  questions_count: 2


================================================
FILE: copy/tools/unovis.yml
================================================
title: Unovis
description: >-
  Modular data visualization framework for React, Angular, Svelte, and vanilla
  TypeScript or JavaScript
logo: unovis.svg
developer: null
based_on:
  - d3
  - leaflet
  - maplibre
licenses:
  - type: open-source
    title: Apache-2.0
    link: 'https://github.com/f5/unovis/blob/main/LICENSE'
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 1
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 1
gallery:
  - /images/slider/unovis-1.png
  - /images/slider/unovis-2.png
  - /images/slider/unovis-3.png
  - /images/slider/unovis-4.png
  - /images/slider/unovis-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - svelte
slugs:
  github: f5/unovis
  npm: '@unovis'
tags:
  stackoverflow:
    - unovis
  twitter:
    - unovisdev
links:
  website: 'https://unovis.dev'
  examples: 'https://unovis.dev/gallery'
  docs: 'https://unovis.dev/docs'
  pricing: null
content:
  - type: official
    title: Quick Start Guide
    link: 'https://unovis.dev/docs/quick-start'
github_data:
  stars: 2384
  contributors: 14
  issues: 52
  stale_issues: 11
  last_release:
    date: '2025-02-19T18:33:01Z'
    link: 'https://github.com/f5/unovis/releases/tag/1.5.1'
stackoverflow_data:
  questions_count: 0


================================================
FILE: copy/tools/vega-lite.yml
================================================
title: Vega-Lite
description: 'Concise grammar of interactive graphics, built on Vega'
logo: vega-lite.svg
developer: null
based_on:
  - vega
licenses:
  - type: open-source
    title: BSD
    link: 'https://github.com/vega/vega-lite/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/vega-lite-1.png
  - /images/slider/vega-lite-2.png
  - /images/slider/vega-lite-3.png
  - /images/slider/vega-lite-4.png
  - /images/slider/vega-lite-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
slugs:
  github: vega/vega-lite
  npm: vega-lite
tags:
  stackoverflow:
    - vega-lite
  twitter:
    - vegalite
links:
  website: 'https://vega.github.io/vega-lite/'
  examples: 'https://vega.github.io/vega-lite/examples/'
  docs: 'https://vega.github.io/vega-lite/docs/'
  pricing: null
  slack: 'https://bit.ly/join-vega-slack-2020'
content:
  - type: official
    title: Introduction to Vega-Lite
    link: 'https://vega.github.io/vega-lite/tutorials/getting_started.html'
github_data:
  stars: 4774
  contributors: 213
  issues: 708
  stale_issues: 637
  last_release:
    date: '2024-12-10T17:38:11Z'
    link: 'https://github.com/vega/vega-lite/releases/tag/v5.23.0'
stackoverflow_data:
  questions_count: 1552


================================================
FILE: copy/tools/vega.yml
================================================
title: Vega
description: >-
  Visualization grammar, a declarative language for creating and sharing
  visualization designs
logo: vega.svg
developer: null
based_on:
  - d3
licenses:
  - type: open-source
    title: BSD
    link: 'https://github.com/vega/vega/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/vega-1.png
  - /images/slider/vega-2.png
  - /images/slider/vega-3.png
  - /images/slider/vega-4.png
  - /images/slider/vega-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
slugs:
  github: vega/vega
  npm: vega
tags:
  stackoverflow:
    - vega
  twitter:
    - vegajs
links:
  website: 'https://vega.github.io/vega/'
  examples: 'https://vega.github.io/vega/examples/'
  docs: 'https://vega.github.io/vega/docs/'
  pricing: null
  slack: 'https://bit.ly/join-vega-slack-2020'
content:
  - type: official
    title: Let's Make a Bar Chart
    link: 'https://vega.github.io/vega/tutorials/bar-chart/'
github_data:
  stars: 11384
  contributors: 156
  issues: 445
  stale_issues: 407
  last_release:
    date: '2025-02-28T02:48:35Z'
    link: 'https://github.com/vega/vega/releases/tag/v5.32.0'
stackoverflow_data:
  questions_count: 1077


================================================
FILE: copy/tools/victory.yml
================================================
title: Victory
description: React components for modular charting and data visualization
logo: victory.png
developer: Formidable
based_on: null
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/FormidableLabs/victory/blob/main/LICENSE.txt'
types:
  - charts
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/victory-1.png
  - /images/slider/victory-2.png
  - /images/slider/victory-3.png
  - /images/slider/victory-4.png
  - /images/slider/victory-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: FormidableLabs/victory
  npm: victory
tags:
  stackoverflow:
    - victory-charts
    - victory-native
  twitter:
    - VictoryCharts
links:
  website: 'https://formidable.com/open-source/victory/'
  examples: 'https://formidable.com/open-source/victory/gallery'
  docs: 'https://formidable.com/open-source/victory/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting Started with Victory
    link: 'https://formidable.com/open-source/victory/docs'
  - type: cube
    title: React Native Charts with Cube.js and Victory
    link: 'https://cube.dev/blog/react-native-charts-with-cubejs-victory/'
github_data:
  stars: 11096
  contributors: 247
  issues: 91
  stale_issues: 66
  last_release:
    date: '2025-01-14T17:23:54Z'
    link: 'https://github.com/FormidableLabs/victory/releases/tag/v37.3.6'
stackoverflow_data:
  questions_count: 306


================================================
FILE: copy/tools/vis.yml
================================================
title: vis.js
description: Dynamic visualization library
logo: visjs.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/visjs/vis-charts/blob/master/LICENSE-APACHE-2.0'
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/vis-1.png
  - /images/slider/vis-2.png
  - /images/slider/vis-3.png
  - /images/slider/vis-4.png
  - /images/slider/vis-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
slugs:
  github: visjs/vis-charts
  npm: vis-charts
  npm_types: '@types/vis'
tags:
  stackoverflow:
    - vis.js
  twitter:
    - visjs
links:
  website: 'https://visjs.org'
  examples: 'https://visjs.github.io/vis-timeline/examples/graph2d/'
  docs: 'https://visjs.github.io/vis-timeline/docs/graph2d/'
  pricing: null
  slack: null
content: null
github_data:
  stars: 113
  contributors: 43
  issues: 0
  stale_issues: 0
  last_release:
    date: '2020-05-17T12:03:36Z'
    link: 'https://github.com/visjs/vis-charts/releases/tag/v3.0.0'
stackoverflow_data:
  questions_count: 795


================================================
FILE: copy/tools/visx.yml
================================================
title: visx
description: 'Collection of expressive, low-level visualization primitives for React'
logo: visx.png
developer: Airbnb
based_on:
  - d3
licenses:
  - type: open-source
    title: MIT
    link: 'https://github.com/airbnb/visx/blob/master/LICENSE'
types:
  - low-level
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/visx-1.png
  - /images/slider/visx-2.png
  - /images/slider/visx-3.png
  - /images/slider/visx-4.png
  - /images/slider/visx-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - react
slugs:
  github: airbnb/visx
  npm: '@visxx/visx'
tags:
  stackoverflow: null
  twitter: null
links:
  website: 'https://airbnb.io/visx/'
  examples: 'https://airbnb.io/visx/gallery'
  docs: 'https://airbnb.io/visx/docs'
  pricing: null
  slack: null
content:
  - type: official
    title: Getting started with vx
    link: 'https://medium.com/vx-code/getting-started-with-vx-1756bb661410'
  - type: cube
    title: Building a visx Dashboard with Cube
    link: 'https://cube.dev/blog/building-a-visx-dashboard-with-cube'
github_data:
  stars: 19799
  contributors: 177
  issues: 126
  stale_issues: 106
  last_release:
    date: '2024-11-07T18:38:04Z'
    link: 'https://github.com/airbnb/visx/releases/tag/v3.12.0'
stackoverflow_data: null


================================================
FILE: copy/tools/vizzu.yml
================================================
title: Vizzu
description: Library for animated data visualizations and data stories
logo: vizzu.svg
developer: null
based_on: null
licenses:
  - type: open-source
    title: Apache 2.0
    link: 'https://github.com/vizzuhq/vizzu-lib/blob/main/LICENSE'
types:
  - charts
renders:
  - canvas
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery: []
languages:
  - JavaScript
frameworks:
  - vanilla-js
slugs:
  github: vizzuhq/vizzu-lib
  npm: vizzu
tags:
  stackoverflow: null
  twitter:
    - Vizzu
links:
  website: 'https://vizzuhq.com'
  examples: 'https://lib.vizzuhq.com/0.3.0/#examples-1.0'
  docs: 'https://lib.vizzuhq.com/0.3.0/'
  pricing: null
  slack: >-
    https://join.slack.com/t/vizzu-community/shared_invite/zt-w2nqhq44-2CCWL4o7qn2Ns1EFSf9kEg
content:
  - type: official
    title: Getting Started
    link: 'https://lib.vizzuhq.com/0.3.0/'
github_data:
  stars: 1954
  contributors: 14
  issues: 2
  stale_issues: 2
  last_release:
    date: '2025-02-24T19:33:42Z'
    link: 'https://github.com/vizzuhq/vizzu-lib/releases/tag/v0.16.1'
stackoverflow_data: null


================================================
FILE: copy/tools/zingchart.yml
================================================
title: ZingChart
description: >-
  Declarative, efficient, and simple JavaScript library for building responsive
  charts
logo: zingchart.png
developer: null
based_on: null
licenses:
  - type: proprietary
types:
  - charts
  - maps
renders:
  - svg
features:
  easy-to-customize: 0
  easy-to-start-with: 0
  full-fledged: 0
  very-popular: 0
  well-documented: 0
gallery:
  - /images/slider/zingchart-1.png
  - /images/slider/zingchart-2.png
  - /images/slider/zingchart-3.png
  - /images/slider/zingchart-4.png
  - /images/slider/zingchart-5.png
languages:
  - JavaScript
  - TypeScript
frameworks:
  - vanilla-js
  - react
  - angular
  - vue
slugs:
  github: zingchart/ZingChart
  npm: zingchart
  npm_types: '@types/zingchart'
tags:
  stackoverflow:
    - zingchart
  twitter:
    - ZingChart
links:
  website: 'https://www.zingchart.com'
  examples: 'https://www.zingchart.com/gallery?type=chartType'
  docs: 'https://www.zingchart.com/docs'
  pricing: 'https://www.zingchart.com/pricing'
  slack: null
content:
  - type: official
    title: Your First JavaScript Chart
    link: 'https://www.zingchart.com/docs/getting-started/your-first-javascript-chart'
github_data:
  stars: 277
  contributors: 23
  issues: 0
  stale_issues: 0
  last_release:
    date: '2025-01-16T18:07:36Z'
    link: 'https://github.com/zingchart/ZingChart/releases/tag/2.9.16-1'
stackoverflow_data:
  questions_count: 259


================================================
FILE: data/filter.js
================================================
const filter = (tools, framework, language, license, render, exploreTools) => {
  const filtered = tools.filter((tool) => {
    let isValid = true;

    if (exploreTools.length && isValid) {
      isValid = hasTypes(tool, exploreTools);
    }
    if (framework.length && isValid) {
      isValid = isCompatibleWith(tool, framework);
    }
    if (language.length && isValid) {
      let hasInclude = 0;
      tool?.languages?.forEach((lg) => {
        if (language.includes(lg.toLowerCase())) {
          hasInclude++;
        }
      });
      isValid = language.length === hasInclude;
    }
    if (license.length && isValid) {
      isValid = hasLicenses(tool, license);
    }
    if (render.length && isValid) {
      let hasInclude = 0;
      tool?.renders?.forEach((obj) => {
        if (render.includes(obj.toLowerCase())) {
          hasInclude++;
        }
      });
      isValid = render.length === hasInclude;
    }
    return isValid;
  });

  const maxFeatureScores = getMaxFeatureScores(tools);
  const maxFeatureScoresCopy = Object.assign({}, maxFeatureScores);

  return filtered
    .map((tool) => {
      const feature_label = getFeatureWithMaxScore(tool, maxFeatureScores);

      if (feature_label) {
        delete maxFeatureScores[feature_label];
      }

      return {
        ...tool,
        feature_label,
      };
    })
    .sort(getComparator(maxFeatureScoresCopy));
};

function getComparator(maxFeatureScores) {
  return function (a, b) {
    // Adding 1,000,000 to the number of GitHub stars is going to pull the tool up to the top.
    // As of 2021-06-01, freeCodeCamp/freeCodeCamp has 325,000 stars
    const aSortKey =
      (a.feature_label ? 1000000 : 0) + (a.github_data?.stars || 0);
    const bSortKey =
      (b.feature_label ? 1000000 : 0) + (b.github_data?.stars || 0);

    return bSortKey - aSortKey;
  };
}

function getMaxFeatureScores(tools) {
  return tools.reduce((features, tool) => {
    if (tool.features) {
      Object.entries(tool.features)
        .filter(([_, score]) => score !== 0)
        .forEach(([feature, score]) => {
          features[feature] =
            features[feature] !== undefined
              ? Math.max(features[feature], score)
              : score;
        });
    }

    return features;
  }, {});
}

function getFeatureWithMaxScore(tool, maxFeatureScores) {
  if (tool.features) {
    return Object.entries(tool.features)
      .sort((a, b) => b[1] - a[1])
      .filter(([_, score]) => score !== 0)
      .reduce((selectMaxFeature, [feature, score]) => {
        return (
          selectMaxFeature ||
          Object.entries(maxFeatureScores).find(
            ([maxFeature, maxScore]) =>
              feature === maxFeature && score === maxScore
          )?.[0]
        );
      }, undefined);
  }

  return false;
}

const setParamsFromRouter = (
  query,
  setExploreTools,
  setFramework,
  setLanguage,
  setLicense
) => {
  if (query.tools) {
    setExploreTools(
      typeof query.tools === "string" ? [query.tools] : [...query.tools]
    );
  }
  if (query.framework) {
    setFramework(
      typeof query.framework === "string"
        ? [query.framework]
        : [...query.framework]
    );
  }
  if (query.language) {
    setLanguage(
      typeof query.language === "string"
        ? [query.language]
        : [...query.language]
    );
  }
  if (query.license) {
    setLicense(
      typeof query.license === "string" ? [query.license] : [...query.license]
    );
  }
};

function hasTypes(tool, types) {
  return types.every(t => tool?.types?.some(type => type === t.toLowerCase()))
}

function isCompatibleWith(tool, frameworks) {
  return frameworks.every(fw => tool?.frameworks?.some(framework => framework === fw.toLowerCase()))
}

function hasLicenses(tool, licenses) {
  return licenses.every(l => tool?.licenses?.some(license => license.type === l.toLowerCase()))
}

export { filter, setParamsFromRouter, hasTypes, isCompatibleWith, hasLicenses };


================================================
FILE: data/frameworks.js
================================================
export default {
  react: {
    slug: "react",
    name: "React",
    icon: "react.svg",
  },
  angular: {
    slug: "angular",
    name: "Angular",
    icon: "angular.svg",
  },
  vue: {
    slug: "vue",
    name: "Vue",
    icon: "vue.svg",
  },
  svelte: {
    slug: "svelte",
    name: "Svelte",
    icon: "svelte.svg",
  },
};

================================================
FILE: data/tools.js
================================================
import fs from "fs";
import yaml from "node-yaml";

export const toolCopyPath = `${process.cwd()}/copy/tools`;

async function readTools() {
  const files = fs.readdirSync(toolCopyPath);
  const ids = files
    .filter((filename) => filename.endsWith(".yml"))
    .map((filename) => filename.split(".")[0]);

  const tools = {};
  const extendedTools = {};

  for (const id of ids) {
    tools[id] = await readTool(id);
  }

  for (const id of ids) {
    extendedTools[id] = await extendTool(tools[id], tools);
  }

  return extendedTools;
}

export async function readTool(id) {
  const tool = await yaml.read(`${toolCopyPath}/${id}.yml`);
  return { id, ...tool };
}

async function extendTool(tool, tools) {
  const positionsByStars = Object.values(tools)
    .map((t) => ({ key: t.id, value: t.github_data?.stars }))
    .sort(compare);

  tool.positions = {
    total: Object.keys(tools).length,
    stars:
      1 +
      positionsByStars.findIndex(
        (pair) => pair.value === tool.github_data?.stars
      ),
  };

  tool.percentages = {
    stale_issues:
      tool.github_data?.issues > 0
        ? 100 *
          (
            (tool.github_data?.stale_issues || 0) / tool.github_data?.issues
          ).toFixed(2)
        : 0,
  };

  return tool;
}

function compare(a, b) {
  return (b.value || 0) - (a.value || 0);
}

export async function getTools() {
  const tools = await readTools();
  return Object.values(tools);
}

export async function getTool(id) {
  const tools = await readTools();
  return tools[id];
}


================================================
FILE: data/types.js
================================================
export default {
  charts: {
    slug: "charts",
    name: "Charting libraries",
    image: "chart.svg",
    descriptor: "a charting library",
  },
  "low-level": {
    slug: "low-level",
    name: "Low-level tools",
    image: "lines.svg",
    descriptor: "a low-level data visualization library",
  },
  maps: {
    slug: "maps",
    name: "Mapping tools",
    image: "globe.svg",
    descriptor: "a mapping or spatial library",
  },
  grid: {
    slug: "grid",
    name: "Data grids",
    image: "grid.svg",
    descriptor: "a data grid or pivot table library",
  },
  "3d": {
    slug: "3d",
    name: "3D tools",
    image: "3d.svg",
    descriptor: "a 3D visualization library",
  },
  app: {
    slug: "app",
    name: "Exploration apps",
    image: "apps.svg",
    descriptor: "a data exploration application",
  },
};

================================================
FILE: data/useSlackMembers.js
================================================
import { useState, useEffect } from "react";
import fetch from "isomorphic-unfetch";
import abbreviateNumber from "../utils/number";

const cubeUrl = "https://amaranth-leech.gcp-us-central1.cubecloudapp.dev/cubejs-api/v1/load";
const cubeToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMDAwMDAwMDAsImV4cCI6NTAwMDAwMDAwMH0.OHZOpOBVKr-sCwn8sbZ5UFsqI3uCs6e4omT7P6WVMFw";

const cubeQuery = {
  measures: [
    "SlackUsers.count"
  ]
};

export default function useSlackMembers() {
  const [slackMembers, setSlackMembers] = useState(abbreviateNumber(5100));

  useEffect(() => {
    const url = new URL(cubeUrl);
    url.search = new URLSearchParams({
      query: JSON.stringify(cubeQuery, null, 2)
    }).toString();

    const options = {
      headers: {
        Authorization: cubeToken
      },
    };

    fetch(url, options)
      .then((response) => response.json())
      .then((response) => response.data[0]["SlackUsers.count"])
      .then((count) => setSlackMembers(abbreviateNumber(count)))
      .catch(() => {}); // Skip error
  }, []);

  return slackMembers;
}


================================================
FILE: data-update-worker/.gitignore
================================================
.env
node_modules

================================================
FILE: data-update-worker/fetchData.js
================================================
const fetch = require("node-fetch");
require("dotenv").config();

const getGithubData = async (githubSlug) => {
  if (!githubSlug) {
    return null;
  }
  const headers = {
    headers: {
      Authorization: `token ${process.env.ACCESS_TOKEN_GITHUB}`,
    },
  };
  let repo = null;
  let contributors = null;
  let releases = null;
  let issues = null;
  let stale_issues = null;
  let stale_date = getStaleDate();

  try {
    issues = await loadJSON(
      `https://api.github.com/search/issues?q=repo:${githubSlug}+type:issue+state:open&per_page=1`,
      headers
    );
    stale_issues = await loadJSON(
      `https://api.github.com/search/issues?q=repo:${githubSlug}+type:issue+created:<${stale_date}+state:open&per_page=1`,
      headers
    );
    repo = await loadJSON(
      `https://api.github.com/repos/${githubSlug}`,
      headers
    );
    contributors = await loadHeaders(
      `https://api.github.com/repos/${githubSlug}/contributors?per_page=1&anon=true`,
      headers
    );
    releases = await loadJSON(
      `https://api.github.com/repos/${githubSlug}/releases`,
      headers
    );
  } catch (e) {
    throw new Error(e);
  }

  if (
    repo.message ||
    releases.message ||
    issues.message ||
    stale_issues.message ||
    contributors.message
  ) {
    throw new Error(
      `Bad request: ${
        repo.message ||
        releases.message ||
        issues.message ||
        stale_issues.message ||
        contributors.message
      }`
    );
  }

  return {
    stars: repo?.stargazers_count,
    contributors: getContributorsByResponseHeaders(contributors),
    issues: issues?.total_count,
    stale_issues: stale_issues?.total_count,
    last_release: {
      date: releases?.[0]?.published_at || null,
      link: releases?.[0]?.html_url || null,
    },
  };
};

const getStackoverflowDataByTags = async (tags) => {
  if (!tags) {
    return null;
  }
  // const headers = {};
  let result = 0;
  try {
    await asyncForEach(tags, async (tag) => {
      const response = await loadJSON(
        `https://api.stackexchange.com/2.2/tags?order=desc&sort=popular&inname=${tag}&site=stackoverflow`
      );

      response?.items?.forEach((item) => {
        if (item.name === tag && item.count) {
          result += item.count;
        }
      });
    });
  } catch (e) {
    console.log(e);
    throw new Error(e);
  }
  return {
    questions_count: result,
  };
};

async function loadJSON(url, headers) {
  try {
    const res = await fetch(url, headers);
    return await res.json();
  } catch (e) {
    throw new Error(e);
  }
}
async function loadHeaders(url, headers) {
  try {
    const res = await fetch(url, headers);
    return await res.headers.get("Link");
  } catch (e) {
    throw new Error(e);
  }
}

function getStaleDate() {
  var date = new Date();
  date.setFullYear(date.getFullYear() - 1);

  return date.toISOString().split("T")[0];
}

function getContributorsByResponseHeaders(str) {
  if (!str) {
    return null;
  }
  let newStr = str.slice(str.indexOf('rel="next"'));
  let start = newStr.indexOf("&page=");
  let end = newStr.length - 13;
  let result = newStr.slice(start, end);
  let numb = result.match(/\d/g);
  return parseInt(numb.join(""));
}

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

exports.getGithubData = getGithubData;
exports.getStackoverflowDataByTags = getStackoverflowDataByTags;


================================================
FILE: data-update-worker/index.js
================================================
const yaml = require("node-yaml");
const fs = require("fs");
const get = require("./fetchData.js");
const { notifySlackUpdateFailures } = require("./notifySlack.js");

const files = fs.readdirSync("../copy/tools");
const ids = files
  .filter((filename) => filename.endsWith(".yml"))
  .map((filename) => filename.split(".")[0]);

let failures = [];

asyncForEach(ids, async (id) => {
  try {
    const file = await yaml.read(`../copy/tools/${id}.yml`);
    file.github_data = await get.getGithubData(file?.slugs?.github);

    file.stackoverflow_data = await get.getStackoverflowDataByTags(
      file?.tags?.stackoverflow
    );

    await yaml.write(`../copy/tools/${id}.yml`, file);
    console.log(id, "success");

    // sleep
    await new Promise((resolve) => setTimeout(resolve, 15000));
  } catch (e) {
    console.log(`${id}`, e);
    failures.push({
      id,
      error: e,
    });
  }
}).then(() => {
  if (failures.length) {
    return notifySlackUpdateFailures(failures);
  }
});

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}


================================================
FILE: data-update-worker/notifySlack.js
================================================
const fetch = require("node-fetch");
require("dotenv").config();

/**
 * @param {Array<any>} blocks 
 * @returns Promise
 */
const notifySlack = async (blocks) =>
  fetch(process.env.SLACK_WEBHOOK_URL, {
    method: "POST",
    body: JSON.stringify({
      blocks,
    }),
  });

/**
 * @param {Array<{ id: string; error: string }>} failures 
 * @returns Promise
 */
const notifySlackUpdateFailures = async (failures) =>
  notifySlack([
    {
      type: "header",
      text: {
        type: "plain_text",
        text: "⚠️ Failed to update some tools",
        emoji: true,
      },
    },

    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `<${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}|GitHub Run>`,
      },
    },

    ...failures.map((failure) => ({
      type: "section",
      text: {
        type: "mrkdwn",
        text: `*${failure.id}:*\n${failure.error}`,
      },
    })),
  ]);

exports.notifySlack = notifySlack;
exports.notifySlackUpdateFailures = notifySlackUpdateFailures;


================================================
FILE: data-update-worker/package.json
================================================
{
  "name": "job",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^10.0.0",
    "fs": "^0.0.1-security",
    "js-yaml": "^4.1.0",
    "node-fetch": "^2.6.1"
  }
}


================================================
FILE: netlify.toml
================================================
[build]
  publish = ".next"


================================================
FILE: next-sitemap.config.js
================================================
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || "https://awesome.cube.dev/",
  generateRobotsTxt: true, // (optional)
};


================================================
FILE: next.config.js
================================================
const withBundleAnalyzer = require("@next/bundle-analyzer")({
  enabled: process.env.ANALYZE === "true",
});

const ContentSecurityPolicy = `
  default-src 'self';
  script-src 'report-sample' 'self' 'unsafe-eval' 'unsafe-inline';
  style-src 'report-sample' 'self' 'unsafe-inline';
  object-src 'none';
  base-uri 'self';
  connect-src 'self' https://amaranth-leech.gcp-us-central1.cubecloudapp.dev https://track.cube.dev https://graphql.contentful.com;
  font-src 'self';
  frame-src 'self';
  img-src 'self';
  manifest-src 'self';
  media-src 'self';
  worker-src 'none';
`;

/**
 * @type {import('next').NextConfig}
 */
const config = {
    reactStrictMode: true,
    async headers() {
        return [
            {
                source: "/(.*)",
                headers: [
                  {
                    key: "Strict-Transport-Security",
                    value: "max-age=31536000; includeSubDomains;",
                  },
                  {
                      key: 'Content-Security-Policy',
                      value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
                  }
                ]
            },
        ]
    },
}

module.exports = withBundleAnalyzer(config);


================================================
FILE: package.json
================================================
{
  "name": "awesome-dataviz-tools",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "postbuild": "next-sitemap",
    "export": "next export",
    "start": "next start"
  },
  "dependencies": {
    "@cube-dev/purple-banner": "2.0.19",
    "@netlify/plugin-nextjs": "^4.30.3",
    "bootstrap": "^5.0.1",
    "classnames": "^2.3.2",
    "cubedev-tracking": "1.1.0",
    "dayjs": "^1.10.7",
    "isomorphic-unfetch": "^3.1.0",
    "js-yaml": "^3.14.1",
    "next": "^13.1.6",
    "next-seo": "^5.15.0",
    "next-sitemap": "^3.1.49",
    "node-yaml": "^4.0.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-slick": "^0.28.1",
    "react-svg": "^13.0.5",
    "slick-carousel": "^1.8.1"
  },
  "devDependencies": {
    "@netlify/ne
Download .txt
gitextract_elt7bwjc/

├── .github/
│   └── workflows/
│       └── scheduled-data-update.yml
├── .gitignore
├── .netlify/
│   └── state.json
├── .nvmrc
├── LICENSE
├── README.md
├── components/
│   ├── Button/
│   │   ├── Button.jsx
│   │   ├── Button.module.scss
│   │   └── index.js
│   ├── ButtonLanding/
│   │   ├── ButtonLanding.jsx
│   │   └── ButtonLanding.module.css
│   ├── CTAButtons/
│   │   ├── CTAButtons.jsx
│   │   └── CTAButtons.module.css
│   ├── Card/
│   │   ├── Card.jsx
│   │   └── Card.module.scss
│   ├── Chip/
│   │   ├── Chip.jsx
│   │   ├── Chip.module.scss
│   │   └── index.js
│   ├── ExploreToolsCard/
│   │   ├── ExploreToolsCard.jsx
│   │   ├── ExploreToolsCard.module.scss
│   │   └── index.js
│   ├── Footer/
│   │   ├── Footer.jsx
│   │   ├── Footer.module.scss
│   │   └── index.js
│   ├── Gallery/
│   │   ├── Gallery.jsx
│   │   ├── Gallery.module.scss
│   │   └── index.js
│   ├── GetHelpCard/
│   │   ├── GetHelpCard.jsx
│   │   ├── GetHelpCard.module.scss
│   │   └── index.js
│   ├── GetStartedCard/
│   │   ├── GetStartedCard.jsx
│   │   ├── GetStartedCard.module.scss
│   │   └── index.js
│   ├── GlobalSignUp/
│   │   ├── GlobalSignUp.jsx
│   │   └── GlobalSignUp.module.css
│   ├── Header/
│   │   ├── Header.jsx
│   │   ├── Header.module.scss
│   │   └── index.js
│   ├── ListPage/
│   │   ├── ListPage.jsx
│   │   └── index.js
│   ├── Slider/
│   │   ├── Slider.jsx
│   │   ├── Slider.module.scss
│   │   └── index.js
│   ├── Text/
│   │   ├── AccentedText.jsx
│   │   ├── AccentedText.module.scss
│   │   ├── H1.jsx
│   │   ├── H1.module.scss
│   │   ├── H2.jsx
│   │   └── H2.module.scss
│   ├── ToolCard/
│   │   ├── ToolCard.jsx
│   │   ├── ToolCard.module.scss
│   │   └── index.js
│   ├── ToolPage/
│   │   ├── Description.jsx
│   │   ├── Description.module.scss
│   │   ├── DescriptionCards.jsx
│   │   ├── DescriptionCards.module.scss
│   │   ├── Header.jsx
│   │   ├── Header.module.scss
│   │   ├── HowToGetHelp.jsx
│   │   ├── HowToGetHelp.module.scss
│   │   ├── HowToGetStarted.jsx
│   │   ├── HowToGetStarted.module.scss
│   │   ├── Integrations.jsx
│   │   ├── Integrations.module.scss
│   │   ├── Popularity.jsx
│   │   ├── Popularity.module.scss
│   │   ├── ToolPage.jsx
│   │   └── ToolPageForFramework.jsx
│   └── ToolsNumberControl/
│       ├── ToolsNumberControl.jsx
│       ├── ToolsNumberControl.module.scss
│       └── index.js
├── copy/
│   └── tools/
│       ├── .example
│       ├── .extended.example
│       ├── ag-grid.yml
│       ├── amcharts.yml
│       ├── ant-design-charts.yml
│       ├── anychart.yml
│       ├── apexcharts.yml
│       ├── appsmith.yml
│       ├── billboard.yml
│       ├── c3.yml
│       ├── chartist.yml
│       ├── chartjs.yml
│       ├── cytoscape.yml
│       ├── d3.yml
│       ├── datasette.yml
│       ├── deck-gl.yml
│       ├── echarts.yml
│       ├── flot.yml
│       ├── frappe.yml
│       ├── fusioncharts.yml
│       ├── g2.yml
│       ├── g2plot.yml
│       ├── g6.yml
│       ├── google-charts.yml
│       ├── highcharts.yml
│       ├── kepler-gl.yml
│       ├── laue.yml
│       ├── layer-cake.yml
│       ├── leaflet.yml
│       ├── lightweight-charts.yml
│       ├── mapbox-gl.yml
│       ├── material-ui-data-grid.yml
│       ├── metabase.yml
│       ├── muze.yml
│       ├── ngx-charts.yml
│       ├── nivo.yml
│       ├── observable-plot.yml
│       ├── p5.yml
│       ├── pancake.yml
│       ├── perspective.yml
│       ├── plotly.yml
│       ├── plottable.yml
│       ├── pts.yml
│       ├── react-charts.yml
│       ├── reaflow.yml
│       ├── reaviz.yml
│       ├── recharts.yml
│       ├── redash.yml
│       ├── rough.yml
│       ├── roughviz.yml
│       ├── semiotic.yml
│       ├── stackgl.yml
│       ├── superset.yml
│       ├── three.yml
│       ├── toast-ui-chart.yml
│       ├── unovis.yml
│       ├── vega-lite.yml
│       ├── vega.yml
│       ├── victory.yml
│       ├── vis.yml
│       ├── visx.yml
│       ├── vizzu.yml
│       └── zingchart.yml
├── data/
│   ├── filter.js
│   ├── frameworks.js
│   ├── tools.js
│   ├── types.js
│   └── useSlackMembers.js
├── data-update-worker/
│   ├── .gitignore
│   ├── fetchData.js
│   ├── index.js
│   ├── notifySlack.js
│   └── package.json
├── netlify.toml
├── next-sitemap.config.js
├── next.config.js
├── package.json
├── pages/
│   ├── _app.js
│   ├── _document.js
│   ├── for/
│   │   ├── [framework]/
│   │   │   ├── charting-libraries.js
│   │   │   └── index.js
│   │   └── open-source.js
│   ├── index.js
│   └── tools/
│       └── [id]/
│           ├── [framework].js
│           └── index.js
├── public/
│   ├── browserconfig.xml
│   ├── robots.txt
│   ├── site.webmanifest
│   ├── sitemap-0.xml
│   └── sitemap.xml
├── styles/
│   ├── _variables.scss
│   ├── globals.scss
│   └── indexPage.scss
├── update-copy.sh
└── utils/
    ├── number.js
    └── tracking.js
Download .txt
SYMBOL INDEX (70 symbols across 41 files)

FILE: components/Button/Button.jsx
  function Button (line 4) | function Button(props) {

FILE: components/Card/Card.jsx
  function Card (line 4) | function Card(props) {

FILE: components/Chip/Chip.jsx
  function Chip (line 3) | function Chip(props) {

FILE: components/ExploreToolsCard/ExploreToolsCard.jsx
  function ExploreToolsCard (line 4) | function ExploreToolsCard(props) {

FILE: components/Footer/Footer.jsx
  function Footer (line 4) | function Footer() {

FILE: components/Gallery/Gallery.jsx
  function Gallery (line 6) | function Gallery(props) {

FILE: components/GetHelpCard/GetHelpCard.jsx
  function Card (line 4) | function Card(props) {

FILE: components/GetStartedCard/GetStartedCard.jsx
  function Card (line 4) | function Card(props) {

FILE: components/Header/Header.jsx
  function Header (line 5) | function Header() {

FILE: components/ListPage/ListPage.jsx
  function ListPage (line 15) | function ListPage({
  function clearFilters (line 218) | function clearFilters(arrayOfFunctions) {

FILE: components/Slider/Slider.jsx
  function getSettingsThumbs (line 11) | function getSettingsThumbs(slidesToShow) {
  function App (line 23) | function App(props) {

FILE: components/Text/AccentedText.jsx
  function AccentedText (line 3) | function AccentedText(props) {

FILE: components/Text/H1.jsx
  function H1 (line 3) | function H1(props) {

FILE: components/Text/H2.jsx
  function H2 (line 3) | function H2(props) {

FILE: components/ToolCard/ToolCard.jsx
  function ToolCard (line 9) | function ToolCard(props) {
  function getShadowByLabel (line 138) | function getShadowByLabel(label) {

FILE: components/ToolPage/Description.jsx
  function Description (line 3) | function Description(props) {

FILE: components/ToolPage/DescriptionCards.jsx
  function DescriptionCards (line 104) | function DescriptionCards(props) {
  function capitalizeFirstLetter (line 126) | function capitalizeFirstLetter(string) {

FILE: components/ToolPage/Header.jsx
  function Header (line 4) | function Header(props) {

FILE: components/ToolPage/HowToGetHelp.jsx
  function HowToGetHelp (line 6) | function HowToGetHelp(props) {

FILE: components/ToolPage/HowToGetStarted.jsx
  function HowToGetStarted (line 5) | function HowToGetStarted(props) {

FILE: components/ToolPage/Integrations.jsx
  function Integrations (line 6) | function Integrations(props) {

FILE: components/ToolPage/Popularity.jsx
  function Popularity (line 7) | function Popularity(props) {

FILE: components/ToolPage/ToolPage.jsx
  function ToolPage (line 17) | function ToolPage(props) {

FILE: components/ToolPage/ToolPageForFramework.jsx
  function ToolPageForFramework (line 18) | function ToolPageForFramework(props) {

FILE: components/ToolsNumberControl/ToolsNumberControl.jsx
  function ToolsNumberControl (line 3) | function ToolsNumberControl(props) {

FILE: data-update-worker/fetchData.js
  function loadJSON (line 102) | async function loadJSON(url, headers) {
  function loadHeaders (line 110) | async function loadHeaders(url, headers) {
  function getStaleDate (line 119) | function getStaleDate() {
  function getContributorsByResponseHeaders (line 126) | function getContributorsByResponseHeaders(str) {
  function asyncForEach (line 138) | async function asyncForEach(array, callback) {

FILE: data-update-worker/index.js
  function asyncForEach (line 40) | async function asyncForEach(array, callback) {

FILE: data/filter.js
  function getComparator (line 54) | function getComparator(maxFeatureScores) {
  function getMaxFeatureScores (line 67) | function getMaxFeatureScores(tools) {
  function getFeatureWithMaxScore (line 84) | function getFeatureWithMaxScore(tool, maxFeatureScores) {
  function hasTypes (line 136) | function hasTypes(tool, types) {
  function isCompatibleWith (line 140) | function isCompatibleWith(tool, frameworks) {
  function hasLicenses (line 144) | function hasLicenses(tool, licenses) {

FILE: data/tools.js
  function readTools (line 6) | async function readTools() {
  function readTool (line 26) | async function readTool(id) {
  function extendTool (line 31) | async function extendTool(tool, tools) {
  function compare (line 58) | function compare(a, b) {
  function getTools (line 62) | async function getTools() {
  function getTool (line 67) | async function getTool(id) {

FILE: data/useSlackMembers.js
  function useSlackMembers (line 14) | function useSlackMembers() {

FILE: next.config.js
  method headers (line 25) | async headers() {

FILE: pages/_app.js
  function MyApp (line 13) | function MyApp({ Component, pageProps }) {

FILE: pages/_document.js
  class MyDocument (line 3) | class MyDocument extends Document {
    method render (line 4) | render() {

FILE: pages/for/[framework]/charting-libraries.js
  function Page (line 6) | function Page({ tools, framework }) {
  function getStaticPaths (line 20) | async function getStaticPaths() {
  function getStaticProps (line 31) | async function getStaticProps({ params }) {

FILE: pages/for/[framework]/index.js
  function Page (line 6) | function Page({ tools, framework }) {
  function getStaticPaths (line 19) | async function getStaticPaths() {
  function getStaticProps (line 30) | async function getStaticProps({ params }) {

FILE: pages/for/open-source.js
  function Page (line 5) | function Page({ tools }) {
  function getStaticProps (line 15) | async function getStaticProps() {

FILE: pages/index.js
  function Home (line 6) | function Home({ tools }) {
  function getStaticProps (line 23) | async function getStaticProps() {

FILE: pages/tools/[id]/[framework].js
  function Tool (line 9) | function Tool(props) {
  function getStaticPaths (line 15) | async function getStaticPaths() {
  function getStaticProps (line 34) | async function getStaticProps({ params }) {

FILE: pages/tools/[id]/index.js
  function Tool (line 7) | function Tool(props) {
  function getStaticPaths (line 13) | async function getStaticPaths() {
  function getStaticProps (line 31) | async function getStaticProps({ params }) {

FILE: utils/number.js
  function abbreviateNumber (line 1) | function abbreviateNumber(value) {

FILE: utils/tracking.js
  method init (line 2) | async init() {
Condensed preview — 167 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (264K chars).
[
  {
    "path": ".github/workflows/scheduled-data-update.yml",
    "chars": 1831,
    "preview": "# This workflow will do a clean install of node dependencies, build the source code and run tests across different versi"
  },
  {
    "path": ".gitignore",
    "chars": 420,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": ".netlify/state.json",
    "chars": 53,
    "preview": "{\n\t\"siteId\": \"51f8094d-998a-424a-b471-6499f5bf2933\"\n}"
  },
  {
    "path": ".nvmrc",
    "chars": 5,
    "preview": "lts/*"
  },
  {
    "path": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2021 Cube Dev, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 393,
    "preview": "<h1><a href='https://awesome.cube.dev'>awesome.cube.dev</a> — charts, data grids, maps, etc.</h1>\n\nChoose the best tool "
  },
  {
    "path": "components/Button/Button.jsx",
    "chars": 453,
    "preview": "import styles from \"./Button.module.scss\";\nimport Link from \"next/link\";\n\nexport default function Button(props) {\n  retu"
  },
  {
    "path": "components/Button/Button.module.scss",
    "chars": 890,
    "preview": "@import \"/styles/variables\";\n\n.button {\n  font-family: CeraPro;\n  font-size: 20px;\n  // line-height: 25px;\n  text-align:"
  },
  {
    "path": "components/Button/index.js",
    "chars": 54,
    "preview": "import Button from \"./Button\";\nexport default Button;\n"
  },
  {
    "path": "components/ButtonLanding/ButtonLanding.jsx",
    "chars": 2998,
    "preview": "import * as React from 'react';\nimport { useEffect } from 'react';\nimport Link from 'next/link';\nimport classNames from "
  },
  {
    "path": "components/ButtonLanding/ButtonLanding.module.css",
    "chars": 9518,
    "preview": ".Button {\n  --dark: hsl(240, 32%, 10%);\n  --dark_a70: rgba(15, 15, 35, 0.7);\n  --dark_01: var(--dark);\n  --dark_02: hsla"
  },
  {
    "path": "components/CTAButtons/CTAButtons.jsx",
    "chars": 1188,
    "preview": "import * as React from 'react';\nimport classnames from 'classnames/bind';\nimport classes from './CTAButtons.module.css';"
  },
  {
    "path": "components/CTAButtons/CTAButtons.module.css",
    "chars": 40,
    "preview": ".CTAButtons__button {\n  color: white;\n}\n"
  },
  {
    "path": "components/Card/Card.jsx",
    "chars": 1593,
    "preview": "import styles from \"./Card.module.scss\";\nimport { ReactSVG } from \"react-svg\";\n\nexport default function Card(props) {\n  "
  },
  {
    "path": "components/Card/Card.module.scss",
    "chars": 1611,
    "preview": "@import \"/styles/variables\";\n\n.card {\n  width: 100%;\n  padding: 32px;\n  border-radius: 24px;\n  border: 1px solid $dark-0"
  },
  {
    "path": "components/Chip/Chip.jsx",
    "chars": 549,
    "preview": "import styles from \"./Chip.module.scss\";\n\nexport default function Chip(props) {\n  return (\n    <button\n      type=\"butto"
  },
  {
    "path": "components/Chip/Chip.module.scss",
    "chars": 1069,
    "preview": "@import \"/styles/variables\";\n\n.chip {\n  font-family: CeraPro;\n  border: none;\n  padding: 8px 16px;\n  background-color: $"
  },
  {
    "path": "components/Chip/index.js",
    "chars": 48,
    "preview": "import Chip from \"./Chip\";\nexport default Chip;\n"
  },
  {
    "path": "components/ExploreToolsCard/ExploreToolsCard.jsx",
    "chars": 808,
    "preview": "import styles from \"./ExploreToolsCard.module.scss\";\nimport { ReactSVG } from \"react-svg\";\n\nexport default function Expl"
  },
  {
    "path": "components/ExploreToolsCard/ExploreToolsCard.module.scss",
    "chars": 1438,
    "preview": "@import \"/styles/variables\";\n\n.exploreToolsCard {\n  background: $dark-06;\n  border: 1px solid $dark-06;\n  transition: bo"
  },
  {
    "path": "components/ExploreToolsCard/index.js",
    "chars": 84,
    "preview": "import ExploreToolsCard from \"./ExploreToolsCard\";\nexport default ExploreToolsCard;\n"
  },
  {
    "path": "components/Footer/Footer.jsx",
    "chars": 1235,
    "preview": "import styles from \"./Footer.module.scss\";\nimport { ReactSVG } from \"react-svg\";\n\nexport default function Footer() {\n  r"
  },
  {
    "path": "components/Footer/Footer.module.scss",
    "chars": 505,
    "preview": "@import \"/styles/variables\";\n\n.footer {\n  margin-top: 90px;\n  border-top: 2px solid #e7e9ed;\n  padding-top: 64px;\n  padd"
  },
  {
    "path": "components/Footer/index.js",
    "chars": 54,
    "preview": "import Footer from \"./Footer\";\nexport default Footer;\n"
  },
  {
    "path": "components/Gallery/Gallery.jsx",
    "chars": 677,
    "preview": "import dynamic from \"next/dynamic\";\nimport styles from \"./Gallery.module.scss\";\nimport H2 from \"../Text/H2\";\nconst Slide"
  },
  {
    "path": "components/Gallery/Gallery.module.scss",
    "chars": 174,
    "preview": ".gallery {\n  margin-bottom: 104px;\n  @media (max-width: 767.98px) {\n    margin-bottom: 48px;\n  }\n}\n.sliderWrap {\n  @medi"
  },
  {
    "path": "components/Gallery/index.js",
    "chars": 57,
    "preview": "import Gallery from \"./Gallery\";\nexport default Gallery;\n"
  },
  {
    "path": "components/GetHelpCard/GetHelpCard.jsx",
    "chars": 716,
    "preview": "import styles from \"./GetHelpCard.module.scss\";\nimport Link from \"next/link\";\n\nexport default function Card(props) {\n  r"
  },
  {
    "path": "components/GetHelpCard/GetHelpCard.module.scss",
    "chars": 657,
    "preview": "@import \"/styles/variables\";\n.card {\n  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);\n  transition: box-shadow 0.32s"
  },
  {
    "path": "components/GetHelpCard/index.js",
    "chars": 69,
    "preview": "import GetHelpCard from \"./GetHelpCard\";\nexport default GetHelpCard;\n"
  },
  {
    "path": "components/GetStartedCard/GetStartedCard.jsx",
    "chars": 801,
    "preview": "import styles from \"./GetStartedCard.module.scss\";\nimport { ReactSVG } from \"react-svg\";\n\nexport default function Card(p"
  },
  {
    "path": "components/GetStartedCard/GetStartedCard.module.scss",
    "chars": 610,
    "preview": "@import \"/styles/variables\";\n\n.card {\n  box-shadow: 0px 8px 32px rgba(194, 194, 218, 0.3);\n  transition: box-shadow 0.32"
  },
  {
    "path": "components/GetStartedCard/index.js",
    "chars": 78,
    "preview": "import GetStartedCard from \"./GetStartedCard\";\nexport default GetStartedCard;\n"
  },
  {
    "path": "components/GlobalSignUp/GlobalSignUp.jsx",
    "chars": 979,
    "preview": "import * as React from 'react';\nimport classnames from 'classnames/bind';\nimport classes from './GlobalSignUp.module.css"
  },
  {
    "path": "components/GlobalSignUp/GlobalSignUp.module.css",
    "chars": 3225,
    "preview": ".GlobalSignUp {\n  background-color: hsl(240, 32%, 10%);\n  overflow: hidden;\n  position: relative;\n}\n\n.GlobalSignUp::befo"
  },
  {
    "path": "components/Header/Header.jsx",
    "chars": 1149,
    "preview": "import styles from \"./Header.module.scss\";\nimport { useRouter } from \"next/router\";\nimport Link from \"next/link\";\n\nexpor"
  },
  {
    "path": "components/Header/Header.module.scss",
    "chars": 208,
    "preview": ".header {\n  padding: 24px 0;\n\n  &__logo {\n    display: flex;\n    align-items: center;\n    min-height: 28px;\n  }\n\n  &__te"
  },
  {
    "path": "components/Header/index.js",
    "chars": 54,
    "preview": "import Header from \"./Header\";\nexport default Header;\n"
  },
  {
    "path": "components/ListPage/ListPage.jsx",
    "chars": 6882,
    "preview": "import React, { useState, useEffect } from \"react\";\nimport dynamic from \"next/dynamic\";\nimport { useRouter } from \"next/"
  },
  {
    "path": "components/ListPage/index.js",
    "chars": 60,
    "preview": "import ListPage from \"./ListPage\";\nexport default ListPage;\n"
  },
  {
    "path": "components/Slider/Slider.jsx",
    "chars": 2162,
    "preview": "// App.js\nimport React, { useState, useEffect } from \"react\";\nimport styles from \"./Slider.module.scss\";\n// import \"./Ap"
  },
  {
    "path": "components/Slider/Slider.module.scss",
    "chars": 907,
    "preview": ".thumbnailSliderWrap {\n  margin-top: 27px;\n  // height: 85px;\n  @media (max-width: 767.98px) {\n    margin-top: 16px;\n  }"
  },
  {
    "path": "components/Slider/index.js",
    "chars": 54,
    "preview": "import Slider from \"./Slider\";\nexport default Slider;\n"
  },
  {
    "path": "components/Text/AccentedText.jsx",
    "chars": 295,
    "preview": "import styles from \"./AccentedText.module.scss\";\n\nexport default function AccentedText(props) {\n  return (\n    <span\n   "
  },
  {
    "path": "components/Text/AccentedText.module.scss",
    "chars": 54,
    "preview": ".accented {\n  font-size: 24px;\n  line-height: 30px;\n}\n"
  },
  {
    "path": "components/Text/H1.jsx",
    "chars": 139,
    "preview": "import styles from \"./H1.module.scss\";\n\nexport default function H1(props) {\n  return <h1 className={styles.title}>{props"
  },
  {
    "path": "components/Text/H1.module.scss",
    "chars": 223,
    "preview": "@import \"/styles/variables\";\n\n.title {\n  font-style: normal;\n  font-weight: 700;\n  font-size: 64px;\n  line-height: 72px;"
  },
  {
    "path": "components/Text/H2.jsx",
    "chars": 256,
    "preview": "import styles from \"./H2.module.scss\";\n\nexport default function H2(props) {\n  return (\n    <h2\n      {...props}\n      cl"
  },
  {
    "path": "components/Text/H2.module.scss",
    "chars": 188,
    "preview": "@import \"/styles/variables\";\n\n.h2 {\n  font-size: 40px;\n  line-height: 50px;\n  color: $dark;\n  margin: 0;\n  @media (max-w"
  },
  {
    "path": "components/ToolCard/ToolCard.jsx",
    "chars": 5157,
    "preview": "import styles from \"./ToolCard.module.scss\";\nimport dayjs from \"dayjs\";\nimport dayjsUtc from \"dayjs/plugin/utc\";\nimport "
  },
  {
    "path": "components/ToolCard/ToolCard.module.scss",
    "chars": 3441,
    "preview": "@import \"/styles/variables\";\n\n.toolCard {\n  cursor: pointer;\n  padding: 32px;\n  color: $dark;\n  background: #ffffff;\n  b"
  },
  {
    "path": "components/ToolCard/index.js",
    "chars": 60,
    "preview": "import ToolCard from \"./ToolCard\";\nexport default ToolCard;\n"
  },
  {
    "path": "components/ToolPage/Description.jsx",
    "chars": 508,
    "preview": "import styles from \"./Description.module.scss\";\n\nexport default function Description(props) {\n  return (\n    <div classN"
  },
  {
    "path": "components/ToolPage/Description.module.scss",
    "chars": 382,
    "preview": "@import \"/styles/variables\";\n\n.description {\n  margin-top: 24px;\n  &__text {\n    font-size: 22px;\n    line-height: 28px;"
  },
  {
    "path": "components/ToolPage/DescriptionCards.jsx",
    "chars": 3606,
    "preview": "import styles from \"./DescriptionCards.module.scss\";\nimport Card from \"../Card/Card\";\n\nconst getLicense = (props) => {\n "
  },
  {
    "path": "components/ToolPage/DescriptionCards.module.scss",
    "chars": 221,
    "preview": ".descriptionCards {\n  margin-top: 40px;\n  display: flex;\n  margin-bottom: 104px;\n  @media (max-width: 767.98px) {\n    ma"
  },
  {
    "path": "components/ToolPage/Header.jsx",
    "chars": 1391,
    "preview": "import styles from \"./Header.module.scss\";\nimport Button from \"../Button\";\n\nexport default function Header(props) {\n  re"
  },
  {
    "path": "components/ToolPage/Header.module.scss",
    "chars": 1000,
    "preview": "@import \"/styles/variables\";\n\n.header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  @med"
  },
  {
    "path": "components/ToolPage/HowToGetHelp.jsx",
    "chars": 2066,
    "preview": "import styles from \"./HowToGetHelp.module.scss\";\nimport GetHelpCard from \"../GetHelpCard\";\nimport H2 from \"../Text/H2\";\n"
  },
  {
    "path": "components/ToolPage/HowToGetHelp.module.scss",
    "chars": 279,
    "preview": ".HowToGetHelp {\n  margin-bottom: 104px;\n  @media (max-width: 767.98px) {\n    margin-bottom: 48px;\n  }\n}\n.cardWrap {\n  ma"
  },
  {
    "path": "components/ToolPage/HowToGetStarted.jsx",
    "chars": 1160,
    "preview": "import styles from \"./HowToGetStarted.module.scss\";\nimport GetStartedCard from \"../GetStartedCard\";\nimport H2 from \"../T"
  },
  {
    "path": "components/ToolPage/HowToGetStarted.module.scss",
    "chars": 143,
    "preview": ".HowToGetStarted {\n  margin-bottom: 104px;\n}\n.cardWrap {\n  margin-bottom: 26px;\n  @media (max-width: 991.98px) {\n    mar"
  },
  {
    "path": "components/ToolPage/Integrations.jsx",
    "chars": 1321,
    "preview": "import styles from \"./Integrations.module.scss\";\nimport Card from \"../Card/Card\";\nimport H2 from \"../Text/H2\";\nimport fr"
  },
  {
    "path": "components/ToolPage/Integrations.module.scss",
    "chars": 167,
    "preview": ".integration {\n  margin-bottom: 104px;\n  @media (max-width: 767.98px) {\n    margin-bottom: 48px;\n  }\n}\n.cards {\n  displa"
  },
  {
    "path": "components/ToolPage/Popularity.jsx",
    "chars": 2183,
    "preview": "import styles from \"./Popularity.module.scss\";\nimport Card from \"../Card/Card\";\nimport H2 from \"../Text/H2\";\nimport dayj"
  },
  {
    "path": "components/ToolPage/Popularity.module.scss",
    "chars": 256,
    "preview": ".popularity {\n  margin-bottom: 104px;\n  @media (max-width: 767.98px) {\n    margin-bottom: 48px;\n  }\n}\n.bigCardWrap {\n  @"
  },
  {
    "path": "components/ToolPage/ToolPage.jsx",
    "chars": 2789,
    "preview": "import React from \"react\";\nimport dynamic from \"next/dynamic\";\nimport { NextSeo } from 'next-seo';\nimport Header from \"."
  },
  {
    "path": "components/ToolPage/ToolPageForFramework.jsx",
    "chars": 3086,
    "preview": "import React from \"react\";\nimport dynamic from \"next/dynamic\";\nimport { NextSeo } from 'next-seo';\nimport Header from \"."
  },
  {
    "path": "components/ToolsNumberControl/ToolsNumberControl.jsx",
    "chars": 910,
    "preview": "import styles from \"./ToolsNumberControl.module.scss\";\nimport { ReactSVG } from \"react-svg\";\nexport default function Too"
  },
  {
    "path": "components/ToolsNumberControl/ToolsNumberControl.module.scss",
    "chars": 849,
    "preview": "@import \"/styles/variables\";\n\n.toolsControl {\n  min-height: 34px;\n  display: flex;\n  align-items: center;\n  @media (max-"
  },
  {
    "path": "components/ToolsNumberControl/index.js",
    "chars": 90,
    "preview": "import ToolsNumberControl from \"./ToolsNumberControl\";\nexport default ToolsNumberControl;\n"
  },
  {
    "path": "copy/tools/.example",
    "chars": 1630,
    "preview": "title: AG Grid\ndescription: Self-proclaimed best JavaScript grid in the world\nlogo: ag-grid.svg\ndeveloper: Google\n\nbased"
  },
  {
    "path": "copy/tools/.extended.example",
    "chars": 124,
    "preview": "# Everything from .example and also the following fields\n\npositions:\n  total: 45\n  stars: 3\n\npercentages:\n  stale_issues"
  },
  {
    "path": "copy/tools/ag-grid.yml",
    "chars": 1457,
    "preview": "title: AG Grid\ndescription: Self-proclaimed best JavaScript grid in the world\nlogo: ag-grid.svg\nbased_on: null\nlicenses:"
  },
  {
    "path": "copy/tools/amcharts.yml",
    "chars": 1304,
    "preview": "title: amCharts\ndescription: JavaScript charts & maps for all data visualization needs\nlogo: amcharts.svg\nbased_on: null"
  },
  {
    "path": "copy/tools/ant-design-charts.yml",
    "chars": 1356,
    "preview": "title: Ant Design Charts\ndescription: 'React charting library, based on G2Plot, G6, X6, L7'\nlogo: antv.svg\ndeveloper: An"
  },
  {
    "path": "copy/tools/anychart.yml",
    "chars": 1450,
    "preview": "title: AnyChart\ndescription: Interactive JavaScript charts\nlogo: anychart.svg\ndeveloper: null\nbased_on: null\nlicenses:\n "
  },
  {
    "path": "copy/tools/apexcharts.yml",
    "chars": 1407,
    "preview": "title: ApexCharts\ndescription: Modern & interactive open-source charts\nlogo: apexcharts.png\ndeveloper: null\nbased_on: nu"
  },
  {
    "path": "copy/tools/appsmith.yml",
    "chars": 1448,
    "preview": "title: Appsmith\ndescription: Low-code tool for building internal apps using pre-built UI widgets\nlogo: appsmith.svg\ndeve"
  },
  {
    "path": "copy/tools/billboard.yml",
    "chars": 1277,
    "preview": "title: Billboard.js\ndescription: 'Re-usable, easy interface JavaScript chart library based on D3.js'\nlogo: billboard.svg"
  },
  {
    "path": "copy/tools/c3.yml",
    "chars": 1199,
    "preview": "title: C3.js\ndescription: D3.js-based reusable chart library\nlogo: c3.svg\ndeveloper: null\nbased_on:\n  - d3\nlicenses:\n  -"
  },
  {
    "path": "copy/tools/chartist.yml",
    "chars": 1396,
    "preview": "title: Chartist\ndescription: Simple responsive SVG charts\nlogo: chartist.svg\ndeveloper: null\nbased_on: null\nlicenses:\n  "
  },
  {
    "path": "copy/tools/chartjs.yml",
    "chars": 2275,
    "preview": "title: Chart.js\ndescription: Simple yet flexible JavaScript charting for designers & developers\nlogo: chartjs.svg\ndevelo"
  },
  {
    "path": "copy/tools/cytoscape.yml",
    "chars": 1340,
    "preview": "title: Cytoscape.js\ndescription: Graph theory (network) library for visualisation and analysis\nlogo: cytoscape.svg\ndevel"
  },
  {
    "path": "copy/tools/d3.yml",
    "chars": 1349,
    "preview": "title: D3.js\ndescription: JavaScript library for manipulating documents based on data\nlogo: d3.png\ndeveloper: null\nbased"
  },
  {
    "path": "copy/tools/datasette.yml",
    "chars": 1226,
    "preview": "title: Datasette\ndescription: Open-source multi-tool for exploring and publishing data\nlogo: datasette.svg\ndeveloper: nu"
  },
  {
    "path": "copy/tools/deck-gl.yml",
    "chars": 1318,
    "preview": "title: deck.gl\ndescription: WebGL-powered visualization framework for large-scale datasets\nlogo: deck-gl.svg\ndeveloper: "
  },
  {
    "path": "copy/tools/echarts.yml",
    "chars": 2517,
    "preview": "title: Apache ECharts\ndescription: Open-source JavaScript visualization library\nlogo: echarts.png\ndeveloper: null\nbased_"
  },
  {
    "path": "copy/tools/flot.yml",
    "chars": 1147,
    "preview": "title: Flot\ndescription: Attractive JavaScript charts for jQuery\nlogo: flot.svg\ndeveloper: null\nbased_on: null\nlicenses:"
  },
  {
    "path": "copy/tools/frappe.yml",
    "chars": 1106,
    "preview": "title: Frappe\ndescription: >-\n  GitHub-inspired simple and modern SVG charts for the web with zero\n  dependencies\nlogo: "
  },
  {
    "path": "copy/tools/fusioncharts.yml",
    "chars": 1572,
    "preview": "title: FusionCharts\ndescription: JavaScript charts for web & mobile\nlogo: fusioncharts.svg\ndeveloper: null\nbased_on: nul"
  },
  {
    "path": "copy/tools/g2.yml",
    "chars": 1251,
    "preview": "title: G2\ndescription: Highly interactive data-driven visualization grammar for statistical charts\nlogo: antv.svg\ndevelo"
  },
  {
    "path": "copy/tools/g2plot.yml",
    "chars": 1315,
    "preview": "title: G2Plot\ndescription: Interactive and responsive charting library based on the grammar of graphics\nlogo: antv.svg\nd"
  },
  {
    "path": "copy/tools/g6.yml",
    "chars": 1196,
    "preview": "title: G6\ndescription: Graph visualization engine with simplicity and convenience\nlogo: antv.svg\ndeveloper: AntV\nbased_o"
  },
  {
    "path": "copy/tools/google-charts.yml",
    "chars": 1984,
    "preview": "title: Google Charts\ndescription: Interactive charts for browsers and mobile devices\nlogo: google-charts.png\ndeveloper: "
  },
  {
    "path": "copy/tools/highcharts.yml",
    "chars": 1314,
    "preview": "title: Highcharts\ndescription: Modern SVG-based multi-platform charting library\nlogo: highcharts.svg\ndeveloper: null\nbas"
  },
  {
    "path": "copy/tools/kepler-gl.yml",
    "chars": 1338,
    "preview": "title: Kepler.gl\ndescription: Open-source geospatial analysis tool for large-scale data sets\nlogo: kepler-gl.svg\ndevelop"
  },
  {
    "path": "copy/tools/laue.yml",
    "chars": 1130,
    "preview": "title: Laue\ndescription: Modern charts for Vue.js\nlogo: laue.svg\ndeveloper: null\nbased_on: null\nlicenses:\n  - type: open"
  },
  {
    "path": "copy/tools/layer-cake.yml",
    "chars": 1077,
    "preview": "title: Layer Cake\ndescription: Graphics framework for Svelte\nlogo: layer-cake.png\ndeveloper: null\nbased_on: null\nlicense"
  },
  {
    "path": "copy/tools/leaflet.yml",
    "chars": 1330,
    "preview": "title: Leaflet\ndescription: JavaScript library for mobile-friendly interactive maps\nlogo: leafletjs.png\ndeveloper: null\n"
  },
  {
    "path": "copy/tools/lightweight-charts.yml",
    "chars": 1604,
    "preview": "title: Lightweight Charts\ndescription: Financial lightweight charts built with HTML5 canvas\nlogo: lightweight-charts.svg"
  },
  {
    "path": "copy/tools/mapbox-gl.yml",
    "chars": 1544,
    "preview": "title: Mapbox GL JS\ndescription: >-\n  Interactive, thoroughly customizable maps in the browser, powered by vector\n  tile"
  },
  {
    "path": "copy/tools/material-ui-data-grid.yml",
    "chars": 1693,
    "preview": "title: MUI X Data Grid\ndescription: Fast and extendable data table and data grid for React\nlogo: material-ui.svg\ndevelop"
  },
  {
    "path": "copy/tools/metabase.yml",
    "chars": 1570,
    "preview": "title: Metabase\ndescription: 'Easy, open-source way to ask questions and learn from data'\nlogo: metabase.png\ndeveloper: "
  },
  {
    "path": "copy/tools/muze.yml",
    "chars": 1433,
    "preview": "title: Muze\ndescription: Free library for creating exploratory data visualizations using WebAssembly\nlogo: muze.svg\ndeve"
  },
  {
    "path": "copy/tools/ngx-charts.yml",
    "chars": 1145,
    "preview": "title: ngx-charts\ndescription: Declarative charting framework for Angular\nlogo: ngx-charts.svg\ndeveloper: Swimlane\nbased"
  },
  {
    "path": "copy/tools/nivo.yml",
    "chars": 1209,
    "preview": "title: nivo\ndescription: Supercharged React components to easily build dataviz apps\nlogo: nivo.png\ndeveloper: null\nbased"
  },
  {
    "path": "copy/tools/observable-plot.yml",
    "chars": 1407,
    "preview": "title: Observable Plot\ndescription: Concise API for exploratory data visualization\nlogo: observable.png\ndeveloper: null\n"
  },
  {
    "path": "copy/tools/p5.yml",
    "chars": 1294,
    "preview": "title: p5.js\ndescription: >-\n  JavaScript library for creative coding that makes coding accessible and\n  inclusive\nlogo:"
  },
  {
    "path": "copy/tools/pancake.yml",
    "chars": 1074,
    "preview": "title: Pancake\ndescription: 'Responsive charts, JavaScript optional'\nlogo: pancake.png\ndeveloper: null\nbased_on: null\nli"
  },
  {
    "path": "copy/tools/perspective.yml",
    "chars": 1460,
    "preview": "title: Perspective\ndescription: >-\n  Interactive analytics and data visualization component, especially well-suited\n  fo"
  },
  {
    "path": "copy/tools/plotly.yml",
    "chars": 1413,
    "preview": "title: Plotly\ndescription: 'High-level, declarative charting library'\nlogo: plotly.svg\ndeveloper: null\nbased_on:\n  - d3\n"
  },
  {
    "path": "copy/tools/plottable.yml",
    "chars": 1174,
    "preview": "title: Plottable\ndescription: Library of modular chart components built on D3.js\nlogo: plottable.svg\ndeveloper: Palantir"
  },
  {
    "path": "copy/tools/pts.yml",
    "chars": 1201,
    "preview": "title: Pts\ndescription: Library for visualization and creative-coding\nlogo: pts.svg\ndeveloper: null\nbased_on: null\nlicen"
  },
  {
    "path": "copy/tools/react-charts.yml",
    "chars": 1184,
    "preview": "title: React Charts\ndescription: 'Simple, immersive & interactive charts for React'\nlogo: react-charts.svg\ndeveloper: nu"
  },
  {
    "path": "copy/tools/reaflow.yml",
    "chars": 1217,
    "preview": "title: reaflow\ndescription: 'React library for building workflow editors, flow charts, and diagrams'\nlogo: reaflow.png\nd"
  },
  {
    "path": "copy/tools/reaviz.yml",
    "chars": 1084,
    "preview": "title: REAVIZ\ndescription: >-\n  Modular chart library that leverages React natively while using D3.js under\n  the hood\nl"
  },
  {
    "path": "copy/tools/recharts.yml",
    "chars": 1542,
    "preview": "title: Recharts\ndescription: Composable charting library built on React components\nlogo: recharts.png\ndeveloper: null\nba"
  },
  {
    "path": "copy/tools/redash.yml",
    "chars": 1118,
    "preview": "title: Redash\ndescription: Collaborative visualization and dashboarding platform\nlogo: redash.svg\ndeveloper: null\nbased_"
  },
  {
    "path": "copy/tools/rough.yml",
    "chars": 1163,
    "preview": "title: Rough.js\ndescription: 'Graphics library for drawing with a hand-drawn, sketchy appearance'\nlogo: rough.png\ndevelo"
  },
  {
    "path": "copy/tools/roughviz.yml",
    "chars": 1105,
    "preview": "title: roughViz.js\ndescription: >-\n  JavaScript library for creating sketchy/hand-drawn styled charts, based on\n  D3.js,"
  },
  {
    "path": "copy/tools/semiotic.yml",
    "chars": 1173,
    "preview": "title: Semiotic\ndescription: Data visualization framework for React\nlogo: semiotic.png\ndeveloper: null\nbased_on:\n  - d3\n"
  },
  {
    "path": "copy/tools/stackgl.yml",
    "chars": 896,
    "preview": "title: stackgl\ndescription: Open software ecosystem for WebGL\nlogo: stackgl.svg\ndeveloper: null\nbased_on: null\nlicenses:"
  },
  {
    "path": "copy/tools/superset.yml",
    "chars": 1509,
    "preview": "title: Apache Superset\ndescription: Modern data exploration and visualization platform\nlogo: superset.svg\ndeveloper: nul"
  },
  {
    "path": "copy/tools/three.yml",
    "chars": 1346,
    "preview": "title: three.js\ndescription: JavaScript 3D library\nlogo: threejs.svg\ndeveloper: null\nbased_on: null\nlicenses:\n  - type: "
  },
  {
    "path": "copy/tools/toast-ui-chart.yml",
    "chars": 1196,
    "preview": "title: TOAST UI Chart\ndescription: Beautiful chart for data visualization\nlogo: toast-ui-chart.png\ndeveloper: null\nbased"
  },
  {
    "path": "copy/tools/unovis.yml",
    "chars": 1322,
    "preview": "title: Unovis\ndescription: >-\n  Modular data visualization framework for React, Angular, Svelte, and vanilla\n  TypeScrip"
  },
  {
    "path": "copy/tools/vega-lite.yml",
    "chars": 1388,
    "preview": "title: Vega-Lite\ndescription: 'Concise grammar of interactive graphics, built on Vega'\nlogo: vega-lite.svg\ndeveloper: nu"
  },
  {
    "path": "copy/tools/vega.yml",
    "chars": 1335,
    "preview": "title: Vega\ndescription: >-\n  Visualization grammar, a declarative language for creating and sharing\n  visualization des"
  },
  {
    "path": "copy/tools/victory.yml",
    "chars": 1542,
    "preview": "title: Victory\ndescription: React components for modular charting and data visualization\nlogo: victory.png\ndeveloper: Fo"
  },
  {
    "path": "copy/tools/vis.yml",
    "chars": 1201,
    "preview": "title: vis.js\ndescription: Dynamic visualization library\nlogo: visjs.svg\ndeveloper: null\nbased_on: null\nlicenses:\n  - ty"
  },
  {
    "path": "copy/tools/visx.yml",
    "chars": 1374,
    "preview": "title: visx\ndescription: 'Collection of expressive, low-level visualization primitives for React'\nlogo: visx.png\ndevelop"
  },
  {
    "path": "copy/tools/vizzu.yml",
    "chars": 1147,
    "preview": "title: Vizzu\ndescription: Library for animated data visualizations and data stories\nlogo: vizzu.svg\ndeveloper: null\nbase"
  },
  {
    "path": "copy/tools/zingchart.yml",
    "chars": 1402,
    "preview": "title: ZingChart\ndescription: >-\n  Declarative, efficient, and simple JavaScript library for building responsive\n  chart"
  },
  {
    "path": "data/filter.js",
    "chars": 3968,
    "preview": "const filter = (tools, framework, language, license, render, exploreTools) => {\n  const filtered = tools.filter((tool) ="
  },
  {
    "path": "data/frameworks.js",
    "chars": 331,
    "preview": "export default {\n  react: {\n    slug: \"react\",\n    name: \"React\",\n    icon: \"react.svg\",\n  },\n  angular: {\n    slug: \"an"
  },
  {
    "path": "data/tools.js",
    "chars": 1536,
    "preview": "import fs from \"fs\";\nimport yaml from \"node-yaml\";\n\nexport const toolCopyPath = `${process.cwd()}/copy/tools`;\n\nasync fu"
  },
  {
    "path": "data/types.js",
    "chars": 826,
    "preview": "export default {\n  charts: {\n    slug: \"charts\",\n    name: \"Charting libraries\",\n    image: \"chart.svg\",\n    descriptor:"
  },
  {
    "path": "data/useSlackMembers.js",
    "chars": 1085,
    "preview": "import { useState, useEffect } from \"react\";\nimport fetch from \"isomorphic-unfetch\";\nimport abbreviateNumber from \"../ut"
  },
  {
    "path": "data-update-worker/.gitignore",
    "chars": 17,
    "preview": ".env\nnode_modules"
  },
  {
    "path": "data-update-worker/fetchData.js",
    "chars": 3492,
    "preview": "const fetch = require(\"node-fetch\");\nrequire(\"dotenv\").config();\n\nconst getGithubData = async (githubSlug) => {\n  if (!g"
  },
  {
    "path": "data-update-worker/index.js",
    "chars": 1154,
    "preview": "const yaml = require(\"node-yaml\");\nconst fs = require(\"fs\");\nconst get = require(\"./fetchData.js\");\nconst { notifySlackU"
  },
  {
    "path": "data-update-worker/notifySlack.js",
    "chars": 1087,
    "preview": "const fetch = require(\"node-fetch\");\nrequire(\"dotenv\").config();\n\n/**\n * @param {Array<any>} blocks \n * @returns Promise"
  },
  {
    "path": "data-update-worker/package.json",
    "chars": 330,
    "preview": "{\n  \"name\": \"job\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"E"
  },
  {
    "path": "netlify.toml",
    "chars": 28,
    "preview": "[build]\n  publish = \".next\"\n"
  },
  {
    "path": "next-sitemap.config.js",
    "chars": 173,
    "preview": "/** @type {import('next-sitemap').IConfig} */\nmodule.exports = {\n  siteUrl: process.env.SITE_URL || \"https://awesome.cub"
  },
  {
    "path": "next.config.js",
    "chars": 1219,
    "preview": "const withBundleAnalyzer = require(\"@next/bundle-analyzer\")({\n  enabled: process.env.ANALYZE === \"true\",\n});\n\nconst Cont"
  },
  {
    "path": "package.json",
    "chars": 889,
    "preview": "{\n  \"name\": \"awesome-dataviz-tools\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    "
  },
  {
    "path": "pages/_app.js",
    "chars": 2606,
    "preview": "import React, { Fragment, useEffect } from \"react\";\nimport dynamic from \"next/dynamic\";\nimport \"../styles/globals.scss\";"
  },
  {
    "path": "pages/_document.js",
    "chars": 301,
    "preview": "import Document, { Html, Head, Main, NextScript } from 'next/document'\n\nclass MyDocument extends Document {\n  render() {"
  },
  {
    "path": "pages/for/[framework]/charting-libraries.js",
    "chars": 1026,
    "preview": "import ListPage from '../../../components/ListPage';\nimport { getTools } from '../../../data/tools';\nimport { hasTypes, "
  },
  {
    "path": "pages/for/[framework]/index.js",
    "chars": 967,
    "preview": "import ListPage from '../../../components/ListPage';\nimport { getTools } from '../../../data/tools';\nimport { isCompatib"
  },
  {
    "path": "pages/for/open-source.js",
    "chars": 538,
    "preview": "import ListPage from '../../components/ListPage';\nimport { getTools } from '../../data/tools';\nimport { hasLicenses, isC"
  },
  {
    "path": "pages/index.js",
    "chars": 708,
    "preview": "import ListPage from '../components/ListPage';\nimport { getTools } from '../data/tools';\nimport { GlobalSignUp } from '."
  },
  {
    "path": "pages/tools/[id]/[framework].js",
    "chars": 1025,
    "preview": "import React from \"react\";\nimport ToolPage from '../../../components/ToolPage/ToolPage';\n\nimport fs from \"fs\";\nimport { "
  },
  {
    "path": "pages/tools/[id]/index.js",
    "chars": 756,
    "preview": "import React from \"react\";\nimport ToolPage from '../../../components/ToolPage/ToolPage';\n\nimport fs from \"fs\";\nimport { "
  },
  {
    "path": "public/browserconfig.xml",
    "chars": 246,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo"
  },
  {
    "path": "public/robots.txt",
    "chars": 125,
    "preview": "# *\nUser-agent: *\nAllow: /\n\n# Host\nHost: https://awesome.cube.dev/\n\n# Sitemaps\nSitemap: https://awesome.cube.dev/sitemap"
  },
  {
    "path": "public/site.webmanifest",
    "chars": 426,
    "preview": "{\n    \"name\": \"\",\n    \"short_name\": \"\",\n    \"icons\": [\n        {\n            \"src\": \"/android-chrome-192x192.png\",\n     "
  },
  {
    "path": "public/sitemap-0.xml",
    "chars": 51139,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:news=\"http://ww"
  },
  {
    "path": "public/sitemap.xml",
    "chars": 190,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n<sitemap><loc>"
  },
  {
    "path": "styles/_variables.scss",
    "chars": 429,
    "preview": "$dark: #141446;\n$dark-02: #43436b;\n$dark-03: #727290;\n$dark-04: #a1a1b5;\n$dark-05: #d5d5e2;\n$dark-06: #f8f8f8;\n$light-da"
  },
  {
    "path": "styles/globals.scss",
    "chars": 2121,
    "preview": "@import \"/styles/variables\";\nhtml,\nbody {\n  padding: 0;\n  margin: 0;\n  font-family: CeraPro, -apple-system, BlinkMacSyst"
  },
  {
    "path": "styles/indexPage.scss",
    "chars": 56,
    "preview": ".counter {\n  margin-top: 80px;\n  margin-bottom: 80px;\n}\n"
  },
  {
    "path": "update-copy.sh",
    "chars": 53,
    "preview": "cd data-update-worker && npm install && node index.js"
  },
  {
    "path": "utils/number.js",
    "chars": 796,
    "preview": "export default function abbreviateNumber(value) {\n  if (!value) {\n    return null;\n  }\n  var newValue = value;\n  if (val"
  },
  {
    "path": "utils/tracking.js",
    "chars": 645,
    "preview": "export const tracking = {\n  async init() {\n    tracking.gateway = await import('cubedev-tracking');\n    window.cubedevEv"
  }
]

About this extraction

This page contains the full source code of the cube-js/awesome-tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 167 files (238.5 KB), approximately 78.3k tokens, and a symbol index with 70 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!