GithubHelp home page GithubHelp logo

cfpb / capital-framework Goto Github PK

View Code? Open in Web Editor NEW
55.0 55.0 29.0 80.42 MB

The Consumer Financial Protection Bureau's user interface framework

Home Page: https://cfpb.github.io/capital-framework/

License: Creative Commons Zero v1.0 Universal

HTML 100.00%
capital-framework frontend-components

capital-framework's People

Contributors

anselmbradford avatar ascott1 avatar awolfe76 avatar cfarm avatar cfpbot avatar chosak avatar contolini avatar dcmouyard avatar himedlooff avatar jimmynotjim avatar kimberlymunoz avatar mistergone avatar niqjohnson avatar scotchester avatar sebworks avatar sephcoster avatar virginiacc avatar wpears 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

Watchers

 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

capital-framework's Issues

Make this framework easy to use for other projects

Originally posted by @himedlooff.


I know this is generic sounding but maybe we can focus this to something like "make bower compatible"?

Should we emulate topcoat.io's organization where modules are separate repo's?

Misc research

VIDEO: Nicolas Gallagher — CSS Application Architecture (SmashingConf)

The current state of the Web platform makes working with, and maintaining lots of HTML and CSS a painful task. Even modestly-sized applications can quickly end up with tens of thousands of lines of HTML and CSS. And dozens of developers may need to work with the UI code on a daily basis.

Without an HTML/CSS application architecture, things can quickly get out of hand. This talk will look at the design of the SUIT framework, and the use of tooling to support and test HTML/CSS development.

Create a docs site

Another idea to centralize docs for all components and the master repo is to create a Capital Framework doc site using DOCter. Within this site we can centralize a lot of the info that is duplicated across each component README and CONTRIBUTING files. This would save us a lot of hassle if we need to make doc changes that affect all components because we would only have to change it once. Of course this means an initial change to all components where we slim down the README and CONTRIBUTING and add in links to the docs site but it's worth it in the long run.

Content to add to docs site:

  • README:
    • About the toolset and workflow
    • Getting started with the Capital Framework master repo
    • Getting started with Capital Framework components
  • CONTRIBUTING:
    • Making contributions (use powerpoint workflow slides to illustrate?)
    • Coding style
    • Browser testing
    • JS testing
    • Governance notes
    • Licensing
  • Misc.

Then edit each repo to link to the docs instead of duplicating information (with the exception of TERMS and anything else that should stay).

Component repos need a build process

In order to properly test individual components we need a test page in each one. This page will be used to test acceptance criteria.

We'll need

  • Gruntfile to bring in dependency and compile .less
  • Demo page in demo folder
  • HTML test page that includes the component markup and dependency component markup

Notes

  • First focus on local testing, we can figure out a gh-pages kind of solution later
  • This should deprecate fj-component-aid

Is there a benefit to adding the `cf-` prefix to component filenames?

@himedlooff:

We've been using filenames like typography.less and buttons.less. I recently accepted a PR from @contolini where he used cf-expandables.js/less.

What's the benefit of adding the prefix?

@contolini:

With jquery plugins I'm used to including the entire plugin's name in the filename but since expandables is part of a larger framework the prefix probably isn't necessary.

@himedlooff:

I dunno, seems kind of smart to add it. Incase they get thrown into a folder with a bunch of other scripts/stylesheets then there will be less potential conflict.

@Scotchester:

/shrug. I don't have a problem with it.

@himedlooff:

Aight, let's do it.

Dependency version pinning thoughts

We need to figure out how we should handle dependency versions.

Steps

  • Decide on use of latest, ~, or a pinned version number in Capital Framework for both Bower and NPM. Decision: use ~
  • Research use of https://gemnasium.com for tracking NPM dependency updates.
  • Research a gemansium-type tool for keeping track of Bower dependency version updates.
    • Gemnasium now handles Bower dependencies as well.

Create grunt-capital-framework task to aid in integration with existing projects

Because integrating the framework's build process (i.e., its Gruntfile) with an existing project's build process could be very messy.

