Giter Site home page Giter Site logo

cupcakearmy / cryptgeon Goto Github PK

View Code? Open in Web Editor NEW
775.0 5.0 81.0 1.15 MB

cryptgeon is a secure, open source note / file sharing service inspired by PrivNote written in rust & svelte.

Home Page: https://cryptgeon.org/

License: MIT License

Rust 13.47% CSS 2.36% HTML 0.25% Svelte 43.61% TypeScript 31.54% JavaScript 8.10% Dockerfile 0.68%
private-notes privnote secure-notes note-sharing file-sharing

cryptgeon's Introduction

logo

discord docker pulls Docker image size badge Latest version



Cryptgeon - Securely share self-destructing notes | Product Hunt

EN | 简体中文 | ES

About?

cryptgeon is a secure, open source sharing note or file service inspired by PrivNote. It includes a server, a web page and a CLI client.

🌍 If you want to translate the project feel free to reach out to me.

Thanks to Lokalise for providing free access to their platform.

Live Service / Demo

Web

Check out the live service / demo and see for yourself cryptgeon.org

CLI

npx cryptgeon send text "This is a secret note"

For more documentation about the CLI see the readme.

Features

  • send text or files
  • server cannot decrypt contents due to client side encryption
  • view or time constraints
  • in memory, no persistence
  • obligatory dark mode support

How does it work?

each note has a generated id (256bit) and key 256(bit). The id is used to save & retrieve the note. the note is then encrypted with aes in gcm mode on the client side with the key and then sent to the server. data is stored in memory and never persisted to disk. the server never sees the encryption key and cannot decrypt the contents of the notes even if it tried to.

Screenshot

screenshot

Environment Variables

Variable Default Description
REDIS redis://redis/ Redis URL to connect to. According to format
SIZE_LIMIT 1 KiB Max size for body. Accepted values according to byte-unit.
512 MiB is the maximum allowed.
The frontend will show that number including the ~35% encoding overhead.
MAX_VIEWS 100 Maximal number of views.
MAX_EXPIRATION 360 Maximal expiration in minutes.
ALLOW_ADVANCED true Allow custom configuration. If set to false all notes will be one view only.
ALLOW_FILES true Allow uploading files. If set to false, users will only be allowed to create text notes.
THEME_NEW_NOTE_NOTICE true Show the message about how notes are stored in the memory and may be evicted after creating a new note. Defaults to true.
ID_LENGTH 32 Set the size of the note id in bytes. By default this is 32 bytes. This is useful for reducing link size. This setting does not affect encryption strength.
VERBOSITY warn Verbosity level for the backend. Possible values are: error, warn, info, debug, trace
THEME_IMAGE "" Custom image for replacing the logo. Must be publicly reachable
THEME_TEXT "" Custom text for replacing the description below the logo
THEME_PAGE_TITLE "" Custom text the page title
THEME_FAVICON "" Custom url for the favicon. Must be publicly reachable

Deployment

ℹ️ https is required otherwise browsers will not support the cryptographic functions.

ℹ️ There is a health endpoint available at /api/health/. It returns either 200 or 503.

Docker

Docker is the easiest way. There is the official image here.

# docker-compose.yml

version: '3.8'

services:
  redis:
    image: redis:7-alpine
    # Set a size limit. See link below on how to customise.
    # https://redis.io/docs/manual/eviction/
    # command: redis-server --maxmemory 1gb --maxmemory-policy allkeys-lru

  app:
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - redis
    environment:
      # Size limit for a single note.
      SIZE_LIMIT: 4 MiB
    ports:
      - 80:8000

    # Optional health checks
    # healthcheck:
    #   test: ["CMD", "curl", "--fail", "http://127.0.0.1:8000/api/live/"]
    #   interval: 1m
    #   timeout: 3s
    #   retries: 2
    #   start_period: 5s

NGINX Proxy

See the examples/nginx folder. There an example with a simple proxy, and one with https. You need to specify the server names and certificates.

Traefik 2

See the examples/traefik folder.

Scratch

See the examples/scratch folder. There you'll find a guide how to setup a server and install cryptgeon from scratch.

Synology

There is a guide you can follow.

YouTube Guides

Written Guides

Development

Requirements

  • pnpm: >=6
  • node: >=18
  • rust: edition 2021

Install

pnpm install

# Also you need cargo watch if you don't already have it installed.
# https://lib.rs/crates/cargo-watch
cargo install cargo-watch

