Giter VIP home page Giter VIP logo

aws-sdk-js-v3-workshop's Introduction

aws-sdk-js-v3-workshop

If you're looking for scripts to upgrade your code from v2 to v3, see aws-sdk-js-codemod.

In this workshop, we're going to:

  • Build a simple note taking application.
  • Identify the benefits of using AWS SDK for JavaScript v3 over v2.

The note taking application is the modified version from the original Open Source MIT licensed project shared in the tutorials on serverless-stack.

If you are starting a new project with AWS SDK for JavaScript v3, then please refer aws-sdk-js-notes-app which uses more services in addition to S3 and DynamoDB.

Table of Contents

Pre-requisites

To set up this workshop package, complete the following tasks:

  • Install Node.js by following these steps:
    1. Install nvm.
    2. Use node v12.x.x by running nvm use or nvm use 12 in a terminal window.
    3. Verify that node is installed by running node -v in a terminal window and confirm that it shows the latest version of v10, such as v12.17.0).
  • Install yarn.
    • We recommend using yarn for its simplicity, speed and yarn workspaces.
  • Install dependencies by running yarn.
  • If you don't have an AWS account, create one.
    • If you're an Amazon employee, see the internal wiki for creating an AWS account.
  • Install the AWS CLI.
    • Verify that the AWS CLI is installed by running aws in a terminal window.
  • Set up AWS Shared Credential File.
    • Your ~/.aws/credentials (%UserProfile%\.aws\credentials on Windows) should look like the following:
      [default]
      aws_access_key_id = <ACCESS_KEY>
      aws_secret_access_key = <SECRET_ACCESS_KEY>
      
    • Your ~/.aws/config (%UserProfile%\.aws\config on Windows) should look like the following:
      [default]
      region = us-west-2
      

Exercise1

This exercise code uses AWS SDK for JavaScript v2 as follows:

  • backend performs create, delete, get, list and update operations on DynamoDB.
  • frontend does put, get, delete operations using an S3 browser client.

The README files have instructions on how to move both to v3. The backend and frontend can be worked on independently as long as the APIs don't change.

Create backend API

  • Run: yarn build:backend
  • This generates bundles to be deployed to lambda.

Deploy infrastructure

  • Run: yarn cdk deploy
  • This command:
    • Creates AWS infrastructure using AWS Cloud Development Kit.
    • Deploys backend bundles to lambda.
    • Creates resources to be used in the frontend.

Prepare frontend API

  • Run: yarn prepare:frontend
  • This command copies AWS resources to the frontend config.

Debug frontend

  • Run: yarn start:frontend
  • This command starts ReactApp for testing frontend, and opens the URL in browser.

Migrate backend from v2 to v3

Follow backend README.md.

Migrate frontend from v2 to v3

Follow frontend README.md.

Clean up

The Cloudformation stack can be deleted by running: yarn cdk destroy

Exercise2

This exercise has the code which uses AWS SDK for JavaScript v3, which you would have got after finishing Exercise1:

  • backend performs create, delete, get, list and update operations on DynamoDB.
  • frontend does put, get, delete operations using an S3 browser client.

Edit existing APIs or create new ones to use AWS Services you're familiar with in the backend. For example:

Exercise3

Inspect the differences of stack trace if call DynamoDB.putItem with invalid resources in V2 and V3 SDK.

Using v2, call a service with invalid parameters as shown below:

Code
const DynamoDB = require("aws-sdk/clients/dynamodb");
const client = new DynamoDB({ region: "us-west-2" });
const request = client.putItem({
  TableName: "FakeName",
  Item: {
    Foo: { S: "Foo" },
  },
});
request.send((err, data) => {
  console.log(err);
});

When the code fails, the stack trace would look like:

