GithubHelp home page GithubHelp logo

changesets / changesets Goto Github PK

View Code? Open in Web Editor NEW
8.0K 30.0 478.0 4.53 MB

πŸ¦‹ A way to manage your versioning and changelogs with a focus on monorepos

License: MIT License

JavaScript 0.16% TypeScript 99.84%

changesets's Introduction

A tool to manage versioning and changelogs
with a focus on multi-package repositories


View changelog

The changesets workflow is designed to help when people are making changes, all the way through to publishing. It lets contributors declare how their changes should be released, then we automate updating package versions, and changelogs, and publishing new versions of packages based on the provided information.

Changesets has a focus on solving these problems for multi-package repositories, and keeps packages that rely on each other within the multi-package repository up-to-date, as well as making it easy to make changes to groups of packages.

How do we do that?

A changeset is an intent to release a set of packages at particular semver bump types with a summary of the changes made.

The @changesets/cli package allows you to write changeset files as you make changes, then combine any number of changesets into a release, that flattens the bump-types into a single release per package, handles internal dependencies in a multi-package-repository, and updates changelogs, as well as release all updated packages from a mono-repository with one command.

How do I get started?

If you just want to jump in to using changesets, the Intro to using changesets and @changesets/cli docs are where you should head.

If you want a detailed explanation of the concepts behind changesets, or to understand how you would build on top of changesets, check out our detailed-explanation.

We also have a dictionary.

Integrating with CI

While changesets can be an entirely manual process, we recommend integrating it with how your CI works.

To check that PRs contain a changeset, we recommend using the changeset bot, or if you want to fail builds on a changesets failure, run yarn changeset status in CI.

To make releasing easier, you can use this changesets github action to automate creating versioning pull requests, and optionally publishing packages.

Documentation

Cool Projects already using Changesets for versioning and changelogs

Thanks/Inspiration

  • bolt - Brought us a strong concept of how packages in a mono-repo should be able to interconnect, and provided the initial infrastructure to get inter-package information.
  • Atlassian - The original idea/sponsor of the changesets code, and where many of the ideas and processes were fermented. It was originally implemented by the team behind atlaskit.
  • lerna-semantic-release - put down many of the initial patterns around updating packages within a multi-package-repository, and started us thinking about how to manage dependent packages.
  • Thinkmill - For sponsoring the focused open sourcing of this project, and the version two rearchitecture.

changesets's People

Contributors

acheronfail avatar ajaymathur avatar akphi avatar andarist avatar blasz avatar brianespinosa avatar caohuilin avatar chaance avatar danieldelcore avatar dependabot[bot] avatar dotansimha avatar emmatown avatar eps1lon avatar feiyang1 avatar github-actions[bot] avatar j9t avatar jakeginnivan avatar jonathanmorley avatar mblaszczyk-atlassian avatar noviny avatar pyupew avatar ryanbraganza avatar sam-b-rose avatar tarang9211 avatar trevor-scheer avatar vladdoster avatar waded avatar with-heart avatar zkochan avatar zthxxx 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  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  avatar  avatar  avatar  avatar  avatar

changesets's Issues

Make changesets work with yarn workpsaces

Currently changesets only work in bolt repositories. We should extend this to yarn workspaces as well.

Bonus thought: Should we extend this to lerna? I'm not concerned with doing this, but some people may be helped?

Add Types

Not having types for this makes it a lot harder to reason about and extend. We should add types.

Executive decision is that these should be be typescript types.

This is just work-to-be-done

Execute default $EDITOR when empty summary given

Doing a git commit without a message will;

  • create a temporary file in /tmp
  • execute sh -c $EDITOR /tmp/<path-to-tmp-file>
  • wait until the $EDITOR process exits
  • use the contents of /tmp/<path-to-tmp-file> as the commit message

I'd love to have the same thing for changesets πŸ‘

Change how we ask questions

Currently we ask question as:

1. Select packages to update: [list of all packages]
=>
2. Select bump type for package [patch, minor, major]
=>
Repeat step two for each package

This means that the number of questions you have to think about is 1 + packages-bumped, and scales up with larger system changes.

Proposed new format is:

1. Select packages to update: [list of all packages]
=>
2. Which of these packages are a major change? [list of selected packages]
=>
3. Which of these packages are a minor change? [list of selected packages - major changed packages)
=>
4. The rest (list them) will be a minor change - is this okay?

This reduces the questions to always 4.


Other concerns:

This makes it too easy to mass-update
We previously removed a bunch of questions because while being the most correct in querying individual information is good, decision overloading users gets worse results than being a bit smarter.

If I am updating less than three packages, I will get asked more questions
We could theoretically avoid this by switching to the old format for 1 or 2 packages, but I would like to have a consistent predictable experience when updating packages.

Could we ask one question only?

If we had one Very Complicated question that looked like:

Select the bump type of all packages:
pkgA *none* | patch | minor | major
pkgB *none* | patch | minor | major

and could cursor both up+down and left+right, you could just use one set of selects to choose EVERYTHING.

I... don't actually like this. It feels like to get all the answers right you need to hold too much information in your head at once, once again upping the complexity cost of getting your changeset 'right'.

Discussion: should private packages have changesets/when should you add a changeset?

by private packages I'm referring to packages that aren't published based on the private package.json field, not ones that are published privately

I feel like this has come up a few times and I think it would be nice to have a discussion and come up with an answer that changesets recommends and create a resource that we can point to when other people ask this question.

I used to have the opinion that changesets should only exist when changing something that needs to be released. My opinion has since changed to being "always add a changeset if you're changing a package" because adding a changeset even when it's not strictly necessary doesn't really hurt anything but missing a changeset can be very bad and adding them more often than not reduces the likelihood of accidentally missing a changeset.

I also recall @Noviny talking about how figuring out whether a change is something that needs to be released is more complex than it sounds at some point but I can't explain it well.

cc @timleslie @jesstelford because I think you might have thoughts on this

Group "changed, but with unstaged changeset" packages

The CLI currently outputs something like:

Changed Packages:
o foobar
o zipquux
o helloworld

Unchanged Packages:
o boombam
o whackadoo

Sometimes I want to do multiple changesets immediately after eachother, so on first cycle, I'd do:

Changed Packages:
o foobar
x zipquux
x helloworld

Unchanged Packages:
o boombam
o whackadoo

(ie; write my changeset for zipquux & helloworld packages)

Now I have some unstaged changes:

- .changesets
  - a-set
    - changes.md
    - changes.json

Now, I want to do a changeset for the foobar package, and end up seeing the same UI again:

Changed Packages:
o foobar
o zipquux
o helloworld

Unchanged Packages:
o boombam
o whackadoo

But ideally I'd prefer if changesets scans unstaged changes in .changesets and groups out packages with changesets just added:

No Changsets:
o foobar

Uncommited Changeset:
o zipquux
o helloworld

Unchanged Packages:
o boombam
o whackadoo

Which makes it really easy for me to see that I only have foobar remaining to write a changeset for.

Add CI integration

We should run CI on this project - let's set that up.

We should run tests and lint on branches

Establish clear open source model

Contributing into atlaskit is hard* for externals, and this tool is fairly unrelated to atlaskit's core mission. In filling out the requirements of the other issues, we may want to investigate this.

Display changesets by release type

Currently we go:

## 2.1.0

