Git Product home page Git Product logo

state-of-js-graphql-results-api's Introduction

StateOfJS API

Translations

You can use the GraphQL API to get more info about a specific translation locale. Here is a sample query:

query GetLocaleData {
  locale(localeId: "ru-RU") {
    completion
    totalCount
    translatedCount
    translators
    untranslatedKeys
  }
}

Data Format

Type definition

The response are normalized using the following structure:

// Might be extended depending on the survey we add.
type SurveyType =
    | 'state_of_js'
    | 'state_of_css'

// Depends on the survey type, for example `css_frameworks`.
type SectionId = string

// Depends on the survey type, for example `react`.
type ToolId = string

type ToolExperience =
    | 'would_use'
    | 'would_not_use'
    | 'interested'
    | 'not_interested'
    | 'never_heard'

// Other tools mentioned for a given section,
// which have been normalized, for example,
// other CSS frameworks, it comes from the freeform
// field available for each major section of the survey:
// "Other options you use for the current section not mentioned in the list above".
type SectionOtherTools = {
    others: NormalizedValueMultiple
}

// Other tools not specific to the survey type,
// for example browsers, IDE... which can contain
// both predefined choices and an optional freeform answer
// which get normalized.
type OtherTools = {
    choices: string[]
    others?: NormalizedValueMultiple
}

// Depends on the survey type, for example `flexbox`.
type FeatureId = string

type FeatureExperience =
    | 'never_heard'
    | 'heard'
    | 'used'

type ResourceType =
    | 'blogs_news_magazines'
    | 'podcasts'
    | 'sites_courses'

// Depends on the survey type, for example `css_easy_to_learn`.
type OpinionId = string

// Date string in ISO format (ISO 8601).
type DateString = string

// Generic rating.
type Rating = 0 | 1 | 2 | 3 | 4

// Used to rate opinions, for example:
// "CSS is a programming language".
// Goes from strong disagreement to strong agreement.
type AgreementRating = Rating

// Used to rate happiness, for example:
// "How happy are you with the general state of CSS?".
// Goes from very unhappy to very happy.
type HappinessRating = Rating

// Used to represent the normalization of free form
// fields, when a single normalized result is expected,
// used for example for `user_info.source`.
type NormalizedValueUnique = {
    // Raw input
    raw: string
    // String representation of the regexp which led
    // to the normalization.
    pattern: string
    // Normalized value which matched `pattern`.
    normalized: string
}

type NormalizedValueMultiple = {
    // Raw input
    raw: string
    // String representations of the regexps which led
    // to the normalizations.
    patterns: string[]
    // Normalized values which matched `pattern`,
    // match `patterns` order, meaning `normalized[1]`
    // was generated using `patterns[1]`.
    normalized: string[]
}

type WorkExperienceRange =
    | 'range_less_than_1'
    | 'range_1_2'
    | 'range_2_5'
    | 'range_5_10'
    | 'range_10_20'
    | 'range_more_than_20'

type CompanySizeRange =
    | 'range_1'
    | 'range_1_5'
    | 'range_5_10'
    | 'range_10_20'
    | 'range_20_50'
    | 'range_50_100'
    | 'range_100_1000'
    | 'range_more_than_1000'

type SalaryRange =
    | 'range_work_for_free'
    | 'range_0_10'
    | 'range_10_30'
    | 'range_30_50'
    | 'range_50_100'
    | 'range_100_200'
    | 'range_more_than_200'

type Gender =
    | 'male'
    | 'female'
    | 'non_binary'
    | 'prefer_not_to_say'

// Might change depending on the surveys we make.
type JobTitle =
    | 'cto'
    | 'front_end_developer'
    | 'full_stack_developer'
    | 'back_end_developer'
    | 'web_developer'
    | 'web_designer'
    | 'ui_designer'
    | 'ux_designer'

type RaceEthnicityId =
    | 'white_european'
    | 'hispanic_latin'
    | 'east_asian'
    | 'middle_eastern'
    | 'black_african'
    | 'multiracial'
    | 'biracial'
    | 'native_american_islander_australian'