Run

Make sure you have docker running.

pnpm run dev

Running pnpm run dev in the root folder will start the following things:

  • redis docker container
  • rust backend
  • client
  • cli

You can see the app under localhost:1234.

There is a Postman collection with some example requests available in the repo

Tests

Tests are end to end tests written with Playwright.

pnpm run test:prepare

# Use the test or test:local script. The local version only runs in one browser for quicker development.
pnpm run test:local

Security

Please refer to the security section here.


Attributions

cryptgeon's People

Contributors

cbin avatar codiflow avatar cupcakearmy avatar dependabot[bot] avatar hash070 avatar ktamas avatar luolongfei avatar mairusupawa avatar mvs avatar pgschk avatar rooyca avatar stiivo avatar zocimek 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

cryptgeon's Issues

File upload bug

SIZE_LIMIT is 250MiB
File I'm trying to upload is 39.8MiB
But it's throwing:
thread 'actix-rt:worker:3' panicked at 'called `Result::unwrap()` on an `Err` value: CommandError(ValueTooLarge)', src/store.rs:20:42

I'm using nginx:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name note.website.com;

    include /config/nginx/ssl.conf;

    client_max_body_size 500m;

    location / {
        include /config/nginx/proxy.conf;
           proxy_pass http://192.168.0.108:13791/;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
    }
}

image

Unauthenticated Paths when limiting note creation to authentik users

I had previously used authentik proxy to limit access to note creation, but used:
^/note
as an unauthenticated path to allow guests to view the notes.

This no longer appears to be working.

I'm assuming I need to add a few more now, any help would be greatly appreciated.

Feature: Easy all In One install Script

A simple one liner copy and paste code that downloads a script and executes everything it needs to to get Cryptgeon up and running with a valid Let Encrypt cert and good default settings. Compatible with Debian 11 and Ubuntu 20.04

Basically a set it and forget it

This should help people get this up and running much quicker

I love this project You did great work and its very clean =]

Version 2.2 does not work with docker - x86

Hi,

the new version 2.2 seems to cause problems with docker.
Unfortunately, there are no logs that i can provide.

if I set the version to "2.1" in my cocker-compose.yml, everything works as expected again.

my yaml

version: '3'

services:
  redis:
    container_name: redis
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --maxmemory 1gb --maxmemory-policy allkeys-lru
    deploy:
      resources:
        limits:
          memory: 1GiB
    networks: [cryptgeon]

  app:
    container_name: cryptgeon
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - redis
    environment:
      SIZE_LIMIT: 50MiB
    ports:
      - 5000:5000
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 128M
    networks: [cryptgeon]

networks:
    cryptgeon:
        external: true

Wrong validation for max views in client

Discussed in #57

Originally posted by JoeyVisbeen September 14, 2022
At the advanced options the amount of views one can give to a secret starts at 0 and goes up to 9. Being 1 to 10, the application doesn't accept 10.

Availability message

We are using Cryptgeon on a server that I host for clients to send files securely to us.

Most of the clients have been calling regarding the message below before they send out a file. Is there anyway to remove or replace it. This will reduce the amount of explanations.

availability:
the note is not guaranteed to be stored as everything is kept in ram, if it fills up the oldest notes will be removed.
(you probably will be fine, just be warned.)

Thank you for your time on this project and giving back to the Free and Open Source Community. Keep up the good work!

Already have NPM, want to load on https://example.com/note - blank screen

Hey y'all - forgive me as I'm relatively new to reverse proxies, etc. I've been looking for self-hosted alternative to privnote, and the internet said this is the best one! LOL So, I'm trying it out. I'm able to load it locally over http but obviously it won't encrypt since the note on the README indicates cryptographic functions only work over https. I already have NGINX Proxy Manager and I already have a subdomain I'd like to use. In NPM, I have set up a custom location for the subdomain:
sub.example.com/note

Under this custom location, I indicated the IP and Port I configured in docker-compose.yml and then used the parameters included in examples/nginx/nginx-plain.conf and added these:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

However, when I load https://sub.example.com/note - I'm met with a blank screen. Here's a copy of my docker-compose.yml file:

version: '3.8'