- [patch] Allows passing --public flag for publishing scoped packages [159c28e](https://bitbucket.org/atlassian/atlaskit-mk-2/commits/159c28e)
- [minor] Changes changelogs to be opt out rather than opt in [f461788](https://bitbucket.org/atlassian/atlaskit-mk-2/commits/f461788)

without caring about the order of release notes, or precedence. To get more readable changelogs, we should do something like:

## 2.1.0
### Minor

- Allows passing --public flag for publishing scoped packages [159c28e](https://bitbucket.org/atlassian/atlaskit-mk-2/commits/159c28e)

### Patch

- [minor] Changes changelogs to be opt out rather than opt in [f461788](https://bitbucket.org/atlassian/atlaskit-mk-2/commits/f461788)

Suggestion by @timleslie

Should we remove `commit: true` as an option?

Currently the commit option is the reason we separate config by command - which we would like to stop doing (it would greatly simplify the config).

As part of this, I want to talk about where changesets intersects with git - and should it?

Currently, we intersect with git in:

  • Committing changesets + committing bumps
  • writing changelogs (we default grab and hand back commit info)
  • status has --since-master option, which will make it care about git

We've said in the past that we don't want changesets to be tied to git, so what happens if we don't tie it to git?

  • Committing bumps is still easy enough to do in CI when you want to commit them
  • Committing changesets become more likely to be missed - you can add a changeset, push changes, and have forgotten to add the files - this seems a weak argument to me.
  • Writing changelogs having access to the git hash helps out a lot with writing changelog messages. Could the logic that fetches it be split into an optional library, similar to how fetching info from github is split out?
  • The status command doing this still seems fine.

bolt-check --fix improvements

I'm going to test bolt-check on some monorepos and find things that can be improved in the auto fix.

Other fixes for this:

  • Stop looking at peerDeps

Maybe rename initialize command to init

I was setting up build-releases on a new project (https://github.com/unstyled-components/design-system) and my gut reaction was to run build-releases init(I also feel like it's more standard across the ecosystem, e.g. npm init, preconstruct init, git init, flow init) but that didn't work because the command is initialize. This wasn't really a very big thing since build-releases logged the commands that do work which said initialize and I ran that and everything worked perfectly but this might be a nice little thing that could change for the rewrite or maybe I'm wrong and initialize is better than init Β―\_(ツ)_/Β―

Also, init is nice because it sidesteps the initialize vs initialise problem.

Allow custom message in changeset-bot.

I would like to include a customised link in my deployment of the changeset-bot to point to internal project docs explaining how to use it in our specific case.

Prereleases

A lot of large open source projects need to do prereleases to share things with the community before releases so they can provide feedback without having to do the real release and then having to do lots of major versions when they inevitably need to change things.

The way I'm thinking this would work is that you would have all of your changesets and when you run something like build-releases version-packages --prerelease=beta, the tool would calculate all of the versions and then append something like -beta.0 to them and write all the versions. I'm thinking choosing the npm dist tag to publish to should probably be something that users handle themselves by using the publishConfig field that npm looks at in package.jsons.

Maybe the changesets that are used in a prerelease could be kept in the file system still(in another directory?) so that for the final release, they could all be used to create the changelog entry for the final version.

I'm not totally sure about how specifically all of this should work and this has a bunch of open questions but I think the general idea would be good to have.

(This isn't a need to have for emotion to use it right now but would likely be necessary in the future when we do the next major version but that likely won't be for a couple months I'm guessing)

When adding changeset, print `changes.md` file path at the end

One of the points of changesets is you can go and edit the markdown contents, but it's still a bit hidden, and the nesting makes it kind of annoying.

When you display Changeset added! - you can now commit it or the other one for if you auto-commit, display under it:

or go expand the changelog summary at {blue .changesets/${ID}/changes.md

My expectation is this small change will get WAY better changelog messages.

Build github addon

Build a github addon to alert when there is no changeset present in a PR (without this changesets are v hard to recommend to open source projects)

Current design idea:

On PR Creation

Leave a comment with the changeset status (bonus: list packages changed, and the version bump they are receiving)

Changeset status should look something like:

❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌
NO CHANGESET PRESENT
❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌

or:

βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…
This PR has a changeset
βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…βœ…
(optional changeset version info)

On PR Update

Do NOT add a new comment - edit and update the existing changeset comment.

Thoughts on config

I want to talk about config.

So, the current format for everything is JS. (except figuring out what the workspaces are which is specified in JSON and isn’t changesets config but it’s very important knowledge to changesets)

I think that has tradeoffs that might not be ideal but also might be the right ones.

The first thing I want to make sure I'm correct about is that as far as I understand everything with the exception of the getReleaseLine and getDependencyReleaseLine can be expressed purely in JSON?

Why I think JSON config is good

  • It can be safely read in any environment
    • This is a useful thing to build tools on top of that it that run in environments where you can't safely run user code. (i.e. bots and etc. without having to have a ridiculous amount of infrastructure)
      • counterpoint: a big use case for this will be github and because of actions, it'll be practical to run user code safely soon
    • counterpoint: Because of getReleaseLine and getDependencyReleaseLine, if the config were JSON, you wouldn't be able to do releases without running user code so that would lessen the benefits
  • changesets can modify, fix things and etc. in the config because it's JSON
  • Probably other things I can't think of

Why I think the JS config is good

  • Everything can be dynamic so you could share config
    • counterpoint: when will you share config beyond the changelog generation stuff?
    • another counterpoint: where is the dynamicness useful?(with the exception of changelog generation stuff)
  • The built in documentation is really really nice
    • counterpoint: it will get out of date as options change and no documentation > out of date/wrong documentation
      • counter-counterpoint: how often will options practically change?
  • Probably other things I can't think of

How I think a JSON config might look

Not if sure if .changeset/config.json or a changeset key in the root level package.json would be better but here's a vague idea of how it could look

{
  "changesets": {
    // this would be a module id that is resolved relative to where the config file is located
    // so people could write their own changelog generators which export  `getReleaseLine` and `getDependencyReleaseLine`
    // or a company, team or etc. could have a standard one
    "changelogs": "@thinkmill/changelog-generator",
    // there could probably be some tweaking of this,
    // i'm not a big fan of separation of options between version, changeset and publish(also, the naming probably needs to be fixed because of the new command names) how it is right now because it means having config that goes through multiple parts of the system is strange but also I see how it's nice in some cases
    ...theRestOfTheConfigOptionsLikeTheyAre
  }
}

(this isn't meant to be "I think this is what we should do" but more "I think the current approach and another approach both have different trade offs and we should discuss about which one is better for changesets")

Expand on range types changesets supports

Currently changesets supports 1.0.0, ~1.0.0, and ^1.0.0, which is a subset of valid semver definitions.

@mitchellhamilton found the range types that yarn supports, and suggested we should do that.

So we need to: refind that info (I have lost the link he gave me soz)
Align our range type function with it.

Add option to get version bump info

Something like: build-releases analyze that should output the versions of what will be published if it is run now. Possible formats of output are:

| Package Name | Bump Type | New Version  |
|:-------------:|:-------------:|:-------------:|
|    packageA    |       minor       |      1.1.0           |
|    packageB    |       major       |      1.0.1           |
|    packageC    |       patch       |      2.0.0          |

Similar, make sure there is a script we can call not from the command line, so we can build extension tools on top of this. #5 would very much like this.

Info I don't think we care about showing - what is being bumped as a dependency vs being a main changeset item.

Run prettier on changesets, changelogs and the changeset config if there is a prettier config in the project

I've noticed that often someone adds a changeset in one PR and then after that PR is merged but before the next release, someone submits another PR which adds a newline to the changeset md file because they opened it their editor and it auto formatted or they ran prettier and it formatted the file. This is kind of annoying from a PR reviewing perspective because they're just a random and I think the changesets tool is in a good position to fix the problem.

So this is the behavior that I think would be nice:
Only do these things if there's a prettier config in the repo (or maybe check whatever heuristic jest uses and do that)

  • When creating the .changeset/config.js run prettier over the file when it's written
  • Run prettier on changesets when they're written. My thought is that prettier should definitely be run on the markdown, not so sure about the json.
  • Run prettier against changelogs when changesets are consumed

One argument against this might be that "caring about prettier is a pretty opinionated thing for a tool that does versioning" but there's already precedence with jest as an example using prettier for toMatchInlineSnapshot.

this might be a bad idea and the problem might not be big enough to justify caring about prettier.

Discussion: should changesets be two files or one?

Currently we add a changes.json and a changes.md file to repositories.

We could write the contents of the changes.json as front-matter in the changes.md.

Pros:

  • We can remove a level of nesting (just have .changeset/UNIQUE_ID.md instead of making UNIQUE_ID a folder)
  • With how github displays frontmatter, you could review a changeset in one screen

Cons:

  • The json content should never be manually edited, but the md content should be, and this make that less obvious
  • I have a dumb bias against frontmatter that isn't fully justified

GitHub integration for doing releases

Let's say I'm a maintainer of a project that I'm not always able to spend time on and when I can, I merge a bunch of PRs and I want to do a release but the amount of work(while not that big) I have to do is annoying and I think it could be better. Another constraint that I also want to add is that doing a release should still be an explicit action by a maintainer or at least that should be an option.

How do I think this could be solved?

The first part of it is having a bot that runs changeset bump on the repo and opens a PR with that whenever there are changesets in master and when changesets are added to master, it resets the old content, runs changeset bump and pushes again.

The second part is automating running changeset release on master, I think this will require quite a bit of thought because exposing npm credentials would be really really bad.

So with these two things, a maintainer can do a release by hitting the merge button on a PR and everything else will be automatic.

I'm probably going to experiment with this at some point, probably with GitHub actions but I wanted to open this in case there are any big problems with this that I can't see.

Group entries by major/minor/patch in CHANGELOG output

My CHANGELOG output currently looks like this:

========

3.0.0

  • [patch]b4dcf44b:

    • Use named exports from @keystone-alpha/keystone package.
  • [patch]b69fb9b7:

    • Update dev devependencies
  • [patch]baff3c89:

    • Use the updated logger API
  • [patch]302930a4:

    • Minor internal code cleanups
  • [major]656e90c2:

    • WebServer.start() no longer takes any arguments. Developer must now explicitly call keystone.connect() before calling WebServer.start().
  • [major]b4dcf44b:

    • Make all parts of the API available as named exports.

=====

I would like this to look like this:

=====

3.0.0

Major

  • 656e90c2: WebServer.start() no longer takes any arguments. Developer must now explicitly call keystone.connect() before calling WebServer.start().
  • b4dcf44b: Make all parts of the API available as named exports.

Patch

  • b4dcf44b: Use named exports from @keystone-alpha/keystone package.
  • b69fb9b7: Update dev devependencies
  • baff3c89: Use the updated logger API
  • 302930a4: Minor internal code cleanups

===

At the moment I can update the formatting of the individual lines with getReleaseLine, but I can't control the overall shape of the template.

When bumping packages, validate changesets and warn on error

This is related to the discussion of a validation command.

Effectively, perform the check that runs on creating a changeset to see if anything else should be released, and ensure that anything that should be release will be.

This helps for times a changeset.json file is modified creating an error state.

(don't edit the changeset.json file)

Name commands

We want to make sure that the commands and the names of the commands make sense. I'm looking at making several changes from build-releases. As always, naming is hard. Feedback would be appreciated.

Current binary is build-releases, so commands are build-releases [command].

New binary will be changesets, so commands are changesets [command]

Current commands are:

  • initialize: get changeset default config set up, and create the .changeset dir
  • changeset: add a new changeset
  • version: consume changesets and update package versions
  • publish: publish any packages that need it (effectively just bolt publish)

Simple changes

  • initialize to init

Reasoning: init is more standard.

  • changeset to add

Since the base command is now changeset, add is now used to generate a new one

Annoying changes

version and publish were originall introduced as names for bolt commands, which would mean they can mirror npm (and yarn) command names, since the global bolt will intercept them, so running bolt version or bolt publish would always be fine.

Changesets are not set up to be installed globally so you tend to create a package script to make running them easier. The most obvious choice is to include a command of the same name. For example:

"changeset": "build-releases changeset",
"version": "build-releases version",
"publish": "build-releases publish",

If you run yarn version however, it will run yarn's version command before looking for package scripts, which is a massive nonbo. So I want to rename both of these.

I want to rename publish to release, which I think is fairly obvious.

version is giving me grief.

Leading candidate is consume, which is very logical once you understand changesets, but is non-obvious when learning the tool in the way that version was. update makes it unclear if it will update a changeset or packages. update-packages might be the best, but doesn't sound good for single-repo use of changesets, and is still not amazingly clear.

So tentative new name suggestions are:

  • initialize => init
  • changeset => add
  • version => consume
  • publish => release

Add strict mode?

Just thinking out loud - nobody has asked for the feature yet.

Currently we only update dependencies when they leave semver, but theoretically your versioning strategy could involve releasing whenever any mono-repo-included dependencies change.

What would that look like? Is it a terrible idea? Should we support it?

Add `test` commands for version

Problem: Version is very configurable, down to how you output the changelog lines, but the only way to test changelog line output (among other things) is just to run it.

Solution: From the command line, run your version command against a series of test changesets and see how your formatted changelogs would look, allowing you to test out this generation in a non-awful way

The wrong dependents are generated in some rare cases with `linked` and changing to single file changesets

changeset add currently doesn't care about the linked option and that creates a problem if a package is bumped at a higher level because of linked which means there should be some dependents.

A, B and C are all linked together and they are all currently at 1.0.0. B has a dependency on C.

A changeset is added:

A@major
C@patch

There will be no dependents generated. When bumping though, A and C will both be released as 2.0.0 and B won't be released which is wrong since its dependency on C is out of range now.

Add a link to create a changeset from the changeset bot comment

Open questions:

  • Should maintainers write custom changeset summaries in the syntax or use the PR name?
  • What should the syntax be?
  • Should we list the changed packages or something in the you have/don't have a changeset message?

The plan is now to add a link to the changeset bot comment with a pre-filled filename so a maintainer can write a changeset.

changesets 2.0 discussion thread

A place to group all the changes we are discussing that we would want to implement in a 2.0 version of changesets, as they are all breaking, drastic or related changes.

Currently covers:

#84
#53

Pre-requisites (but can be done without breaking)
#40
#86

Nit: Cursor positioning is odd now

image

When typing a summary, the cursor is spaced away form the text. The above image has no character after the question mark but is oddly not next to it.

This keeps putting me off slightly and I should probably dig into what it is.

Ensure writing changelogs will succeed before writing files

Currently if there is an error in getting release lines, the changelog will fail to be written, but the package will be updated. This can lead to lossy changelogs.

Fix:
Generate all changelog updates before writing any files, then, if there are no errors, proceed on to writing the files afterwards.

If there are errors bail completely out of consuming changelogs

Decompose changesets/cli into meaningful packages

The goal: make it easy for people to build their own utilities with minimum fuss.

Current new packages:

@changesets/[command]
  • programmatically run any of the changeset commands as a function if you have all the correct information.

Ban devDeps in the root of monorepos in bolt-check

The distinction does not matter for the root package.json and by letting people choose where to put them, it only creates confusion because people aren’t sure where a dep should go and there isn’t really a β€œright” answer because it doesn’t affect anything.

get-workspaces order is not deterministic

When running our testing suite, sometimes get-workspaces, or tests that rely on the output of get-workspaces fail, because the order of packages changes. This is very bad for tests, but also probably bad for the package.

We need to track down the root cause and then resolve.

Lint markdown

With remark, for preference.

Tried a quick experiment looking at how keystone-5 does it, but the config wasn't being picked up at all, so going to revisit this later.

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.