It also ensures that updates to the framework's build process don't need to be manually integrated into the project's build.

Ultimately, this should make the integration step very simple: adding a single new Grunt task to the project's Gruntfile and setting options to fit the project's needs.

Inspiration:

Create a components roadmap doc

If people are interested in creating new components it would be nice to have a prioritized roadmap along with an inventory of older code that has already been written that could potentially be leveraged.

For example here is a list of JS Components pulled together by @danny8000 that we have written at the CFPB at one time or another:

  • Show / Hide:
    • Chuck's
    • Dan's (in GPRA)
    • Armin's (in Paying for College)
  • Tabset:
    • Dan's (in GPRA)
  • Dropdown Menu: (cf.gov global menubar)
  • Accordion:
    • Dan's (in GPRA)
  • And many others...

Document the Gulp tasks

It would be nice to describe what the tasks are doing so others can modify/tweak this repo for their own projects. For example in the Workflow section of the readme, step three says:

grunt vendor – Pulls in Bower components.

This is good enough for the readme but there needs to be further explanation. For example this task also routes vendor assets for you, concatenates all of the cf components, rewrites img and font asset locations, etc. This is useful information to know and documented on our docs site.

Ideas for explaining the tasks

  • bower-install
    Downloads dependencies and routes dependency assets that are flagged in the exportsOverride section of bower.json into the demo folder.
  • concat
    Concatenates dependency styles.
  • copy
    Copies dependency assets that have been routed to the demo folder during the bower-install task into the docs folder.

...

Research JS dependency management

The main question:

Is script dependency something that we need in Capital Framework components, or is it something we only need in the Capital Framework demo when illustrating usage of our JS components?

Create releases with GitHub API/Gulp?

As we want to distribute zip files for each release, we should think about using Grunt to create the releases via the GitHub API and eliminate the need to upload the file through the web interface.

This might leverage an existing task like grunt-release, or it could be an extension of grunt-cfpb-internal. I probably favor the latter.

Research Yeoman

What is Yeoman and how does Yeoman differ from Grunt?

Yeoman will allow you to construct a new project quickly so you don't have to cobble together all of the pieces yourself. By pieces I mean things like getting the latest jQuery, getting the latest modernizr, creating grunt tasks, pulling in frameworks and dependencies.

Yo scaffolds out a new application, writing your Grunt configuration and pulling in relevant Grunt tasks that you might need for your build.
http://yeoman.io/

Yeoman builds upon a number of open-source tools to offer an opinionated workflow that helps developers achieve common tasks more easily. Grunt.js is one of these tools and powers our underlying build process and task plugin architecture.
On top of this architecture, we've highly customized tasks, profiles and systems which work well together and also provide developers with features like our generator system and Twitter Bower integration. Yeoman takes care of configuring your Gruntfile and setup to support Sass, CoffeeScript and Require.js/r.js out of the box. With additional features like wiring, an improved server and init, we like to think of ourselves as a helper project on top of Grunt.
Developers are free to continue using any Grunt tasks with Yeoman and there should remain a good level of cross-tool task compatibility.
http://yeoman.io/faq.html

What is the difference between Grunt Init & Yeoman?

Yeoman plans to completely subsume grunt-init
gruntjs/grunt-init#31

What is the difference between Yeoman and Brunch?

brunch/brunch#408

Creating your own Yeoman generators

Generators are instructions on how to scaffold out a type of project. There are many existing generators but you can create your own to meet your needs. You can also create sub generators to scaffold out common templates that might be needed within a project.

Questions about the README

The instructions mention a dist folder but I can't find it. Should it be here?

Also then there is a mv front-end my-project which I believe should be mv capital-framework my-project

Use bower to pull in dependencies

(Links to internal URLs have been removed.)

  • Create a vendor folder as a sibling to js/ and css/
  • Use bower to pull in the external dependencies (component breakdown)
  • Figure out how to move static assets (e.g., fonts and images) to the /dist folder
  • Build main CSS file
  • During/after build of main CSS file, rewrite links to static assets now located in /dist
  • Build main JS file
  • Copy non-universal JS (things that we don't want everywhere and don't build into the main minified JS) into /dist/vendor folder