services:
  redis_cryptgeon:
    image: redis:7-alpine
    # Set a size limit. See link below on how to customise.
    # https://redis.io/docs/manual/eviction/
    # command: redis-server --maxmemory 1gb --maxmemory-policy allkeys-lru

  app:
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - redis_cryptgeon
    environment:
      # Size limit for a single note.
      SIZE_LIMIT: 4 MiB
      VERBOSITY: debug
    ports:
      - 5080:5000

Here's a copy of the debug log:

cryptgeon-app-1              | [2022-11-15T16:11:47Z INFO  actix_server::builder] Starting 12 workers
cryptgeon-app-1              | [2022-11-15T16:11:47Z INFO  actix_server::server] Actix runtime found; starting in Actix runtime
cryptgeon-redis_cryptgeon-1  | 1:C 15 Nov 2022 16:11:47.283 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
cryptgeon-redis_cryptgeon-1  | 1:C 15 Nov 2022 16:11:47.283 # Redis version=7.0.5, bits=64, commit=00000000, modified=0, pid=1, just started
cryptgeon-redis_cryptgeon-1  | 1:C 15 Nov 2022 16:11:47.283 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
cryptgeon-redis_cryptgeon-1  | 1:M 15 Nov 2022 16:11:47.283 * monotonic clock: POSIX clock_gettime
cryptgeon-redis_cryptgeon-1  | 1:M 15 Nov 2022 16:11:47.284 * Running mode=standalone, port=6379.
cryptgeon-redis_cryptgeon-1  | 1:M 15 Nov 2022 16:11:47.284 # Server initialized
cryptgeon-redis_cryptgeon-1  | 1:M 15 Nov 2022 16:11:47.284 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
cryptgeon-redis_cryptgeon-1  | 1:M 15 Nov 2022 16:11:47.284 * Ready to accept connections
cryptgeon-app-1              | [2022-11-15T16:16:41Z DEBUG actix_files::service] error handling /note: No such file or directory (os error 2)
cryptgeon-app-1              | [2022-11-15T16:16:41Z INFO  actix_web::middleware::logger] "GET /note HTTP/1.1" 200 898 0.000643

It seems it's also trying to load /note on the container, which obviously doesn't exist. I'm not entirely sure how to make it load on a sub-directory in the URL which already includes a subdomain. Otherwise, I'd just create a new subdomain such as note.example.com and just have it load that way, but unfortunately, I'm unable to add a new subdomain. Any ideas/help on how to get this to load properly? I'm sure I'm missing something, but I don't know how to properly phrase the search terms to get what I'm trying to do....

No indication when decrypted note is copied to clipboard.

After decoding one-time note I press the "copy to clipboard" button.
In Firefox (Windows 10) there is no visual indication whether something happened or not.
(Text copied to clipboard correctly.)

Would be wonderful to have some visual representation like when copying the share link.

View count has no minimum value

The view count under advanced does not have a minimum value, and thus can be set to a negative number of views. If you click create note, it just gives an error. I think this could be corrected by adding the min property to the input field.

Screenshot 2022-11-11 at 20-17-38 cryptgeon

Default to Dark Mode?

Hi there,
Thanks for creating this webapp - its super cool!

I'm struggling to find the night mode toggle though? Is it possible to default to dark mode?

Thanks,

Some messengers can't cope with long links

Screenshot 2022-08-10 at 17 09 48

This is slack, for instance. See those [...] - some users are crazy enough to copy that.
This is more of a messenger issue, but if it can be changed on cryptgeon side, that would be nice.

Title tag & favico

Hi,

Would it be possible to implement variables to be able to set the title tag and a favicon?

Multiple File Uploads Enhancement

Multiple File Uploads by selecting one then clicking add additional to add more instead of holding ctrl click to select all files in the beginning

Cannot read property 'importKey' of undefined while creating message

Deployment via Docker:

version: '3.7'

services:
  memcached:
    image: memcached:1-alpine
    entrypoint: memcached -m 128 # Limit to 128 MB Ram, customize at free will.
    ports:
      - 11211:11211

  app:
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - memcached
    ports:
      - 8081:5000

index.svelte-2cde6fd6.js:1 TypeError: Cannot read property 'importKey' of undefined
at E (Button-93aec9d8.js:1)
at HTMLFormElement. (index.svelte-2cde6fd6.js:1)
at Generator.next ()
at index.svelte-2cde6fd6.js:1
at new Promise ()
at a (index.svelte-2cde6fd6.js:1)
at HTMLFormElement. (index.svelte-2cde6fd6.js:1)
at HTMLFormElement. (vendor-cb0ac300.js:1)