// Proficiency rating for a specific domain,
// from completely inexperienced to expert.
type Proficiency = Rating

type EnvironmentId = string

interface NormalizedResponse {
    // Auto generated ID.
    _id: number
    // Reference `users` collection,
    // only available for survey made in the Vulcan survey system.
    userId?: number
    // Reference non-normalized `responses` collection,
    // only available for survey made in the Vulcan survey system.
    responseId?: number
    survey: SurveyType
    // Year the response belongs too
    year: number
    // Concatenation of `survey` + `year`
    surveySlug: string
    // Creation and update dates, can be used to compute
    // time spent filling out the survey.
    createdAt: DateString
    updatedAt: DateString
    // Date when the response was normalized.
    generatedAt: DateString
    user_info: {
        os: string
        device: string
        browser: string
        version: string
        browser_type: string
        user_agent: string
        platform: string
        // How participants found the survey,
        // it's a freeform field which is normalized.
        source: NormalizedValueUnique
        referrer: string
        job_title: JobTitle
        years_of_experience: WorkExperienceRange
        company_size: CompanySizeRange
        yearly_salary: SalaryRange
        gender: Gender
        skin_tone: number
        country_name: string
        country_alpha3: string
        backend_proficiency: Proficiency
        javascript_proficiency: Proficiency
        css_proficiency: Proficiency
        race_ethnicity: {
            choices: [RaceEthnicityId]
        }
        // Used to identify users, especially useful when
        // we want to cross responses for surveys filled out
        // on a different platform (typically TypeForm),
        // where we don't have a corresponding entry
        // in the `users` collection.
        hash: string
    }
    tools: Record<ToolId, {
        experience: ToolExperience
    }>
    tools_others: Record<
        SectionId | string,
        SectionOtherTools | OtherTools
    >
    features: Record<FeatureId, {
        experience: FeatureExperience
    }>
    // Contains lists of features grouped by
    // specific topics, for example, CSS units.
    // Participants are asked to select the
    // features they used from a predefined list
    // of options.
    features_others: Record<string, {
        choices: string[]
    }>
    // Opinions on a specific topic, expressed as a rating.
    opinions: Record<OpinionId, AgreementRating>
    // Opinions on a specific topic, freeform field, for example:
    // "What do you feel is currently missing from CSS?"
    // value is normalized.
    opinions_others: Record<OpinionId, {
        others: NormalizedValueMultiple
    }>
    // How happy participants are about certain topics,
    // can be both tied to sections or generic.
    happiness: Record<string, HappinessRating>
    // Resources relevant to the survey type such as blogs, courses...
    resources: Record<ResourceType, {
        // Predefined options selection.
        choices: string[]
        // Optional freeform answer, normalized.
        others?: NormalizedValueMultiple
    }>
    // Contain answers related to environments,
    // for example, browsers, form factors...
    // It has both choices and rating based answers.
    environments: Record<EnvironmentId, Rating | {
        choices: string[]
    }>
}

Example data

Here's an example of a sample survey response for the 2020 State of CSS survey:

{
  "_id": "123foobar",
  "surveySlug": "css2020",
  "createdAt": "2020-10-13T21:32:25.571Z",
  "updatedAt": "2020-10-13T21:50:08.693Z",
  "year": 2020,
  "completion": 89,
  "userId": "456barbaz",
  "responseId": "789foobaz",
  "generatedAt": "2020-10-13T21:53:55.219Z",
  "survey": "css",
  "user_info": {
    "device": "desktop",
    "browser": "Chrome",
    "version": "86.0.4240.75",
    "os": "macOS",
    "referrer": "",
    "backend_proficiency": 3,
    "company_size": "range_1",
    "css_proficiency": 4,
    "gender": "male",
    "how_did_user_find_out_about_the_survey": "I made it!",
    "javascript_proficiency": 4,
    "job_title": "full_stack_developer",
    "race_ethnicity": {
      "choices": [
        "white_european"
      ]
    },
    "yearly_salary": "range_10_30",
    "years_of_experience": "range_10_20",
    "country": "JP",
    "email_hash": "63bea61eeda07586ced5fc60400672b2b61b06986445a1de665a827a5456d519",
    "country_name": "Japan",
    "country_alpha3": "JPN"
  },
  "features": {
    "aspect_ratio": {
      "experience": "never_heard"
    },
    "content_visibility": {
      "experience": "never_heard"
    },
    "exclusions": {
      "experience": "never_heard"
    },
    "flexbox": {
      "experience": "used"
    }
  },
  "features_others": {
    "attributes": {
      "choices": [
        "presence",
        "equality"
      ]
    },
    "combinators": {
      "choices": [
        "descendant",
        "child",
        "next_sibling"
      ]
    }
  },
  "happiness": {
    "pre_post_processors": 3,
    "css_frameworks": 3,
    "css_methodologies": 2,
    "css_in_js": 2,
    "state_of_css": 3,
    "state_of_the_web": 3
  },
  "tools": {
    "less": {
      "experience": "not_interested"
    },
    "post_css": {
      "experience": "would_use"
    },
    "sass": {
      "experience": "would_use"
    },
    "stylus": {
      "experience": "not_interested"
    }
  },
  "tools_others": {
    "css_frameworks": {
      "others": {
        "raw": "angular native, react native",
        "normalized": [
          "angular_native",
          "reactnative"
        ],
        "patterns": [
          "/angular( |-)?native/i",
          "/react( |-|_)?native/i"
        ]
      }
    },
    "utilities": {
      "choices": [
        "stylelint",
        "purge_css"
      ],
      "others": {
        "raw": "some other utility",
        "normalized": [],
        "patterns": []
      }
    },
    "text_editors": {
      "others": {
        "raw": "angular native",
        "normalized": [
          "angular_native"
        ],
        "patterns": [
          "/angular( |-)?native/i"
        ]
      }
    }
  },
  "environments": {
    "browsers": {
      "choices": [
        "chrome",
        "safari",
        "firefox",
        "safari_ios"
      ]
    },
    "css_for_email": 1,
    "css_for_print": 0,
    "form_factors": {
      "choices": [
        "desktop",
        "smartphone"
      ]
    }
  },
  "resources": {
    "blogs_news_magazines": {
      "choices": [
        "css_tricks",
        "codrops",
        "sidebar",
        "heydesigner"
      ],
      "others": {
        "raw": "some other blog",
        "normalized": [],
        "patterns": []
      }
    },
    "podcasts": {
      "choices": [
        "shop_talk_show",
        "syntaxfm"
      ]
    },
    "sites_courses": {
      "choices": [
        "stack_overflow",
        "mdn"
      ]
    }
  },
  "opinions": {
    "css_easy_to_learn": 1,
    "css_evolving_slowly": 1,
    "css_is_programming_language": 4,
    "enjoy_writing_css": 2,
    "selector_nesting_to_be_avoided": 3,
    "utility_classes_to_be_avoided": 1
  },
  "opinions_other": {
    "currently_missing_from_css": {
      "others": {
        "raw": "Container queries",
        "normalized": [
          "container_queries"
        ],
        "patterns": [
          "/container ?queries/i"
        ]
      }
    }
  }
}

state-of-js-graphql-results-api's People

Contributors

abaldeweg avatar adamkudrna avatar avocadovenom avatar berkayyildiz avatar coooraph avatar dependabot[bot] avatar ervinismu avatar jaideepghosh avatar lex111 avatar luk-str avatar magdaavram avatar maxaltena avatar michaelrambeau avatar mingjunlu avatar myakura avatar nunhes avatar omhet avatar plouc avatar sachag avatar sarahfossheim avatar scarsu avatar sgrove avatar shadowings-zy avatar shramkoweb avatar sk8guerra avatar socunanena avatar spice-z avatar timbergus avatar tiovoit avatar webistomin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

state-of-js-graphql-results-api's Issues

I want to translate to Korean

Hello.
thank you for StateOfJS.
every year, I see the your survey. this is very helpful to me.
Actually, I want to translate to Korean.
So How can I help you do that?
just can I PR ?

bug: years_of_experience and company_size filters are not working as expected with GraphQL API