Use Less extend

As of version 1.4, LESS supports extending a style. Extend is sort of like the opposite of a mixin. Instead of adding all the properties of a mixed-in class into a class, it adds the extending selector to the selector list for output of the extended class.

The syntax for extend is designed to mimic the syntax of CSS pseudo-classes, and can be combined with pseudo-classes as long as any extends selectors come last.

For example:

div {
    background-color: #e0e0e0;
}
p:extend(div) {
    color: #101010;
}

Will output

div,
p{
    background-color: #e0e0e0;
}
p{
    color: #101010;
}

As you may have noticed, this can significantly remove the amount of bloat in the output CSS compared to mixins.

The extend selector can be used on the same line as the class selector, or it can be nested as seen in this example:

.parent {
    font-size:12pt;
}
.child {
    &:extend(.parent);
}

By default, extend does not include nested elements of the extended style. To do this, you must add all to the selector in the extend expression.

For example:

.a.b.test,
.test.c {
    color: orange;
}
.test {
  &:hover {
    color: green;
    }
}
.replacement :extend(.test) {
}

Outputs:

.a.b.test,
.test.c {
    color: orange;
}
.test:hover {
    color: green;
}

But this:

.a.b.test,
.test.c {
    color: orange;
}
.test {
  &:hover {
    color: green;
    }
}
.replacement :extend(.test all) {
}

Outputs:

.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
  color: orange;
}
.test:hover,
.replacement:hover {
  color: green;
}

Document how to add new CSS/JS libraries to cf-demo

RE: #25 we should be documenting how we are building our CSS/JS with Grunt so people know how to add new libraries and have them integrated properly.

Also Via @Scotchester

We need to figure out a way to deal with scripts that we don't want to build into the global JS files and only want to load on individual pages as needed. For example, a tablesort script may not need to be loaded in the global JS file; it could just be called by itself on pages where it is needed.

I think the way we're adding in html5shiv speaks to this so it's just a matter of documenting it. In fact we should document what we're doing in general because it might not be so obvious that you should be adding your site-wide js/css into main.js/main.less.

Add Normalize.css to all components

Add to all components

  • cf-buttons
  • cf-expandables
  • cf-forms
  • cf-grid
  • cf-icons
  • cf-pagination
  • cf-typography
  • cf-demo

Update TERMS for all components to now include Normalize

  • cf-buttons
  • cf-expandables
  • cf-forms
  • cf-grid
  • cf-icons
  • cf-pagination
  • cf-typography
  • cf-demo

Research

Status: Done!

Problem: Normalize is up to V3 now and V2 dropped IE7 support. Here is the thread where necolas talks about dropping IE7.

We can add IE7 support back in by comparing it to the commit where he took out support.