Code:

return window.crypto.subtle.importKey(

Feature Request: Multilanguage capable

Hello,

it would be great if you could maybe offer this application in multiple languages.
For example a

ENV LANGUAGE=EN

Would add the German translation.

Doesn't work with proxy_pass

Cryptogen doesn't allow to specify us "baseUrl" to support the following cases (nginx):

location /cryptogen/ {
    proxy_pass http://127.0.0.1:3000;
}

Using sub_filter "/_app/" "/cryptogen/_app/" doesn't solve the problem.

Please, consider adding baseUrl or similar option and env var for docker.

Update README.md

It would be well to update the readme to include further Installation details and more up-to-date information.

Example:

Development Installation:

Requirements:
PNPM? | What version?
Rust? | What version? | Rust Nightly?
.....? | What version?

Installation Options:

  1. Docker
    Steps...

Steps...

Steps...


Is pnpm i ; pnpm install, pnpm init? https://github.com/cupcakearmy/cryptgeon/blob/main/README.md#development

I am currently having errors and cant source the cause. #28

Could not create note.

Screenshot_20220209-215305
IMG_20220209_215600

Hi,
I have this issue. I pulled it with the Standard docker yml config and i only have changed from 4mb to 100mb. What is wrong? Kind regards

Expiration for all notes (even view constraint notes)

I've been using https://1ty.me/ but wanted to find a self hosted open source alternative, so was super happy to stumble across your creation today. Thanks so much.

I'm wondering whether it'd be an option to enable expiration for view constrain notes, this will prevent unused notes staying in redis indefinitely, and should be pretty easy to implement with a TTL on the redis key. Generally in my use, I also configure single view notes (so as long as the expected recipient received it I know no-one else has seen it), and I expect someone to pickup the note in the next hour or day etc., so would be nice to be able to configure MAX_EXPIRATION and allow a user to set the expiry for single view notes too.

In essence the combination of Expiration and View count would be very useful.

I don't have much Svelte or rust experience, but would be happy to help out if you feel it's something that'd server the broader use case.

HTTP 404 Error with new version 1.4

Hello,

with the new version i get a http 404 error when i create a new note.
1.3 version works but not the 1.4.

image

I tried to debug it, but cannot find the settings to turn logging on.

My docker-compose file:

version: '3.7'

services:
  memcached:
    container_name: memcached_cryptgeon
    image: memcached:1-alpine
    restart: unless-stopped
    entrypoint: memcached -m 256M
    ports:
      - 11211:11211

  app:
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - memcached
    environment:
      SIZE_LIMIT: 10M
    ports:
      - 80:5000

Docker environment variable for disabling file share

It would be great if you could disable the file share via a Docker variable and let users only send text. Or is there already a suitable Docker variable here? I haven't found anything suitable in the source code. Great project anyways!

cryptgeon fails after server restart

Hi, first thanks for this great piece of code!

I have one problem: Every time, I need to make a server restart, crypteon fails to start successfully.

After running docker-compose up -d again everything works fine.

I have a couple of docker services on that machine, cryptgeon is the only one not starting successfully after server restart.

Any idea on this?

Build error

I'm getting this error when building with the Dockerfile file.

Docker file build error

Solution : I solved the error by updating the vite version.

Cannot create notes

I run cryptgeon (latest version) inside Docker on my NAS at home and it worked flawlessly in the past. I haven't used it for a while but now when I try to create a new note a red message appears in the top right corner that the note couldn't be created.

The only thing Portainer shows in the logs is the following:
No log line matching the '' filter

Here's the stack I used to create the container.

version: '3.7'

services:
  memcached:
    container_name: Cryptgeon_Memcached
    image: memcached
    entrypoint: memcached -m 512M -I 64M

  app:
    container_name: Cryptgeon
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - memcached
    environment:
      SIZE_LIMIT: 64M
    ports:
      - 8120:5000

Is there any more information I can provide to look into the problem here?

Secret should not be a normal part in the url

Hi, nice looking app 😊

But I have one notice for you, you should not put the secret as normal part in the url like this:

https://cryptgeon.nicco.io/note/18l0rBija8mShKYjSUj49tL9TcTgzVYWMiT6E3RrmSRJw2xwQ0k1OzJxbb2oJuENDZRJ3tUsmFf5266DMithSVV/6565023d2d98cfd1c0fc08726d93e39bede97473c7528bd3f8bf4bc037350159

The problem with this URL is that the secret will send to the server and with a man in the middle attack, someone is able to see the key. Or if you are not delete the note after one visit, you can see the URL in the Access Logs and get the secret from there. If the note is still there, someone can see also the note.

Bildschirmfoto 2021-05-16 um 09 40 56

You can use a # for the URL part with the secret. The part with the # will be not send from the browser to the server.
Your client app is still able to read this key from the key

https://cryptgeon.nicco.io/note/18l0rBija8mShKYjSUj49tL9TcTgzVYWMiT6E3RrmSRJw2xwQ0k1OzJxbb2oJuENDZRJ3tUsmFf5266DMithSVV#6565023d2d98cfd1c0fc08726d93e39bede97473c7528bd3f8bf4bc037350159

privnote is also using a # 😉 https://privnote.com/JkRrzfWk#W4UuuU9M2

Cannot create notes

    I have the same Issue. Docker runs on Ubuntu LXC on Proxmox. Same Problem on a Hetzner Ubuntu VM.

docker-compose.yml

version: '3.8'

services:
  redis:
    image: redis:7-alpine

  app:
    image: cupcakearmy/cryptgeon:latest
    depends_on:
      - redis
    environment:
      SIZE_LIMIT: 4 MiB
    ports:
      - 85:5000

Here is my docker compose log

redis_1  | 1:C 27 Sep 2022 19:50:59.788 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 27 Sep 2022 19:50:59.788 # Redis version=7.0.5, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 27 Sep 2022 19:50:59.788 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 27 Sep 2022 19:50:59.788 * monotonic clock: POSIX clock_gettime
redis_1  | 1:M 27 Sep 2022 19:50:59.790 * Running mode=standalone, port=6379.
redis_1  | 1:M 27 Sep 2022 19:50:59.790 # Server initialized
redis_1  | 1:M 27 Sep 2022 19:50:59.790 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1  | 1:M 27 Sep 2022 19:50:59.790 * Ready to accept connections

Originally posted by @geoigeek in #51 (comment)

Redis support

Is it possible to add Redis support so that secrets are not lost when the server crashes or restarts or redeploys?

Documentation for 2.0

  • Deployment examples
  • "Migration" guide
  • Link to old docs.
  • Tag the latest 1.0 release

note sharing just does not work

You should be able to reproduce the error while trying to share a note. The link generates successfully but the note is not available under the link.

Can the service work with the POST method?

I'm trying to come up with a CURL request like this:

#!/bin/bash
data=LOGIN
password=123PASSWD
note_link=$(curl -s 'https://cryptgeon.nicco.io'
-H 'X-Requested-With: XMLHttpRequest'
--data-urlencode "data=$data"
--data "has_manual_pass=false&duration_hours=0&dont_ask=false&data_type=T&notify_email=&notify_ref="
| jq -r --arg arg $password '.note_link + "#" + $arg')
echo "note URL is $note_link"

but it doesn't work

Bigger files cannot be uploaded.

Hello,

i'm running the latest cryptgeon version on docker.
My docker-compose file:

`version: '3.7'

services:
memcached:
container_name: memcached_cryptgeon
image: memcached:1-alpine
restart: unless-stopped
entrypoint: memcached -m 512M -I 20M
ports:
- 11211:11211

app:
image: cupcakearmy/cryptgeon:latest
depends_on:
- memcached
environment:
SIZE_LIMIT: 10MiB
ports:
- 80:5000
`
When i try to upload files below 10 MByte i get an error that the file couldn't bei uploaded.
File is only 8.9 MByte.

image
image

CLI client

Some have asked about the possibility of using cryptgeon from the cli.
(#54 and https://discord.com/channels/252403122348097536/912714340157755482/1016073982757322863)

However while the app already uses Rest and using the endpoints is not an issue, encryption is handled by design in the front end, therefore the server is agnostic about the contents of the data, wether it's encrypted or not.

Goals:

  • have a CLI client that is compatible with macOS, Linux and maybe windows?
  • should be able to encrypt and decrypt from links
  • maybe start with text and then enable also file upload and download

Anyone interested: leave feedback and comments below so we can do something together here :)

Nginx working example

Hi!

Pretty impressive job :) I've been looking for something like this for a while!

Do you have any working example using Nginx? (:

Thanks!

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.