When I use the graphql API and attempt to filter by either company size or year of experience, I am returned a response that is the same as if no filter parameters had been submitted.

It appears that the issue may likely lie in your filters.js file here (lines 83-84, 88-89)
https://github.com/StateOfJS/state-of-js-graphql-results-api/blob/413b6a07b3ac38cead184823311892ebdad756a3/src/filters.ts

It seems like these two variables didn't get switched from camelCase to snake_case. This is repeated up in the interface definition as well. (Lines 16-17 of the same file)

Mongo Aggregation Help: Facets Breakdown

Currently, you can search for e.g. the age range distribution of survey respondents and get data that looks like this:

{
  "data": {
    "survey": {
      "demographics": {
        "age": {
          "year": {
            "buckets": [
              {
                "id": "range_less_than_10",
                "count": 3,
                "percentage": 0
              },
              {
                "id": "range_10_18",
                "count": 95,
                "percentage": 1.5
              },
              {
                "id": "range_18_24",
                "count": 678,
                "percentage": 10.4
              },
              {
                "id": "range_25_34",
                "count": 3289,
                "percentage": 50.6
              },
              {
                "id": "range_35_44",
                "count": 1901,
                "percentage": 29.2
              },
              {
                "id": "range_45_54",
                "count": 433,
                "percentage": 6.7
              },
              {
                "id": "range_55_64",
                "count": 83,
                "percentage": 1.3
              },
              {
                "id": "range_more_than_65",
                "count": 18,
                "percentage": 0.3
              }
            ]
          }
        }
      }
    }
  }
}

You can also filter this by e.g. gender to limit the results to women.

