Giter Site home page Giter Site logo

grommet-toolbox's Introduction

grommet-toolbox

Dependency Status devDependency Status

[DEPRECATED]: Please use grommet pack and grommet check available in the new grommet-cli

Developer Environment for Grommet applications with the following built-in features:

  • Ability to create a production ready distribution with minified JavaScript and CSS
  • Ability to sync your distribution to a remote location
  • JavaScript and Sass linters
  • Development server with hot-reloading
  • Test infrastructure based on tape and gulp watch
  • Code coverage using Istanbul
  • Convert raw svgs to Grommet icons with accessibility support
  • Bundle your project and its dependencies in a compressed file

grommet-toolbox runs on top of Gulp.

Install

npm install grommet-toolbox --save-dev

Basic usage

gulpfile.babel.js

import gulp from 'gulp';
import grommetToolbox from 'grommet-toolbox';

var opts = {
  copyAssets: [
    'src/index.html',
    {
      asset: 'src/img/**',
      dist: 'dist/img/'
    }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: ['src/js/**/*.js'],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/index.scss',
  devServerPort: 9000
};

grommetToolbox(gulp, opts);

Grommet-toolbox augments gulp object with these additional tasks:

  • gulp copy: uses copyAssets option to move files to distribution folder.
  • gulp generate-icons: uses icons option to convert raw svg icons to Grommet icons.
  • gulp scsslint: uses scssAssets option to lint your Sass code.
  • gulp jslint: uses jsAssets and testPaths options to lint your JavaScript code.
  • gulp dev: starts a webpack dev server with hot reloading. See options for example configuration.
    • --config: Set the path of the config file to use.
    • --no-preprocess: Skips preprocess tasks.
    • --no-open: Skips opening dev server url in a browser.
  • gulp dist: prepares your application/library for production.
    • --config: Set the path of the config file to use.
    • --no-preprocess: Skips preprocess tasks.
    • --no-minify: Skips minifying JS code.
  • gulp sync: uses sync option to sync distribution content to a remote server.
  • gulp test: uses testPaths option to execute tests based on Tape.
  • gulp test:watch: runs tests and watch for changes to execute the tests again.
  • gulp test:coverage: runs tests and generates a code coverage report.
  • gulp test:update: runs all the tests and updates the Jest snapshots for the project.
  • gulp pack: uses the package.json dependencies object to create a compressed file with all the dependencies included.

Recommended Usage

As your configuration grows it gets really difficult to manipulate everything inside a single gulp file. Grommet-toolbox offers a config file where you can store your application specific settings. This is the recommended way of using this tool. Now you will have two files, grommet-toolbox.config.js and gulpfile.babel.js:

grommet-toolbox.config.js

export default {
  copyAssets: [
    'src/index.html',
    {
      asset: 'src/img/**',
      dist: 'dist/img/'
    }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: ['src/js/**/*.js'],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/index.scss',
  devServerPort: 9000
};

gulpfile.babel.js

import gulp from 'gulp';
import grommetToolbox from 'grommet-toolbox';

grommetToolbox(gulp);

grommet-toolbox will look into your application's root folder and extract the configuration for your project.

Options

property type description default example
argv object Optional. Default cli args set on gulp tasks. See above. {} {open: false}
base string Optional. Base working directory process.cwd() base: '.'
copyAssets array Optional. Assets to be copied to the distribution folder undefined See copyAssets WIKI
eslintConfigPath string Optional. Path to your custom eslint config file undefined eslintConfigPath: path.resolve(__dirname, '../.eslintrc')
eslintOverride string Optional. Path to your custom eslint overrides undefined eslintOverride: path.resolve(__dirname, 'customEslintrc')
devPreprocess array Optional. A set of tasks to run before gulp dev undefined ['set-webpack-alias']
devServerDisableHot boolean Optional. If true, will disable webpack hot reloading false devServerDisableHot: true
devServerHost string Optional. Host address for the webpack dev server 'localhost' devServerHost: '127.0.0.1'
devServerPort int Optional. Sets a listener port for the webpack dev server 8080 devServerPort: 9000
devServerProxy object Optional. Proxy requests from the webpack dev server undefined devServerProxy: { '/rest/*': 'http://localhost:8114' }
devServer object Optional. Any additional options for the webpack dev server undefined devServer: { https: true }
dist string Optional. Location of the distribution folder 'dist' dist: 'distribution'
distPreprocess array Optional. A set of tasks to run before gulp dist undefined ['dist-css']
env object Optional. Adds environment variables for Node undefined { DEV_MODE: 'true'}
icons object Optional. Converts raw icons to a Grommet icon undefined See icon WIKI
jsAssets array Required. Location of your JavaScript Assets [] jsAssets: ['src/js/**/*.js']
jsLoader object Optional. If you want to use another webpack loader for your JavaScript Assets react-loader `{ test: /.jsx?$/, loader: 'babel-loader', exclude: /(node_modules
lintCache boolean Optional. If true, it will skip caching for linters (build time increases). true lintCache: false
mainJs string Required. Location of your main JavaScript file undefined mainJs: 'src/js/index.js'
preCommitTasks array Optional. The gulp tasks to run as git pre-commit hooks jslint, scsslint, test ['jslint','scsslint','test']
publicPath string Optional. Your main app context '/' publichPath: '/docs'
scssAssets array Optional. Location of your Sass Assets [] scssAssets: ['src/scss/**/*.scss']
scssLoader object Optional. If you want to use another webpack loader for your SCSS Assets react-loader { test: /\.scss?$/, loader: 'file?name=assets/css/[name].css!sass'}
scsslint boolean (deprecated) Optional. If false, it will skip Sass linting true scsslint: false
sync object Optional. Syncs your content to a remote server undefined sync: { hostname: 'grommet.io', username: 'grommet', remoteDestination: '/var/www/html/'}
testPaths array Optional. Location of your test assets undefined testPaths: ['test/**/*.js']
webpack object Optional. Additional webpack options to be used in gulp dist undefined See Webpack Configuration
webpackProfile string Optional. Location to save webpack profile stats in json format. undefined webpackProfile: './stats.json'

Example

See grommet-todo

Advanced

See Advanced Usage wiki

grommet-toolbox's People

Contributors

alansouzati avatar coltonw avatar eabay avatar ericsoderberghp avatar michaelgilley avatar phuson avatar tobinford avatar

Stargazers

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

Watchers

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

grommet-toolbox's Issues

Make Grommet-Toolbox a generator app?

@alansouzati What are your thoughts on replacing grommet-toolbox with a generator app like, e.g., create-react-app?

Doing this would unhook the tight coupling between the grommet ecosystem and an app so that setup could easily be scaffolded for new users while also allowing for a greater level of customization and little-to-no reliance on grommet-toolbox releases. We think this would cut down on the required issue->PR->review->release loop that must take place every time a feature or proprietary change is needed.

Thoughts?

@nickjvm

localization encoding

submitting the issue after consulting with Alan.

The zh-CN.js file is being complied in a way that the characters are not encoded. I checked the type of the file I committed, and like all the others lang (that seems to work) it is indeed in "UTF-8" so there shouldn't be any problem with encoding.

This is an example of the compiled file:
image

I'm thinking that the only thing that may cause it, is the build process that grommet is using.
Please note that Japanese is working well.

Bests,
Shimi

Avoid use of cache mechanism

Usually implementation of cache mechanism (like gulp-cache) relies on inotify to detect file changes, but there are some issues regarding the shared folder among host and VM.

Currently we are facing some instability issues because of that, mainly when we have host using different OS flavor.

In my current project, we are using VirtualBox and VMware.

VirtualBox issue: https://www.virtualbox.org/ticket/10660

eslint failAfterError very disruptive

Running a grommet-toolbox based environment in a container. When I introduce a lint error, failAfterError causes gulp to exit, which then exits the container.

Instead, I want the error reported, and the environment to continue to watch for the next file change. Having to restart gulp after any error is really disruptive to the development workflow.

Support for destructured imports

It would be great if grommet-toolbox would allow using destructuring syntax.

import {Menu, Anchor, Checkbox} from 'grommet'

instead of

import Menu from 'grommet/components/Menu';
import Anchor from 'grommet/components/Anchor';
import CheckBox from 'grommet/components/CheckBox';

without importing the whole grommet package into the build.

You might consider using https://github.com/lodash/babel-plugin-lodash for that purpose. Despite the name it allows 'cherry-picking' of modules.
e.g. nwb (https://github.com/insin/nwb) has the plugin configured in that generic way.

insin/nwb#141
https://github.com/insin/nwb/blob/master/docs/Configuration.md#cherrypick-string--arraystring

Any option to remove comments in compressed index.js after run 'gulp dist'?

Hi experts,

we want to remove comments in compressed index.js after run 'gulp dist'.

Then I didn't find an option we can input in webpack.dist.config.js.

Only can do is change it codes as or set skipMinify as 'true' and then compress it by ourselves.

if (!argv.skipMinify) {
config.plugins.push(new _webpack2.default.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
},

}));
}

Here, my question is that, could give an option to user that make it easy set comments as 'false' to close comment output?

Thanks,

Robert

Trying to load current options causes errors with FS

Hi,

I am trying to access current options according to wiki by addingh the following lines to a file:

import {getOptions} from 'grommet-toolbox';

const options = getOptions();

Unfortunately, when I do that, the application stops working and I see a bunch of errors. Stacktraces shows a lot of errors like this:

ERROR in ./~/default-require-extensions/js.js
Module not found: Error: Cannot resolve module 'fs' in C:\Users\lachto\Documents\Chat2.0\node_modules\default-require-ex
tensions
 @ ./~/default-require-extensions/js.js 3:9-22
webpack: Failed to compile.

Can anybody help me with the issue?

URLs with dot are rewritten when using webpack-dev-server

Edit: appending a / to the end of the URL would show a different error. Now I would get Cannot GET /foo/bar.xyz

I've been having issues with running gulp dev on my application which makes use of periods (".") in the URL. For example, /foo/bar.xyz would get rewritten to /bar.xyz. I suspect it is the following line:

} else if (req.url.match(/.+\/.*\.[^\/]*$/)) { // file

else if (req.url.match(/.+\/.*\.[^\/]*$/)) { // file
    res.redirect(301, req.url.replace(/.*\/([^\/]*)$/, '/$1'));
}

Is there a workaround?

Cannot set extension resolution for jsx files

I used to drop module extension in my sources such as:

import LoginForm from '../components/LoginForm';

However adding:

    webpack: {
    resolve: {
        extensions: ['', '.jsx', '.js', '.scss', '.css']
    }
    }

does not work because these settings are always overridden by predefined settings.

Not able set many of the webpack config.

I am trying to add headers to web page requests while developing. On file grommet-toolbox.config.js I tried add:

...
  webpack: {
    devServer: {
      headers: {
        "Authorization": "Bearer jfdsdfj2423408892"
      }
    }
  }
...

I also tried to add devServer key directly, instead of embedding inside of webpack key, as mentioned in README instructions. But no luck.

This is very much needed for our use-case. Now I have to resort to running third party server like Django or Flask just to redirect Grommet webapp URL with required headers.

webpack.module.loaders breaks the build

Liked the toolbox but got a problem :)

Here is my gulpfile.js:

var gulp = require('gulp');
var path = require('path');
var fs = require('fs');
var grommetToolbox = require('grommet-toolbox').default;

var alias = p => path.resolve(__dirname, 'node_modules', p);

var opts = {
  base: '.',
  dist: path.resolve(__dirname, 'dist/'),
  copyAssets: [
    'src/index.html',
    { asset: 'src/img/**', dist: 'dist/img/' }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: ['src/js/**/*.js'],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/index.scss',
  webpack: {
    resolve: {
      root: ['src/js', 'src/scss', 'node_modules'].map(p => path.resolve(__dirname, p)),
      alias: {
        'grommet-index/scss': alias('grommet-index/src/scss'),
        'grommet-index': alias('grommet-index/src/js'),
        'grommet/scss': alias('grommet/src/scss'),
        'grommet': alias('grommet/src/js')
      }
    },
    module: {
      loaders: [{
        test: /\.svg$/,
        loader: 'file-loader?mimetype=image/svg+xml'
      }]
    }
  },
  devServerPort: 4000,
  devServerProxy: {
    '/api/*': {
      target: process.env.SERVER_URL,
      rewrite: function(req) {
        req.url = req.url.replace(/^\/api/, '');
      }
    }
  }
};

grommetToolbox(gulp, opts);

There is a file loader for .svg files but webpack does not produce a healthy built.

Console output:

[01:08:20] Using gulpfile ~/workspace/projects/bigs/services/uinext/gulpfile.js
[01:08:20] Starting 'dev-preprocess'...
[01:08:20] Starting 'preprocess'...
[01:08:20] Starting 'clean'...
[01:08:20] Finished 'clean' after 6.38 ms
[01:08:20] Starting 'copy'...
[01:08:20] Finished 'copy' after 17 ms
[01:08:20] Starting 'generate-icons'...
[01:08:20] Finished 'generate-icons' after 32 μs
[01:08:20] Starting 'jslint'...
[01:08:23] Finished 'jslint' after 2.65 s
[01:08:23] Starting 'scsslint'...
[scsslint] scsslint skipped!
[scsslint] scss-lint is not installed. Please install ruby and the ruby gem scss-lint.
[01:08:23] Finished 'scsslint' after 1.15 ms
[01:08:23] Finished 'preprocess' after 2.67 s
[01:08:23] Finished 'dev-preprocess' after 2.67 s
[01:08:23] Starting 'dev'...
[01:08:23] Finished 'dev' after 137 ms
[webpack-dev-server] started: opening the app in your default browser...
[01:08:23] Opening http://localhost:4000/webpack-dev-server/ using the default OS app
Hash: 894c5fada0850735885b
Version: webpack 1.12.14
Time: 1131ms
                              Asset     Size  Chunks             Chunk Names
d38545ef77a2ad664a19320f7d246218.js  1.95 kB          [emitted]  
                           index.js   274 kB       0  [emitted]  app
chunk    {0} index.js (app) 216 kB [rendered]
    [0] multi app 52 bytes {0} [built]
    [1] (webpack)-dev-server/client?http://localhost:4000 2.67 kB {0} [built]
    [2] ./~/url/url.js 22.3 kB {0} [built]
    [3] ./~/punycode/punycode.js 14.7 kB {0} [built]
    [4] (webpack)/buildin/module.js 251 bytes {0} [built]
    [5] ./~/querystring/index.js 127 bytes {0} [built]
    [6] ./~/querystring/decode.js 2.4 kB {0} [built]
    [7] ./~/querystring/encode.js 2.09 kB {0} [built]
    [8] ./~/sockjs-client/lib/entry.js 244 bytes {0} [built]
    [9] ./~/sockjs-client/lib/transport-list.js 613 bytes {0} [built]
   [10] ./~/sockjs-client/lib/transport/websocket.js 2.68 kB {0} [built]
   [11] ./~/process/browser.js 2.06 kB {0} [built]
   [12] ./~/sockjs-client/lib/utils/event.js 2 kB {0} [built]
   [13] ./~/sockjs-client/lib/utils/random.js 746 bytes {0} [built]
   [14] ./~/sockjs-client/lib/utils/browser-crypto.js 438 bytes {0} [built]
   [15] ./~/sockjs-client/lib/utils/url.js 975 bytes {0} [built]
   [16] ./~/url-parse/index.js 8.09 kB {0} [built]
   [17] ./~/requires-port/index.js 753 bytes {0} [built]
   [18] ./~/url-parse/lolcation.js 1.58 kB {0} [built]
   [19] ./~/querystringify/index.js 1.3 kB {0} [built]
   [20] ./~/debug/browser.js 3.76 kB {0} [built]
   [21] ./~/debug/debug.js 4.1 kB {0} [built]
   [22] ./~/ms/index.js 2.33 kB {0} [built]
   [23] ./~/inherits/inherits_browser.js 672 bytes {0} [built]
   [24] ./~/sockjs-client/lib/event/emitter.js 1.11 kB {0} [built]
   [25] ./~/sockjs-client/lib/event/eventtarget.js 1.75 kB {0} [built]
   [26] ./~/sockjs-client/lib/transport/browser/websocket.js 58 bytes {0} [built]
   [27] ./~/sockjs-client/lib/transport/xhr-streaming.js 1.25 kB {0} [built]
   [28] ./~/sockjs-client/lib/transport/lib/ajax-based.js 1.31 kB {0} [built]
   [29] ./~/sockjs-client/lib/transport/lib/sender-receiver.js 1.15 kB {0} [built]
   [30] ./~/sockjs-client/lib/transport/lib/buffered-sender.js 2.3 kB {0} [built]
   [31] ./~/sockjs-client/lib/transport/lib/polling.js 1.32 kB {0} [built]
   [32] ./~/sockjs-client/lib/transport/receiver/xhr.js 1.58 kB {0} [built]
   [33] ./~/sockjs-client/lib/transport/sender/xhr-cors.js 343 bytes {0} [built]
   [34] ./~/sockjs-client/lib/transport/browser/abstract-xhr.js 4.67 kB {0} [built]
   [35] ./~/sockjs-client/lib/transport/sender/xhr-local.js 352 bytes {0} [built]
   [36] ./~/sockjs-client/lib/utils/browser.js 560 bytes {0} [built]
   [37] ./~/sockjs-client/lib/transport/xdr-streaming.js 984 bytes {0} [built]
   [38] ./~/sockjs-client/lib/transport/sender/xdr.js 2.42 kB {0} [built]
   [39] ./~/sockjs-client/lib/transport/eventsource.js 766 bytes {0} [built]
   [40] ./~/sockjs-client/lib/transport/receiver/eventsource.js 1.58 kB {0} [built]
   [41] ./~/sockjs-client/lib/transport/browser/eventsource.js 37 bytes {0} [built]
   [42] ./~/sockjs-client/lib/transport/lib/iframe-wrap.js 981 bytes {0} [built]
   [43] ./~/sockjs-client/lib/transport/iframe.js 3.8 kB {0} [built]
   [44] ./~/json3/lib/json3.js 43.3 kB {0} [built]
   [45] (webpack)/buildin/amd-options.js 43 bytes {0} [built]
   [46] ./~/sockjs-client/lib/version.js 25 bytes {0} [built]
   [47] ./~/sockjs-client/lib/utils/iframe.js 4.95 kB {0} [built]
   [48] ./~/sockjs-client/lib/utils/object.js 532 bytes {0} [built]
   [49] ./~/sockjs-client/lib/transport/htmlfile.js 710 bytes {0} [built]
   [50] ./~/sockjs-client/lib/transport/receiver/htmlfile.js 2.17 kB {0} [built]
   [51] ./~/sockjs-client/lib/transport/xhr-polling.js 894 bytes {0} [built]
   [52] ./~/sockjs-client/lib/transport/xdr-polling.js 712 bytes {0} [built]
   [53] ./~/sockjs-client/lib/transport/jsonp-polling.js 1.02 kB {0} [built]
   [54] ./~/sockjs-client/lib/transport/receiver/jsonp.js 5.49 kB {0} [built]
   [55] ./~/sockjs-client/lib/transport/sender/jsonp.js 2.46 kB {0} [built]
   [56] ./~/sockjs-client/lib/main.js 11.9 kB {0} [built]
   [57] ./~/sockjs-client/lib/shims.js 18.2 kB {0} [built]
   [58] ./~/sockjs-client/lib/utils/escape.js 2.31 kB {0} [built]
   [59] ./~/sockjs-client/lib/utils/transport.js 1.35 kB {0} [built]
   [60] ./~/sockjs-client/lib/utils/log.js 386 bytes {0} [built]
   [61] ./~/sockjs-client/lib/event/event.js 485 bytes {0} [built]
   [62] ./~/sockjs-client/lib/location.js 177 bytes {0} [built]
   [63] ./~/sockjs-client/lib/event/close.js 295 bytes {0} [built]
   [64] ./~/sockjs-client/lib/event/trans-message.js 292 bytes {0} [built]
   [65] ./~/sockjs-client/lib/info-receiver.js 2.22 kB {0} [built]
   [66] ./~/sockjs-client/lib/transport/sender/xhr-fake.js 456 bytes {0} [built]
   [67] ./~/sockjs-client/lib/info-iframe.js 1.52 kB {0} [built]
   [68] ./~/sockjs-client/lib/info-iframe-receiver.js 791 bytes {0} [built]
   [69] ./~/sockjs-client/lib/info-ajax.js 1.03 kB {0} [built]
   [70] ./~/sockjs-client/lib/iframe-bootstrap.js 2.9 kB {0} [built]
   [71] ./~/sockjs-client/lib/facade.js 723 bytes {0} [built]
   [72] ./~/strip-ansi/index.js 161 bytes {0} [built]
   [73] ./~/ansi-regex/index.js 135 bytes {0} [built]
   [74] (webpack)/hot/only-dev-server.js 2.25 kB {0} [built]
   [75] (webpack)/hot/log-apply-result.js 813 bytes {0} [built]
   [76] ./src/js/index.js 81 bytes {0} [built]
webpack: bundle is now VALID.

When I remove the module section from options, it builds but gives errors for svg files.

Same config was working with old utils and as far as I can see, there is no change in how module loaders are handled.

I couldn't figure out where the problem is.

We need a option to disable jsLint

As we have an option to disable the scsslint, it would be useful to have an option to disable jsLint also. At least the build should be completed, even if there is a jsList error.

I'm facing some instability issue (that I'm still trying to figure out what's happening), but until I fixed it, I could not proceed with my develop.

Optimizations for Dist

  • react-hot is present during gulp dist
  • sass loader should be compressed w/ sourcemaps (only in dev mode)
  • Is UglifyJS leaving only license comments or all comments?

Debugging (source maps) does not work as expected

Well, under Chrome it does not show jsx files so I have to deal with babelized javascript.
Now I'm using

    webpack: {
        devtool: 'eval-source-map'
        }

entry in mu grommet-toolbox.config.js and it does solve the issue but brings the other one - gulp dist now produces 13Mb file because of source maps are included for production build.

What is the correct and optimal way to get things right?

Hot reload

I cant get to work hot reload. I was also testing on grommet-todo, grommet-blog. It does not work anywhere.

gulp dist runs tests but ignores the result

I would expect when the tests fail for the build to stop and fail, but instead it just keeps on running and considers the gulp build a success. Seems like a bug to me but I am not sure I can get to it right away like my other 2 pull requests.

gulp dist should exit with errorcode on build error

Moving issue from grommet core project (grommet/grommet#220)

Submitted by @kylebyerly-hp

Found while changing node version.

Anytime that you change node version you have to rebuild any item with node-gyp.

Similar reproduction without having to change node-version for easy fix

npm i && rm -rf node_modules/node-sass && gulp dist
# should return non zero, returns 1
echo $?

Allow running a specific unit test.

It would be helpful to be able to run just a single unit test. This would allow triaging test issues via console.log without having to wade through the time and output of other tests.

gulp dist no longer copies assets

I don't know if this was an intentional change but it seems like your last commit removed copy from preprocess so dist no longer copies assets. It is easy enough to add copy to my build but it was unexpected and broke our continuously deployed demo UI.

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.