Giter VIP home page Giter VIP logo

lambda-comments's Introduction

Lambda Comments

This project which implements a minimal blog commenting service.

Blog posts:

Hacker News thread: https://news.ycombinator.com/item?id=11644042

It is completely "serverless", designed to use the following Amazon services:

The Lambda functions are written in ES6, with async/await, transpiled using Babel, and bundled using Webpack.

The AWS resources are provisioned using the CloudFormation service.

Additionally, we use Apex to simplify the uploading of the Lambda functions (without the shim).

Costs

It should cost very little to run. The following resources are provisioned:

  • DynamoDB - only provisioned for 1 read capacity unit, 1 write capacity unit (which limits it to 1 job per second). This is the most expensive resource, approximately $0.65 a month.
  • S3 - storage for comments and private data, plus requests and data transfer
  • CloudWatch Logs
  • Lambda functions - only pay for invocations, first million requests per month are free (hopefully your blog isn't that popular)
  • API gateway - only pay for API calls

Deployment Instructions

Prerequisites

  • You will need an AWS Account
  • You will need OS X, Linux, *BSD or another Unix-based OS (scripts will need some modifications for Windows)
  • Install the AWS CLI and ensure credentials are setup under ~/.aws/credentials (Instructions)
  • Install Node.js (tested with v4.2.6 and v5.7.0)
  • git clone https://github.com/jimpick/lambda-comments.git (https)
    or
    git clone [email protected]:jimpick/lambda-comments.git (git)
  • cd lambda-comments
  • npm run install-all (runs npm install in top directory, and then sets up sub-packages under packages)
  • Install Apex

Configuration

Copy .env.SAMPLE to .env and customize it.

cp .env.SAMPLE .env

The default .env.SAMPLE contains:

# The URL of your blog/website that will be hosting the comments
# Used to generate CORS headers and also for Akismet
BLOG=https://example.com/blog/

# A name for your CloudFormation stack
# Also prefixed to the API Gateway REST API name
CLOUDFORMATION=myBlogComments

# The AWS region to provision the resources in
REGION=us-west-2

# The name for the API Gateway stage
STAGE=prod

# The Akismet.com API key (optional, but recommended)
# Akismet is a service for combatting blog spam from Automattic (WordPress)
#AKISMET=0123456789ab

# A Slack webhook to send notifications to (optional)
#SLACK=https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ

We use dotenv so it is also possible to configure the project by setting environment variables.

Parameters

BLOG: The full base url of the blog/website

CLOUDFORMATION: The name of the CloudFormation stack

REGION: The AWS region

STAGE: The API Gateway stage to create

AKISMET: (Optional, but recommended) API key from akismet.com for spam filtering

SLACK: (Optional) Slack webhook - configure this if you want a notification in a Slack channel each time a comment is posted

Installation

For now, follow the step-by-step instructions below. In the future, we will develop a streamlined installation procedure.

Use CloudFormation to create the AWS resources

npm run create-cloudformation

The command returns immediately, but it will take a while to complete (typically 3-4 minutes). It's a good idea to watch the CloudFormation task in the AWS Web Console to ensure that it completes without errors.

Note: When working with the CloudFormation recipe, you can also use npm run update-cloudformation and npm run delete-cloudformation

Save the references to the provisioned CloudFormation resources

npm run save-cloudformation

This will create a file in deploy/state/cloudFormation.json

Temporary fix - update Lambda functions to use Node.js 4.3

CloudFormation has issues setting the runtime to 'nodejs4.3', see:

https://forums.aws.amazon.com/thread.jspa?threadID=229072

Until CloudFormation is updated, here's an extra step to update the Lambda functions to use Node.js 4.3 using a custom script.

npm run flip-lambdas-to-4.3

Generate an API key

npm run gen-api-key

This will create a file in deploy/state/apiKey.json containing an apiKey variable that will be baked into the client to sign requests.

The purpose of the API key is to try to minimize spam to the API, but as the API key is distributed publicly as part of the javascript, it's only there to stop non-sophisticated spammers who don't care enough to extract the API key and sign their requests.

Setup the Apex build directory

npm run setup-apex

This generates build/apex/project.json

Compile the Lambda scripts using babel

npm run compile-lambda

This will use webpack and babel to compile the source code in src/server/lambdaFunctions into build/apex/functions

The webpack configuration is in deploy/apex/webpack.config.es6.js

Deploy the lambda functions

npm run deploy-lambda

This will run apex deploy in the build/apex directory to upload the compiled lambda functions.

Alternatively, if you want to execute the compile and deploy steps in one command, you can run: npm run deploy-backend

Build the frontend javascript

npm run build-frontend

This builds the code in the packages/frontend directory.

Upload the frontend javascript script to S3

npm run upload-script

This will copy lambda-comments.js to the S3 bucket.

Alternatively, if you want to execute the compile and deploy steps in one command, you can run: npm run deploy-frontend.

If you want to deploy the backend and frontend all in one step, you can use: npm run deploy

Run the test suite

npm run test

This will run both the local tests, and remote test which test the deployed API and lambda functions.

The local tests can be run as npm run test-local, and the remote tests can be run as npm run test-remote.

Currently the test suite expects some data to pre-exist in the S3 bucket. Until the tests are properly mocked, they will fail unless the data is created.

View logs

You can tail the CloudWatch logs:

npm run logs

This just executes apex logs -f in build/apex

Embed the front-end JavaScript client

First, get the URL for the script:

npm run get-client-js-url

This will return a URL you will use below. eg.

//s3-us-west-2.amazonaws.com/myblogcomments-websites3-1ttpk69ph7gr7/lambda-comments.js

In the target web page (perhaps a blog generated by a static site generator such as Jekyll or Hugo), add the following HTML to insert the comments from the development server into the page:

<div id="lambda-comments"></div>
<script src="*** url from above ***"></script>

Providing that the webpage is located at the web address matching the 'BLOG' setting in the .env configuration file, the comments form should appear on the page. If not, check the developer tools console in the web browser to see if there are any errors (typically due to CORS).

Front-end development

The code for the "front-end" javascript that displays the comments and the comment form embedded in a web page lives in the packages/frontend directory.

To run a development server, change into the packages/frontend directory, copy .env.SAMPLE to .env, and run the development server.

cd packages/frontend
cp .env.SAMPLE .env
npm start

The development server is based on react-project with a heavily modified webpack configuration in webpack.config.js.

In the target web page (perhaps a blog generated by a static site generator such as Jekyll or Hugo), add the following HTML to insert the comments from the development server into the page:

<div id="lambda-comments"></div>
<script src="http://localhost:8081/lambda-comments.js"></script>

To Do List

  • Limit length of comments and metadata
  • Simplified installation
  • Check that permalink and blog match
  • Override for path location
  • Fetch source page to confirm script is installed on first post
  • Test on various browsers, polyfills
  • CORS override
  • Rearrange code: put lambda scripts under packages directory
  • Admin: auth
  • Admin: moderation
  • Admin: submit ham/spam to akismet
  • Admin: Turn comments on/off
  • Support for editing blog posts for a limited time
  • Detect DDoS style attacks and automatically throttle API Gateway to prevent unlimited charges
  • Mocks for AWS/API calls
  • Integration test
  • Selenium tests
  • Coverage
  • Emoji support
  • Handle DynamoDB ProvisionedThroughputExceededException
  • Investigate Swagger
  • Generate API docs
  • Webpack 2 tree-shaking support
  • Optimize download size
  • Plugins for server-side rendering on common static site generators
  • Optimized bundle for ES6-capable platforms
  • Library for bundling with existing client-side javascript builds
  • Investigate deep integration with React.js static site generators
  • Gatsby
  • Phenomic
  • Instructions for static-ish hosting platforms
  • GitHub Pages
  • Surge
  • Netlify
  • Aerobatic
  • Firebase
  • Zeit

Interesting links

Lots of related projects, many of which I haven't investigated yet.

Lambda / Serverless Frameworks

Lambda Libraries

Awesome Lists

Serverless Comment Systems

Open-source Comment Systems

Hosted Comment Platforms

lambda-comments's People

Contributors

jimpick 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

lambda-comments's Issues

Use root akismet-api package

Hey there, congrats on reaching the front page of HN!
A colleague pointed out that you're using a forked version of my akismet-api library, I'm glad it's useful for building this. I was curious about the changes and I noticed you just updated superagent.

I had an issue for that here, but superagent changes the way it passes around errors in 1.0 so I had to do some additional testing to make sure everything was good.

I just released a new version (2.1.0) that supports superagent 1.8.3, so you might want to consider using the root akismet-api package again! If you have any other suggestions for the library, feel free to make an issue or pull request!

Can't get it to run NPM test and pass

Tried to use today and everything worked until I got to the npm run test. Getting the following error:

1 failing

  1. local Post new comment to the queue should catch spam:
    Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.1/bin/node" "/usr/local/bin/npm" "run" "test"
npm ERR! node v6.2.1
npm ERR! npm v3.10.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] test: mocha --compilers js:./babel-register
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test script 'mocha --compilers js:./babel-register'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the lambda-comments package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! mocha --compilers js:./babel-register
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs lambda-comments
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls lambda-comments
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/jbrodley/lambda-comments/npm-debug.log