But I would like to add an option to group the results by gender (or any other demographic "facet" – not sure if that's the proper term by the way?). So the resulting data would look something like this:

{
  "data": {
    "survey": {
      "demographics": {
        "age": {
          "year": {
            "facets": [
              {
                "type": "gender", // could be "country", "age", "salary", etc.
                "id": "female", // the value we're currently grouping by
                "buckets": [
                  {
                    "id": "range_less_than_10",
                    "count": 3,
                    "percentage": 0
                  },
                  {
                    "id": "range_10_18",
                    "count": 95,
                    "percentage": 1.5
                  },
                  {
                    "id": "range_18_24",
                    "count": 678,
                    "percentage": 10.4
                  },
                  {
                    "id": "range_25_34",
                    "count": 3289,
                    "percentage": 50.6
                  },
                  {
                    "id": "range_35_44",
                    "count": 1901,
                    "percentage": 29.2
                  },
                  {
                    "id": "range_45_54",
                    "count": 433,
                    "percentage": 6.7
                  },
                  {
                    "id": "range_55_64",
                    "count": 83,
                    "percentage": 1.3
                  },
                  {
                    "id": "range_more_than_65",
                    "count": 18,
                    "percentage": 0.3
                  }
                ]
              },
              {
                "type": "gender",
                "id": "male",
                "buckets": [
                  {
                    "id": "range_less_than_10",
                    "count": 3,
                    "percentage": 0
                  },
                  {
                    "id": "range_10_18",
                    "count": 95,
                    "percentage": 1.5
                  }
                  // etc.
                ]
              },

              {
                "type": "gender",
                "id": "non_binary",
                "buckets": [
                  // ...
                ]
              }
            ]
          }
        }
      }
    }
  }
}

The current Mongo aggregation pipeline is fairly simple:

const pipeline = [
            {
                $match: match
            },
            {
                $unwind: {
                    path: `$${key}`
                }
            },
            {
                $group: {
                    _id: {
                        id: `$${key}`,
                        year: '$year'
                    },
                    count: { $sum: 1 }
                }
            },
            {
                $project: {
                    _id: 0,
                    id: '$_id.id',
                    year: '$_id.year',
                    count: 1
                }
            },
            { $sort: { [sort]: order } }
        ]

I'm guessing I need to add a second $group stage, but I'm not quite sure how to do it…

Also note that the facet that items are grouped by will be set dynamically (or can be empty, in which case the facets array would just contain a single element with "type": "default" and "id": "default").

Add missing resources and other projects

Screen Shot 2019-12-21 at 16 21 21

There are still quite a few resources not properly formatted and/or linked up on:

https://2019.stateofjs.com/resources/

As well as a few other tools on:

https://2019.stateofjs.com/other-tools/

If you'd like to help you can submit a PR to add the missing items to this file:

https://github.com/StateOfJS/state-of-js-graphql-results-api/blob/master/src/data/entities.yml

Following this structure:

- id: syntaxfm
  name: Syntax
  homepage: https://syntax.fm/
  description: A great podcast
  category: podcasts

Where id is the character string used in the chart (some of them are truncated which makes copy/pasting them a bit harder, sorry… You can hover on the bar to see the full string).

name will be used as the properly formatted name, and homepage will optionally be the URL linked to. description and category are optional and not currently used but we might use them in the future if we want to build out a more fleshed out directory of JavaScript resources.

Note that once a PR is merged to add in more resources, we still need to manually clear the API cache and rebuild the site before the changes are live, so it won't be instant.

Important: to avoid many people doing overlapping work please post here indicating which block's resources (Other Blogs & Magazines, Podcasts etc.) you want to work on and make sure nobody else is working on that first.

Anonymized dev database

There should be a separate, anonymized development database for people who want to work on the API.

Query Builder/Filtering UI

(I'm opening this thread here even though it's more about the results UI because it's not really specific to any given results repo)

Problem

No matter which demographics we reach with the survey, we'll always have minoritized segments by definition. The issue is that these segments then get drowned out by the majority, and you can't always hear their voices. For example, if e.g. a JavaScript library was especially popular in a given country, or did a really great job reaching out to women, that wouldn't necessarily be reflected in the current survey results.

Solution

The solution would be a filtering/querying UI somewhat similar to the Mac OS search dialog, for example.

Screen Shot 2021-04-02 at 9 48 28

Scenarios

  • Show React trends in France.
  • Show Salary limited to Black/African-American women.
  • Show front-end rankings for women who earn more than $X in Spain.
  • etc.

Things to Consider

Flexibility vs Simplicity

Ideally, we'd support any combination of filters. At the same time, we can anticipate some filters being the most used (non-male, non-white, etc.) and it would make sense not to require people to re-specify them manually each time.

Operators

It'd be great to support in, not in, equal to, etc. operators for filtering.

In-chart vs Inter-chart

Do we want to compare chart A to chart B, or else within a single chart compare different datasets? In other words, having two different bar charts vs having a single bar chart with double bars for each datapoint (the first solution would be much easier to implement, the second one is not currently supported by the API and wouldn't work for some chart types).

Filtering All Charts

If someone lives in China they probably want to add the "China" filter to every chart without having to manually specify it each time.

State

Ideally, each chart would preserve its filtering state in case of a page reload, component re-rendering, etc.

Applicability

Can every filter be applied to every chart? How do we account for e.g. filtering the "gender identity" chart by "gender identity"? Disable it, return an error?

Sharing

Can we make the filtered charts shareable? Generating a dynamic thumbnail preview seems hard, but we can probably at least make them linkable? This means loading state via the URL?

Ideas

What I currently have in mind would be a system that provides predefined presets in combination with the ability to create your own custom filters. Ideally, once a custom filter is created it would then be available as a preset for all other charts to save people time.

Mongo Aggregations help for bracket questions

I'm struggling a bit to figure out the correct mongo aggregations to achieve this:

Input

Data for the 8-player tournament bracket-style questions is stored in the following format, where each triplet is of the form [first player, second player, winner]:

const bracketResult = [
  [7, 6, 6], // first round
  [4, 0, 0], // first round
  [5, 2, 2], // first round
  [3, 1, 3], // first round
  [6, 0, 6], // semi-finals
  [2, 3, 3], // semi-finals
  [6, 3, 6], // finals
];

Desired Output

I would like to output two different data views.

1. Wins Aggregation

In this view, each player would have the following stats:

  • total number of wins (and winning percentage)
  • total number of wins (and winning percentage) in a first-round match-up
  • total number of wins (and winning percentage) in a semi-finals match-up
  • total number of wins (and winning percentage) in a finals match-up

So we would end up with an 8-item array, where each item has these eight datapoints. For example:

{
 id: 'player_A',
 overall: {
   count: 123,
   percentage: 23
  },
 round1: {
   count: 123,
   percentage: 23
  },
 round2: {
   count: 123,
   percentage: 23
  },
 round3: {
   count: 123,
   percentage: 23
  }
}

(I've already managed to calculate the total number of wins by the way)

2. Match-ups Aggregation

In this view, a given Player A would have the following stats:

  • total number of wins (and winning percentage) against player B
  • same against player C
  • same against player D
  • etc.

So we would end up with eight 7-item arrays. For example:

{
  id: 'player_A',
  matchups: [
    {
      id: 'player_B',
      wins: 123,
      percentage: 23
   },

    {
      id: 'player_C',
      wins: 123,
      percentage: 23
   }

   // etc.
  ]
}

Spanish Translations

I wanted to start translating it, so following our fellow japanese friends, i'll follow their style to organize it!

As far as I checked, some files already have partial translations.

If you want to contribute Spanish translation, please let us know here!

  • accounts.yml : Done by @sk8Guerra !
  • common.yml : Done by @sk8Guerra !
  • homepage.yml : TODO by
  • results.yml : Done by @sk8Guerra !
  • state_of_css_2020.yml: TODO by
  • state_of_css.yml: TODO by
  • state_of_js_2020_survey.yml : Done by @Arkalex !
  • state_of_js_2020.yml : Done by @Arkalex !
  • state_of_js.yml: TODO by
  • surveys.yml: Done by @Arkalex !

Translations

Update: see readme here


This thread will contain all info related to translating the State of CSS and State of JS surveys going forward.

Getting Started

The YAML files to translate live in this current repo, which contains our API:

IMPORTANT: also check that there aren't any existing PRs for the language you want to translate first!

Getting Credit

Every translator will be credited on any site that makes use of the translations, starting with the survey-taking app. You can add your name here if it's not already there.

Translation API

You can get extra data such as the completion percentage for a locale or the untranslated strings via our API, available at:

Here is a sample query:

query GetLocaleData {
  locale(localeId: "ru-RU") {
    completion
    totalCount
    translatedCount
    translators
    untranslatedKeys
  }
}

Translation Files

Surveys App

These strings are related to the app that you use to fill out the actual survey.

  • surveys.yml
  • accounts.yml
  • state_of_js_2020_survey.yml

Results App

These strings only appear in the static site that displays the survey results and stats.

  • results.yml
  • state_of_css_2020.yml
  • state_of_js_2020.yml

Both

These strings appear in both.

  • common.yml
  • state_of_css.yml
  • state_of_js.yml

Other

  • homepage.yml

Joining Translation Teams

It's recommended you join the translation team for the language you want to translate.

Previous Translations

You may also want to take a look at previous year's translations if that helps:

🇳🇱 Dutch translations

🇳🇱 Dutch translations

For all the Dutchy out there, let's translate!
Voor alle Nederlanders onder ons, laten we vertalen!

List of translations

File Author Status DONE?
accounts.yml @MaxAltena DONE ✔️
common.yml @MaxAltena DONE ✔️
homepage.yml @MaxAltena DONE ✔️
results.yml @MaxAltena DONE ✔️
state_of_css_2020.yml @MaxAltena DONE ✔️
state_of_css.yml @MaxAltena DONE ✔️
state_of_js_2020_survey.yml @MaxAltena DONE ✔️
state_of_js_2020.yml @MaxAltena DONE ✔️
state_of_js.yml @MaxAltena DONE ✔️
surveys.yml @MaxAltena DONE ✔️

🙌Japanese Translation🙌(日本語翻訳)

A part of files are translated.
一部のファイルは翻訳済みです。

To avoid conflicts, I made a translation list .
If you want to contribute Japanese translation, please let us know here!
コンフリクトを避けるため、翻訳リストを作りました。
もし翻訳に貢献したい場合、ぜひここで知らせてください!

Translation List

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.