There is also an SCSS normalize project that allows you to specify if you want IE7 support. Seems like we could more easily backfill support by looking for instances of @if support-legacy-browser(ie, "7") { ... in their code.

Keep in mind we should re-test the components when adding this. There also might be some CSS we can drop from our stylesheets once adding this but I'm not sure how we can figure that out easily.

Set up automated accessibility testing

Research

Chrome DevTools Accessibility Extension

Notes from OSCON 2013 courtesy of @Scotchester

Install from the Chrome Web Store

Run accessibility tests from the Audits tab.

Can access the API with Web Puppeteer. Tutorial on http://github.com/GoogleChrome (see slides for link).

Case study: Case Commons using capybara-accessible

Notes from OSCON 2013 courtesy of @Scotchester

Government child welfare organization, required to follow Section 508.

Tech constraints: Rspec, Capybara

Created a Capybara wrapper around the Chrome DevTools Accessibility Extension, baking the testing into their integration test suite. It's a drop-in replacement for a Selenium web driver in Capybara.

It generates a build failure like any other integration testing error.

To help locate problem spots, added a debugging snapshot right before the exceptions are thrown so that you can load it up in a browser and use the DevTools to see what's going on.

http://github.com/CaseCommons/capybara-accessible

Quail.js

Accessibility testing in the browser and on the server.

QUAIL is a jQuery plugin for checking content against accessibility guidelines. It provides a flexible way to test for certain problems (say, images missing an alt text) and a collection of over 200 tests to get you started. Defining your own tests is easy, and you can pick-and-choose tests to focus on the needs of your own app.

http://quailjs.org/

Deque

FireEyes is our free accessibility testing plug-in. With the click of a button, it can provide a detailed and comprehensive report of any accessibility errors on any of the pages within your site. You can then send that error report to the WorldSpace public server where you can download it as an Excel or .csv file.

When you’ve got a big accessibility project, you need an automated testing tool that’s up to the task. WorldSpace combines the fast and thorough reporting capabilities of FireEyes and can use them across any quantity of pages. It also offers special features for managers, developers, and QA.

http://www.deque.com/products/

Centralize component Grunt tasks

As noted by @danny8000, currently, individual components' Gruntfiles are largely the same. How can we make these more maintainable?

Discussed briefly with @himedlooff and more extensively with @contolini, I propose:

  1. Pull out the common tasks into an npm package published as a @cfpb repo.
  2. Add that package into each component's package.json dependencies.
  3. Reduce each component's Gruntfile to calling the common tasks from the package's node_modules location, plus any component-specific Grunt tasks. Potential technique: cowboy/wesbos@5a2980a

Question to be answered: Can we override a standard task with a custom one in the component's Gruntfile? (What happens if you are importing a standard task and then below you declare a task of the same name?) Or can we pass them options?

One CONTRIBUTING to rule them all?

I propose that we use the CONTRIBUTING.md file from this repo for all Capital Framework components.

Currently within each component repository we have a CONTRIBUTING.md file. They all say the same exact thing. Recently we've been updating the contributing guidelines for this master repo. These edits are applicable to all components as well and it would be nice to update each component. We can save some effort on updating all of the component repos in the future if we 1) delete the CONTRIBUTING.md file in each component repo and 2) within each component README update the contributing link to point to the CONTRIBUTING.md of this repo. If we feel like a CONTRIBUTING.md file is necessary in each repo maybe we can replace all the content within that file with a link.

@Scotchester any thoughts?

Add style guide info to CONTRIBUTING

We need to add a style guide section to CONTRIBUTING.md. Additions should be terse so it is easy to read and so people don't ignore it. If examples are needed link to them.

The following additions are needed:

  • The obligatory "in lieu of a formal style guide...".
  • Notes on linting tasks used in Gruntfile.js.
  • Less notes like use of unit() to make calculations clear and using line breaks in unit() to make long calculations easy to read.
  • Mention our ideal BEM syntax (and acknowledge we're not using it fully everywhere yet). #40
  • Creating new components.

Look into using .editorconfig

EditorConfig is a file format and collection of text editor plugins for maintaining consistent coding styles between different editors and IDEs.

From what I briefly read it's a way to set tabs, spaces, etc per project. So you'd open up this repo and there'd be an .editorconfig file and your IDE would pick it up and automatically update your settings to keep these kinds of things consistent. This is how I imagine it works but I haven't looked into it really. Figured I'd first see if anyone has used it or knows what it really is.

Use reference imports for Less

The benefit I think is that if we needed to output a .CSS file for each component then that file would only contain the component styles and not any dependency styles. Only mixins or variables that are dependencies are used for styling the current component but not compiled into the .CSS.

http://lesscss.org/

We have another import option - reference. This means that any variables or mixins or selectors will be imported, but never output.

e.g. if you have

.a {
  color: green;
}

in a file and import it

@import (reference) "file.less";
then that file will not be output, but you could do

.b {
  .a;
}

Not cloning the full history

@ascott1:

A lot of "boilerplate" projects seem to suggest not cloning the full history of the project. This can be accomplished like so:

git clone --depth 1 git://[GHE]/flapjack/front-end.git

What do you guys think about this? Should these instructions be added to the README?

@himedlooff:

Another issue is that you can only fork a project once. Are there git tricks to get around that?

@ascott1:

My workflow so far has been to do the following:

  1. Create a new (empty) repo at github
  2. Clone as I did above
  3. Push that clone to the new repo

edit: once everything is public, we may be able to simplify this by creating a yeoman generator

@Scotchester:

Yeah, end users should not fork the project, just clone as @ascott1 suggested.

I like the suggestion of adding that to the README, thanks @ascott1! Wish I had known about that option a long time ago...

@himedlooff:

Yeah, smart thinking it should definitely be in the readme.

Research Code Documentation Libraries

Originally written by @himedlooff:


Status: Thinking of going with Topdoc as adoption and implementation seems to be much easier. See notes below.

Check in our own components?

@Scotchester

Interesting article: http://addyosmani.com/blog/checking-in-front-end-dependencies/

I am pretty sure we're not willing to check in the third-party dependencies we rely on, but should we check in our own components?

@himedlooff

Why can't we check in all Bower dependencies? What was most convincing to me was that it doesn't matter if you pin down your Bower dependencies because their might be child dependencies that aren't pinned down. I can see how this would cause headaches during a launch. I'm not sure if any third party dependency uses bower though so this point might be moot for now. The only way I can think of to control this particular issue would be to use a fork of every third party dependency and build/pin them down yourself.

Another (admittedly a minor) convenience is you could skip the grunt vendor step in each component and in the framework repo decreasing the complexity a little.

Also we should start using the bower.json ignore property.

ignore [array]: An array of paths not needed in production that you want Bower to ignore when installing your package.

@Scotchester

In general, for public repos, we don't want to "redistribute" others' code. I mean, we can in most instances, if their license permits it, but it's just easier if we don't, as a rule.

But you make a good point about our inability to control how third party components manage their own dependencies. I don't think forking and maintaing our own is an option.

Maybe we should talk to the OSWG and try to get a group consensus on whether or not we should do that?

(Interesting note about the ignore property... not sure why I didn't know that existed. But, is there an advantage to using that over specifying only the files you want via the main option?)

@himedlooff

Also in that article you linked to

Jørgen Borgesen
How do you handle files (from dependency packages) that are not needed by your application? A lot of the bower packages contains files for test, documentation, etc. Do you recommend adding them to source control? How about their bower.json file?

Sindre Sorhus
Yeah, that’s currently the biggest issue with the Bower ecosystem. Package authors aren’t using the ignore property in bower.json to exclude unneeded files. You could however add some of the junk manually to your .gitignore. As for their bower.json, yes, as it’s used by Bower.

@Scotchester

Hmm... so perhaps using both is the best policy, so that if someone else wants to use our package, their build process could potentially use either method to get the necessary files.

Handling scripts we only want to load as needed

Via @Scotchester

We need to figure out a way to deal with scripts that we don't want to build into the global JS files and only want to load on individual pages as needed. For example, a tablesort script may not need to be loaded in the global JS file; it could just be called by itself on pages where it is needed.

Running `bower install` before `grunt vendor` breaks `grunt compile`

@Scotchester:

It causes grunt vendor to skip its own bower install step, leaving things in the /bower_components folder. Then the LESS build breaks when it looks for imported dependencies in the wrong place.

Since many people might be in the habit of running bower install when cloning a project that uses Bower, we should set up grunt vendor so that it doesn't break if someone runs bower install prior.

An easy way to do this would be to just add a task to grunt vendor that deletes /bower_components, but maybe there's a better way out there?

@contolini:

Would having .bowerrc point to src/vendor/ fix this?

@Scotchester:

I think probably not, because the grunt-bower task also does the exportsOverride bit, so it's not just a matter of getting the stock bower components in the right place.. But it's worth trying just to be sure!

@Scotchester:

Right, so I remember why we set it up this way (why .bowerrc doesn't point to src/vendor): If we do it the way it's currently implemented, the grunt-bower task only copies the useful files into src/vendor.less and .js files, not READMEs and package.jsons and such. If .bowerrc points to src/vendor, the entirety of each package's repo is pulled in.

Let me know if you would like me to explain that over screensharing, Chris, where it might be easier to see in action.

@Scotchester:

Going to commit the easy fix for this for now.

@himedlooff:

Is this really an issue? If people followed the instructions (or if the instructions were more clear) then they wouldn't have this problem. Why bloat our gruntfile for cases like this?

The other thought was should we submit this to the grunt-bower repo as a bug?

CSS conventions

We should have conventions on class names. In the hand book we say we use SMACSS but none of us really do. I'm partial to the BEM-ish style of:

.block{}
.block__element{}
.block--modifier{}

For example:

.site-search { .. }
.site-search--full { .. }
.site-search__field { .. }
.site-search__button { .. }
<form class="site-search  site-search--full">
    <input type="text" class="site-search__field">
    <input type="Submit" value ="Search" class="site-search__button">
</form>

More info: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/

Pros

Flexibility.

Non-BEM-ish

.nav { ... }
.nav > li { ... }
<ul class="nav">
    <li></li>
    <li></li>
    <li></li>
</ul>

BEM-ish

.nav { ... }
.nav__item { ... }
<nav class="nav">
    <div class="nav__item"></div>
    <div class="nav__item"></div>
    <div class="nav__item"></div>
</nav>

Thoughts

  • The selectors in the BEM-ish version are more portable. For example you could change from using div's to span's easily. Or you could format the markup differently and nest .nav__item further down the tree if you need to like this:
<nav class="nav">
    <div class="col-4">
        <div class="nav__item"></div>
    </div>
    <div class="col-4">
        <div class="nav__item"></div>
    </div>
    <div class="col-4">
        <div class="nav__item"></div>
    </div>
</nav>
  • Also notice how the specificity of .nav__item is lower than .nav > li or even .nav li. Keeping specificity low in every day usage means you can leverage specificity later when you really need to override something.

Document EM's and the unit() LESS function

When using EM values I find it helpful to leave the calculation that got me the value inside of a comment. For example:

font-size: 0.875em; /* 14/16 = 0.875 */

This is helpful because it's hard to understand what these EM values mean sometimes. Like I haven't yet memorized that 0.875em is 14px in the context of 16px. And if the context changes then it gets even more confusing.

The downside to commenting the calculation is it's harder to comment whole blocks of CSS because you can't do this:

/*.something {
  font-size: 0.875em; /* 14/16 = 0.875 */
}*/

I think it's worth it though because it makes it clear what that value is incase it needs to be adjusted later. Also this is only an issue when writing .css files.

With LESS you can use LESS comments which you can wrap with standard CSS comments like this:

/*.something {
  font-size: 0.875em; // 14/16 = 0.875
}*/

OR... I've been playing around with the unit() function which allows you to use a math expression inside of it. This is nice because the calculation is not inside of a comment anymore. Also when you need to calculate margins or other properties in EM's where the context is likely to affect the calculation it's much easier to do.

When changing from 22px to 28px font-size it's pretty easy:

h1 {
    font-size: unit( 22 / @base-font-size-px, em );
    margin: unit( 10 / 22, em ) 0;
}
h1 {
    font-size: unit( 28 / @base-font-size-px, em );
    margin: unit( 10 / 28, em ) 0;
}

Framework logo

A logo would make Capital classier. We can stick it on the demo page and we'll need one if we end up moving the framework to a dedicated GH org.

Any ideas? Perhaps the standard four column government-looking building? Or a silhouette of the Capitol building? Or something money-themed like a seal on a U.S. dollar bill?

300px-government_icon_symbo_01
icon-government
one_dollar_bill_reverse-united_states_

Address potential naming collisions in combined asset folders

When building combined asset folders (e.g., dist/static/img), in the current implementation, there is a possibility that two files with the same name would get put in that folder. Presumably, the first would get overridden by the second.

We should figure out how to sequester assets for each vendor component in their own folders (either dist/static/vendor/[type] or dist/static/[type]/vendor) to prevent such conflicts.

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.