from Debug log.

sxjbrodmbp:lambda-comments jbrodley$ vi /Users/jbrodley/lambda-comments/npm-debug.log

11 silly lifecycle [email protected]test: Args: [ '-c', 'mocha --compilers js:./babel-register' ]
12 silly lifecycle [email protected]
test: Returned: code: 1 signal: null
13 info lifecycle [email protected]~test: Failed to exec test script
14 verbose stack Error: [email protected] test: mocha --compilers js:./babel-register
14 verbose stack Exit status 1
14 verbose stack at EventEmitter. (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:242:16)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at EventEmitter.emit (events.js:191:7)
14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:40:14)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at ChildProcess.emit (events.js:191:7)
14 verbose stack at maybeClose (internal/child_process.js:852:16)
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)
15 verbose pkgid [email protected]
16 verbose cwd /Users/jbrodley/lambda-comments
17 error Darwin 15.6.0
18 error argv "/usr/local/Cellar/node/6.2.1/bin/node" "/usr/local/bin/npm" "run" "test"
19 error node v6.2.1
20 error npm v3.10.5
21 error code ELIFECYCLE
22 error [email protected] test: mocha --compilers js:./babel-register
22 error Exit status 1
23 error Failed at the [email protected] test script 'mocha --compilers js:./babel-register'.
23 error Make sure you have the latest version of node.js and npm installed.
23 error If you do, this is most likely a problem with the lambda-comments package,
23 error not with npm itself.
23 error Tell the author that this fails on your system:
23 error mocha --compilers js:./babel-register
23 error You can get information on how to open an issue for this project with:
23 error npm bugs lambda-comments
23 error Or if that isn't available, you can get their info via:
23 error npm owner ls lambda-comments
23 error There is likely additional logging output above.
24 verbose exit [ 1, true ]

