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 ================================================

awesome.cube.dev — charts, data grids, maps, etc.

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

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 ( {props.children} ); } ================================================ 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 = ( ); 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 = {loader}; } if (href) { if (href.startsWith('/')) { return ( {children} ); } return ( {children} ); } return ( ); } ); 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 ( <> ); }; ================================================ 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 (
{props.icons && props.icons.map((icon) => { return ( ); })} {props.icon && ( )}
{props.text}
{props.description && (
{props.description}
)} {props.smallText && (
{props.smallText}
)} {props.footerText && (
)}
); } ================================================ 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 ( ); } ================================================ 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 (

') }} >

{props.image && ( )}
); } ================================================ 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 ( ); } ================================================ 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 (

Gallery

{props.link && (
All examples →
)}
); } ================================================ 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 (
{props.icon && (
)} {props.title &&
{props.title}
} {props.footer &&
{props.footer}
}
); } ================================================ 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 (
{props.icon && ( )} {props.type &&
{props.type}
} {props.title &&
{props.title}
} {props.link && (
Read more →
)}
); } ================================================ 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 (

Deliver better data, faster—with Cube.

{children}
); }; ================================================ 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 (
Cube {children}} > Awesome tools
); } 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 ( <>

{title}
for application developers

{showType && (
{Object.values(allTypes).map((type, i) => ( setItem(exploreTools, setExploreTools, type.slug) } active={exploreTools.includes(type.slug) ? "active" : null} text={type.name} image={type.image} /> ))}
)} {showCompatibleWith && (
Compatible with {Object.values(allFrameworks).map((framework) => ( setItem(frameworks, setFrameworks, framework.slug) } /> ))}
)}
With support for setItem(languages, setLanguages, "typescript")} /> {showLicense && ( and )} {showLicense && ( <> setItem(licenses, setLicenses, "open-source")} /> setItem(licenses, setLicenses, "proprietary")} /> license )}
Rendering setItem(renders, setRenders, "canvas")} /> setItem(renders, setRenders, "svg")} /> setItem(renders, setRenders, "html")} />
{ clearFilters([ setExploreTools, setFrameworks, setLanguages, setLicenses, setRenders, ]); }} />
{filteredTools && filteredTools.map((tool) => (
{/* to lazy load on scroll need to set heigth */}
))}
); } 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 (
setSlider1(slider)} > {props.slidesData && props.slidesData.map((slide, i) => (
{`Preview
))}
setSlider2(slider)} > {props.slidesData && props.slidesData.map((slide, i) => (
{`Thumbnail
))}
); } 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 ( {props.children} ); } ================================================ 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

{props.children}

; } ================================================ 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 (

{props.children}

); } ================================================ 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 (
{`${props.title}

{props.title || ""} {props.developer && (  by {props.developer} )}

{props?.github_data && (
GitHub stars
{`${props.title} {abbreviateNumber(props?.github_data?.stars) || "-"}
)} {props.frameworks && props.frameworks.length > 0 && (
Framework
{props.frameworks && props.frameworks.map((framework, i) => { return (
{framework !== "Universal" ? ( {`${props.title} ) : null} {props.frameworks.length === 1 && ( {framework === "vanilla-js" ? "vanilla JS" : framework} )}
); })}
)} {language && (
Language
{language ? ( {`${props.title} ) : null} {language}
)} {props?.github_data?.last_release?.date && (
Last release
{dayjs(props?.github_data?.last_release?.date) .utc() .format("MMM DD, YYYY") || "-"}
)}
{props.feature_label && (
{`${props.title}
)}
); } 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 (
{props.description}
{props.based && (
Based on {props.based.map((tag) => ( {tag} ))}
)}
); } ================================================ 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 ( {capitalizeFirstLetter(s)} {index === frameworksOnly.length - 1 ? " " : ", "} ); }), 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 (
{props.licenses && (
)} {props.frameworks && props.slugs.github && (
)} {props.languages && (
)}
); } 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 (
{`${props.title}

{props.title} {props.developer && (  by {props.developer} )} {props.framework && (  for {props.framework} developers )}

{props.achievement && (
tool label
)}
{props.github && ( )} {props.website && ( )}
); } ================================================ 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 (

How to
Get Help

{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 ? (
) : null; })}
); } ================================================ 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 (

How to
Get Started

{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 (
); })} {/*
*/}
); } ================================================ 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 (

{props.integration ? frameworks[props.integration.framework].name : "Framework"} Support

{integrations.map(integration => { const framework = frameworks[integration.framework] const link = integration.links?.website ? integration.links.website : `https://github.com/${integration.slugs.github}`; return (
); })}
); } ================================================ 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 (

Popularity
& Relevance

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`} />
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 )} % older than 1 year`} />
{props?.github?.last_release?.date && ( )}
); } ================================================ 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 ( <>
{props.gallery && props.gallery.length !== 0 && ( )} {props.github_data && ( )} {props.integrations?.length > 0 && ( )} {props.content && props.content.length > 0 && ( )}
); } ================================================ 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 ( <>
{integration && ( )} {props.gallery && props.gallery.length !== 0 && ( )} {props.github_data && ( )} {props.content && props.content.length > 0 && ( )}
); } ================================================ 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 (
{props.filteredTools.length} {text}
{props.isChanged !== 0 && ( )}
); } ================================================ 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} 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/next": "^1.4.3", "@next/bundle-analyzer": "^13.1.6", "sass": "^1.32.13" } } ================================================ FILE: pages/_app.js ================================================ import React, { Fragment, useEffect } from "react"; import dynamic from "next/dynamic"; import "../styles/globals.scss"; import "bootstrap/dist/css/bootstrap-grid.min.css"; import Head from "next/head"; import Header from "../components/Header"; import PurpleBanner from "@cube-dev/purple-banner"; import { DefaultSeo } from "next-seo"; import { useRouter } from "next/router"; const Footer = dynamic(() => import("../components/Footer")); function MyApp({ Component, pageProps }) { useEffect(() => { const { page } = require("cubedev-tracking"); page(); }, []); const router = useRouter(); return (