Stack trace
ResourceNotFoundException: Requested resource not found
    at Request.extractError (XXX/node_modules/aws-sdk/lib/protocol/json.js:51:27)
    at Request.callListeners (XXX/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (XXX/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (XXX/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (XXX/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (XXX/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at XXX/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:685:12)
    at AcceptorStateMachine.runTo (XXX/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at XXX/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:685:12)
    at AcceptorStateMachine.runTo (XXX/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at XXX/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (XXX/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (XXX/node_modules/aws-sdk/lib/sequential_executor.js:116:18)

This happens, as Request.transition exists multiple times as the SDK state machine stuck at some state and makes stack trace unreadable.

Is the same operation is tried in v3:

Code
const {
  DynamoDBClient,
  PutItemCommand,
} = require("@aws-sdk/client-dynamodb-node");
const client = new DynamoDBClient({ region: "us-west-2" });
const command = new PutItemCommand({
  TableName: "FakeName",
  Item: {
    Foo: { S: "Foo" },
  },
});
(async () => {
  try {
    await client.send(command);
  } catch (e) {
    console.log(e);
    throw e;
  }
})();

The stack trace would be much smaller:

Stack trace
ResourceNotFoundException: Requested resource not found
    at JsonRpcParser.exports.jsonErrorUnmarshaller [as parseServiceException] (XXX/node_modules/@aws-sdk/json-error-unmarshaller/build/index.js:37:70)
    at JsonRpcParser.<anonymous> (XXX/node_modules/@aws-sdk/protocol-json-rpc/build/JsonRpcParser.js:22:40)
    at step (XXX/node_modules/tslib/tslib.js:136:27)
    at Object.next (XXX/node_modules/tslib/tslib.js:117:57)
    at fulfilled (XXX/node_modules/tslib/tslib.js:107:62)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Contributing

Contributions are more than welcome. Please read the code of conduct and the contributing guidelines.

License Summary

This sample code is made available under the MIT license. See the LICENSE file.

aws-sdk-js-v3-workshop's People

Contributors

alexforsyth avatar allanzhengyp avatar dependabot-preview[bot] avatar dependabot[bot] avatar doug-aws avatar idkjs avatar imedadel avatar jpeddicord avatar klaytaybai avatar trivikr 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

aws-sdk-js-v3-workshop's Issues

Add architecture diagram for the note taking application in READMEs

Is your feature request related to a problem? Please describe.
Although the exercises are simple, attendees have to go through the code to understand the architecture of the note taking application

Describe the solution you'd like
Add architecture diagram for the note taking application in READMEs of the respective exercises

Unable to install aws-sam-cli

Getting the following error:

cd /private/tmp/aws-sam-cli-20190923-93856-6h1nhs/src/github.com/awslabs/aws-sam-cli && /private/tmp/aws-sam-cli-20190923-93856-6h1nhs/bin/govendor sync

Error: Vendor file at "vendor" not found.
govendor sync
Ensures the contents of the vendor folder matches the vendor file.
Options:
-n dry run, print out action only
-insecure allow downloading over insecure connection
-v verbose output

If reporting this issue please do so to (not Homebrew/brew or Homebrew/core):
amazon/amazon

/usr/local/Homebrew/Library/Homebrew/utils/github.rb:258:in raise_api_error': Validation Failed: [{"message"=>"The listed users and repositories cannot be searched either because the resources do not exist or you do not have permission to view them.", "resource"=>"Search", "field"=>"q", "code"=>"invalid"}] (GitHub::ValidationFailedError) from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:212:in open_api'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:357:in search' from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:265:in search_issues'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:278:in issues_for_formula' from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:375:in fetch_issues'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:371:in issues' from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:425:in dump'
from /usr/local/Homebrew/Library/Homebrew/brew.rb:141:in rescue in <main>' from /usr/local/Homebrew/Library/Homebrew/brew.rb:38:in

'

sam deploy fails with Exit status 255 due to missing S3 permissions

Describe the bug
The deploy step of yarn bpd fails with exit status 255

To Reproduce
yarn mb
yarn bpd

Expected behavior
yarn bpd passes

Stack Trace

11 silly lifecycle [email protected]~deploy: Args: [ '-c',
11 silly lifecycle   'sam deploy --template-file packaged.yaml --stack-name $AWS_JS_SDK_ID --capabilities CAPABILITY_IAM' ]
12 silly lifecycle [email protected]~deploy: Returned: code: 255  signal: null
13 info lifecycle [email protected]~deploy: Failed to exec deploy script
14 verbose stack Error: [email protected] deploy: `sam deploy --template-file packaged.yaml --stack-name $AWS_JS_SDK_ID --capabilities CAPABILITY_IAM`
14 verbose stack Exit status 255
14 verbose stack     at EventEmitter.<anonymous> (/Users/<redacted>/.nvm/versions/node/v10.16.3/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
14 verbose stack     at EventEmitter.emit (events.js:198:13)
14 verbose stack     at ChildProcess.<anonymous> (/Users/<redacted>/.nvm/versions/node/v10.16.3/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
14 verbose stack     at ChildProcess.emit (events.js:198:13)
14 verbose stack     at maybeClose (internal/child_process.js:982:16)
14 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)

Additional context
Updating default region to us-west-2 as indicated by #12 does not resolve the issue

Explore using SvelteKit instead of React

Is your feature request related to a problem? Please describe.
Not a problem, but it's worth to have frontend in vanilla JavaScript - so that bundle size contains mainly SDK code.

In create-react-app, react-dom itslef is around ~80%, i.e. around 116 KB, as shown in the screenshot.

Screenshot

Screen Shot 2020-11-07 at 11 57 08 PM

Describe the solution you'd like
Instead of React.js, use a compiler like Svelte which compiles code into framework-less vanilla JS. Svelte recently announced SvelteKit

Describe alternatives you've considered
Sticking with React for Frontend, as it's still the most popular UX library out there.

Exercise 2 Solutions

Is your feature request related to a problem? Please describe.
No

Describe the solution you'd like
Will like to see solutions for Exercise 2.

Describe alternatives you've considered
Just want to see alternate solutions to the suggested questions in exercise 2.

Additional context
None

deleteObject command not found

Describe the bug
Looks like you didnt handle deleteObject in Exercise1 readme steps.

After doing all the updates in the front end you get this error:

Property 'deleteObject' does not exist on type 'S3Client'.ts(2339)

Looks like you have to move this to Exercise1 if its intended that Exercise1 compile at the end of the steps in its README.me

import { DeleteObjectCommand } from "@aws-sdk/client-s3-browser/commands/DeleteObjectCommand";
import { s3Client } from "./s3Client";
import { config } from "../config";
const deleteObject = async (fileName: string) =>
s3Client.send(
new DeleteObjectCommand({
Key: fileName,
Bucket: config.s3Bucket
})
);
export { deleteObject };

Use Tailwind CSS instead of react-bootstrap in workshop repo

Is your feature request related to a problem? Please describe.
Not a problem, but workshop repo uses react-bootstrap which arguably is the most popular CSS framework. But Tailwind is gaining in popularity since 2019

Describe the solution you'd like
Use Tailwind CSS instead of react-bootstrap in workshop repo
Blog post on how to use Tailwind CSS in CRA https://daveceddia.com/tailwind-create-react-app/

Describe alternatives you've considered
Stick with react-bootstrap, as it's usage is not expected to go down anytime soon.

Getting following error when trying to use `PutItemCommand`

Describe the bug
Getting following error when trying to use PutItemCommand

Argument of type 'PutItemCommand' is not assignable to parameter of type 'Command<InputTypesUnion, PutItemInput, OutputTypesUnion, PutItemOutput, DynamoDBResolvedConfiguration, Readable>'.
  Property 'model' is missing in type 'PutItemCommand' but required in type 'Command<InputTypesUnion, PutItemInput, OutputTypesUnion, PutItemOutput, DynamoDBResolvedConfiguration, Readable>'.ts(2345)
command.d.ts(28, 14): 'model' is declared here.

To Reproduce
Follow steps here

Show how to use S3 GetObjectCommand

Is your feature request related to a problem? Please describe.

The usage of GetObject has changed significantly in the new SDK version 3. It is no longer easy to get the response body.

v2:

const client = new S3({ region: 'eu-west-1' })
const data = await client.getObject({
  BucketName: 'my-bucket',
  Key: '/foo.txt',
}).promise()

// gets a string
console.log(data.Body.toString('utf-8'))

v3:

const client = new S3Client({ region: 'eu-west-1' })
const cmd = new GetObjectCommand({})
const data = await client.send(cmd)

// Body is a complex object containing network primitives etc. but no body
console.log(JSON.stringify(Object.keys(data.Body)))

Describe the solution you'd like

It's not clear if the SDK's current behaviour is intentional, but for this repository it would be most useful to include a use of the GetObjectCommand.

Describe alternatives you've considered

I've been listing out the contents of Body from the response and attempting to read from the socket etc. but have not yet been able to read the string that comes back from S3.

Additional context

Object.keys(response.Body) returns the following:

[
  "_readableState",
  "readable",
  "_events",
  "_eventsCount",
  "_maxListeners",
  "socket",
  "connection",
  "httpVersionMajor",
  "httpVersionMinor",
  "httpVersion",
  "complete",
  "headers",
  "rawHeaders",
  "trailers",
  "rawTrailers",
  "aborted",
  "upgrade",
  "url",
  "method",
  "statusCode",
  "statusMessage",
  "client",
  "_consuming",
  "_dumped",
  "req"
]

Not getting the list of identity-pools while running yarn identity-pools

Describe the bug
While following the instructions mentioned in frontend redme of exercise 1, when I reached to execute the command to yarn identity-pools, it shows the identity-pool as empty array.

To Reproduce
Steps to reproduce the behavior:

  1. Go to frontend redme of exercise 1
  2. Follow the instructions
  3. While executing yarn identity-pools, it shows the empty list

Expected behavior
Instructions should be clear to find the right data.

Desktop (please complete the following information):

  • OS: ios
  • Browser Chrome
  • Version Latest

Additional context
yarn run v1.17.3
$ aws cognito-identity list-identity-pools --max-results 20
{
"IdentityPools": []
}
โœจ Done in 1.24s.

Update workshop code to use webpack 5 on backend

Is your feature request related to a problem? Please describe.
Webpack 5 release is planned on 2020-10-10 webpack/webpack#11406

Describe the solution you'd like
The backend code in workshop repo uses webpack 5
Currently it uses webpack 4

"webpack": "4.44.1",
"webpack-cli": "3.3.11"

Describe alternatives you've considered
Continue using webpack 4 as it's not going to be deprecated anytime soon.

Additional context
Webpack 5 fixes the bug with tree shaking in multiple entry points webpack/webpack#4453
Existing hack to avoid that bug

const entry = glob.sync("./src/*.ts").reduce((acc, item) => {
const name = item.replace("./src/", "").replace(".ts", "");
acc[name] = item;
return acc;
}, {});

Exercise 1 - confusion in running clean resources

Reading the page from top to bottom, it seems like you wouldn't want to clean your resources until after going through all of the exercise change the import statements. Currently it leaves the impression that I should run it before starting the "Activities" section.

Importing the commands doesn't reduce lambda bundle size

Describe the bug
Importing the commands doesn't reduce lambda bundle size.
The bundle size does reduce in frontend (create-react-app) though.

To Reproduce
Documented in README:

Expected behavior
Importing the commands should reduce lambda bundle size, like it happened in 1.0.0-preview.

Write tsmorph or codemod scripts to update workshop code from v2 to v3

Is your feature request related to a problem? Please describe.
To experiment with workshop code in v3, attendees manually have to make changes suggested in README. They can't jump to Exercise 2 without completing Exercise 1

Describe the solution you'd like
Write and provide tsmorph or codemod scripts to move from v2 to v3 in workshop code. These scripts can later also be shared with customers for easy upgrade.

Describe alternatives you've considered
Having separate folders with workshop repo using v3 as we were doing it in the past, but it was a burden to maintain duplicate code.
The duplicate code couldn't be removed without affecting workshop flow.

Simplify the workshop by reducing duplicate code and automating steps

Is your feature request related to a problem? Please describe.

There is lot of duplicate code in this workshop

If you go through the README, the things changing while moving to v3:

  • importing client in libs/dynamoDB.ts - can be exported to a util used by both v2 and v3

    -import { DynamoDB } from "@aws-sdk/client-dynamodb-node";
    +import { DynamoDBClient } from "@aws-sdk/client-dynamodb-node";
    
    -export default new DynamoDB({});
    +export default new DynamoDBClient({});
  • importing commands in individual files - can be avoided by exporting utils for individual commands (say putItem in this case)

    import crypto from "crypto";
    -import dynamoDB from "./libs/dynamoDB";
    +import dynamoDBClient from "./libs/dynamoDB";
    +import { PutItemCommand } from "@aws-sdk/client-dynamodb-node";
    import { success, failure } from "./libs/response";

The attendees have to go through lot of manual steps in this workshop.

This can be avoided by using AWS CDK for automating infrastructure
Example: https://github.com/trivikr/cdk-typescript-workshop

Describe the solution you'd like
One solution I can think of is using yarn workspaces, and creating 4 packages:

  • aws-sdk-js-utils
    • contains utils which use AWS JS SDK v2, and can be called from aws-sdk-js-workshop
  • aws-sdk-js-v3-utils
    • contains utils which use AWS JS SDK v3, and can be called from aws-sdk-js-workshop
  • aws-sdk-js-workshop
    • The actual code for note taking application - where the only change workshop attendee will make is changing whether to import aws-sdk-js-utils or aws-sdk-js-v3-utils
  • aws-sdk-js-workshop-infra
    • The cdk application for deploying aws-sdk-js-workshop

By following this setup, workshop attendee will find it easy to go through the workshop code. And they'll spend most of the time on aws-sdk-js-utils package (experimenting with moving it to v3)

Describe alternatives you've considered
Following the existing setup which is difficult to follow, and workshop attendees make lot of mistakes because of process involved.

Explore using Vue 3 instead of React in Frontend

Is your feature request related to a problem? Please describe.
Not a problem, but it's worth testing ToDo app in community driven UX library like Vue.
They just released v3 which is written in TypeScript and uses no classes https://github.com/vuejs/vue-next/releases/tag/v3.0.0

React is a great UX library, but had some concerns because of Facebook ownership in the past.
For example, BSD+Patents LICENSE back in 2017 which was changed to MIT https://www.freecodecamp.org/news/facebook-just-changed-the-license-on-react-heres-a-2-minute-explanation-why-5878478913b2/

Describe the solution you'd like
Frontend written in [email protected] instead of React

Describe alternatives you've considered
Sticking with React for Frontend, as it's still the most popular UX library out there.

Use JavaScript SDK/CDK instead of aws cli or sam cli for setting up infrastructure

Is your feature request related to a problem? Please describe.

  • We currently use AWS CLI and SAM CLI for managing infrastructure in exercises
  • Since this is a workshop for JavaScript SDK v3, how about using JS SDK for managing the infrastructure?

Describe the solution you'd like
Use JavaScript SDK/CDK instead of aws cli or sam cli for setting up infrastructure

Environment variable not supported on Windows

While using Windows 10 and following through exercise 1, the AWS_JS_SDK_ID was not handled properly, resulting in:

image

As a workaround, I changed all instances f $AWS_JS_SDK_ID in package.json

Publish this repo as starter kit package

Is your feature request related to a problem? Please describe.
Currently workshop users needs to fork and clone the repo, install the dependencies and execute the prerequisites. Multiple commands are involved.

Describe the solution you'd like
With the yarn starter kit package feature, users and establish the workspace from a template via yarn create xxx. In the post-install script, we can add script to install the dependency, transpiling, bundling, and prompt to config AWS credentials. It automates the configuration process and less error-prone.

Describe alternatives you've considered
GitHub template repository enable users create a local repository with the same directories, branches and files. This is helpful if the library will have multiple branches. But it doesn't support lifecycle scripts as yarn starter kit packages. Yarn starter kit package solution can potentially support multiple branches is .git is published.

Redme instructions are not very clear

Describe the bug
When I am following the instructions in redme, it is not clear on backend redme till how long we should go and in frontend redme when to start.

To Reproduce
Steps to reproduce the behavior:

  1. Go to main redme
  2. Click on backend redme
  3. When to jump to front redme is not clear

Expected behavior
Clear instructions for how long we should follow backend redme, the frontend and backend redme can be done in parellel.
Screenshots

Desktop (please complete the following information):

  • OS: OS
  • Browser Chrome
  • Version latest

Use React with snowpack instead of webpack

Is your feature request related to a problem? Please describe.
CRA is way to bloated. The commands take time to run. It also has too many dependencies, some of them get security warnings from time-to-time.
Here's an article from Feb 2019 which goes through CRA dependencies in detail: https://hackernoon.com/create-react-app-is-way-too-bloated-5db07c3511

Describe the solution you'd like
Use a faster frontend build tool like Snowpack.
CreateApp frontend build config generator just added support for Snowpack at: https://createapp.dev/snowpack

Describe alternatives you've considered
Stick with create-react-app. It's slow, but stable and gets work done.

Update README based on updates in #176

Is your feature request related to a problem? Please describe.
The README is not updated with instructions/screenshots in PR #176

Describe the solution you'd like
Post a PR with following README files updated on simplify-workshop branch https://github.com/aws-samples/aws-sdk-js-v3-workshop/tree/simplify-workshop:

Priorities for updating README:

  • Latest diffs required to move from v2 to v3
  • Screenshots of the package sizes using latest version of v2, and latest gamma version of v3
  • Updated setup and instructions
  • Comparison between v3 and v2 lambda duration

Switch to React Router once v6 is released

Is your feature request related to a problem? Please describe.
Workshop repo uses @reach/router which was put on path of deprecation in favor of React Router
Post from May 17th, 2019 https://reacttraining.com/blog/reach-react-router-future/

Describe the solution you'd like
Switch to Reach Router once v6 stable version is released.
As of June 2020, it's in beta https://github.com/ReactTraining/react-router/releases/tag/v6.0.0-beta.0

Describe alternatives you've considered
Stick with @reach/router, as it continues to get bugfixes.

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.