Working example?

Hello - is this in use anywhere that I can take a look?
Kind regards

Form does not show (OSX - Node v6.2.2) / Test fails (Linux - Node v5.7.0)

Hello, first of all thank you for your work. Second, I successfully deployed API and lambda functions and embed the javascript (without the akismet option). First with Node 6.0.0 then I tried with Node 6.2.2, both on OSX. Npm always runs test successfully but the only thing that appears in my page are these divs

div id="lambda-comments"
div data-reactid=".0"

so no comment form. No CORS errors in the browser. Apparently it is a frontend problem.

I also tried on a Linux VM with Node 5.7.0 (with and without sudo) and test fails (sometime it even fails during the install, running BootstrapCommand.execute when linking lambda-comments-utils dependencies). In this VM I am building without the akismet API key as well.

npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: [email protected]
Lerna v2.0.0-beta.9
Linking all dependencies
Errored while running BootstrapCommand.execute
Error: Command failed: npm install [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.>

at ChildProcess.exithandler (child_process.js:202:12)
at emitTwo (events.js:100:13)
at ChildProcess.emit (events.js:185:7)
at maybeClose (internal/child_process.js:827:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)> 

npm ERR! Linux 4.4.14-24.50.amzn1.x86_64
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "install-all"
npm ERR! node v5.7.0
npm ERR! npm v3.10.6
npm ERR! code ELIFECYCLE
npm ERR! [email protected] install-all: npm install && lerna bootstrap && linklocal
npm ERR! Exit status 1

but if I re-run it successfully bootstrapps. And this is my test

passing (66ms)
8 failing>

  1. local Post new comment to the queue should return an id:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:33:29)>

  2. local Post new comment to the queue should fail if there is no data:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:55:29)>

  3. local Post new comment to the queue should catch spam:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:90:29)>

  4. local Post new comment to the queue should fail with a bad signature:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:124:29)>

  5. local Post new comment to the queue should allow posting hangul characters:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:159:29)>

  6. remote Post new comment to the queue should return an actionRef:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:214:29)>

  7. remote Post new comment to the queue should fail if there is no data:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:224:29)>

  8. remote Post new comment to the queue should allow posting hangul characters:
    TypeError: this is not a typed array.
    at Function.from (native)
    at Context. (test.js:252:29)>

Any suggestion?

'npm start' in packages/frontend fails with Node 6.1.0

$ npm start

> @jimpick/[email protected] start /Users/jim/projects/comments/lambda-comments/packages/frontend
> if-env NODE_ENV=production && npm run react-project:start:prod || npm run react-project:start:dev


> @jimpick/[email protected] react-project:start:dev /Users/jim/projects/comments/lambda-comments/packages/frontend
> eslint src && react-project start

[react-project] [start] task
[react-project] checking app dependencies
[react-project] Some of your dependencies don't match what I expect
[react-project] You have: [email protected] and I expect [email protected]
[react-project] You have: [email protected] and I expect [email protected]
[react-project] You have: [email protected] and I expect [email protected]
[react-project] You have: [email protected] and I expect [email protected]
[react-project] You might want to `npm install` the versions I expect.
[react-project] NODE_ENV=development
/Users/jim/projects/comments/lambda-comments/packages/frontend/node_modules/react-project/lib/build.js:53
    if (err) throw err;
             ^

TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.dirname (path.js:1324:5)
    at /Users/jim/projects/comments/lambda-comments/packages/frontend/node_modules/babel-core/lib/transformation/file/options/option-manager.js:374:36
    at /Users/jim/projects/comments/lambda-comments/packages/frontend/node_modules/babel-core/lib/transformation/file/options/option-manager.js:396:22
    at Array.map (native)
    at OptionManager.resolvePresets (/Users/jim/projects/comments/lambda-comments/packages/frontend/node_modules/babel-core/lib/transformation/file/options/option-manager.js:385:20)
    at OptionManager.mergePresets (/Users/jim/projects/comments/lambda-comments/packages/frontend/node_modules/babel-core/lib/transformation/file/options/option-manager.js:369:10)

npm run install-all fails, then just plain old npm install fails

sudo npm run install-all gives:

npm ERR! Linux 3.13.0-74-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "run" "install-all"
npm ERR! node v6.1.0
npm ERR! npm  v3.8.6
npm ERR! code ELIFECYCLE
npm ERR! @jimpick/[email protected] install-all: `npm install && cd packages/frontend && npm install`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the @jimpick/[email protected] install-all script 'npm install && cd packages/frontend && npm install'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the @jimpick/lambda-comments package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     npm install && cd packages/frontend && npm install
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs @jimpick/lambda-comments
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls @jimpick/lambda-comments
npm ERR! There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! Please include the following file with any support request:
npm ERR!     /home/ubuntu/lambda-comments/npm-debug.log

sudo npm install on its own gives:

npm ERR! Linux 3.13.0-74-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! node v6.1.0
npm ERR! npm  v3.8.6                                                                      npm ERR! code E404

npm ERR! 404 Not found : @jimpick/akismet-api
npm ERR! 404                                                                              npm ERR! 404  '@jimpick/akismet-api' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 It was specified as a dependency of '@jimpick/lambda-comments'               npm ERR! 404 
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/ubuntu/lambda-comments/npm-debug.log

Something tells me that this may have to do with the recent security upgrade to 6.x and the apparent phasing-out of 5.x.

Changing Access-Control-Allow-Origin header from https to http

After I enable the frontend I get:

GET https://s3-eu-central-1.amazonaws.com/myblogcomments-../comments.json 403 (Forbidden)

And when posting:

"Fetch API cannot load https://xxx.execute-api.eu-central-1.amazonaws.com/prod/comments. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://www.website.org' that is not equal to the supplied origin. Origin 'http://www.website.org' is therefore not allowed access. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."

I can't seem to be able to change from https to http, any hint on how to change it?

Allows posting of empty content

Entering spaces as content, or anything that will render to an empty markdown section is currently permitted.

Add some checks to ensure that the markdown renders out to something.

In lambda-comments.json, line 145 and 181, change "nodejs" to "nodejs4.3"

Hi Jim,

My name is Vam. I live in Beijing, China. First of all, I want to say - thank you very much!! I am so so excited when I found your work - It is exactly what I need and it is amazing! You know that Disqus and many other popular sites are blocked in China for some reasons. And I want to have a simple commenting system that can be accessed from China and all over the world. I spent a lot of time tried to find a right one but I didn't. Until I see your Lambda-comments. And I agreed with your point of view from "Introducing lambda-comments". I just integrated it. Please have a look:

http://vamworks.com/2016/paintings-and-drawings-by-me-before-2016/

However, during the process I got a problem: when I create a stack via the command:

npm run create-cloudformation

I saw this message when I check my AWS CloudFormation console:

console of CloudFormation: ROLLBACK_COMPLETE

lambdacomments-01

When click the stack name, I see the following problem from log:

Logical ID:

QueueCommentLambdaFunction

Status reason:

The runtime parameter of nodejs is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs4.3) while creating or updating functions.

lambdacomments-02

I spent some time to did research and finally I found the answer:

http://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html

In lambda-comments.json, line 145 and 181, change "nodejs" to "nodejs4.3".

After that, it works very well!

:)

Best Regards,

Vam

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.