GithubHelp home page GithubHelp logo

ianmitchell / sentrydiscord.dev Goto Github PK

View Code? Open in Web Editor NEW
200.0 4.0 23.0 622 KB

Forward Sentry notifications to your Discord server

Home Page: https://sentrydiscord.dev

License: MIT License

JavaScript 21.33% TypeScript 78.67%
discord sentry error-notification webhooks

sentrydiscord.dev's Introduction

Sentry → Discord

Event Count Webhook Count


Note: There was an incident on February 28 which unfortunately resulted in the loss of the production database. The previous data is not recoverable. I sincerely apologize. You will need to revisit the website and setup your webhooks again.


Sentry → Discord is a service for forwarding Sentry event notifications to Discord. It acts as a middleman and transforms the webhook payload into a Discord-compatible format.

You can run your own version of Sentry → Discord or use the free, hosted version at https://sentrydiscord.dev.

Local Development

To get started in a local environment, you'll need a PostgreSQL instance running locally. Clone the repository and run

npm install
npx prisma migrate dev --preview-feature
npx prisma generate

Next, create a .env file with

DATABASE_URL=postgresql://...

Replacing the postgresql string with the URL to your local database. Finally, run

npm run dev

You should be able to view the website at http://localhost:3000.

Capturing Webhook Events

If you want to see what the Webhook payload looks like from Sentry, clone and run this website locally, and use a service like ngrok to get a public URL you can use to point Sentry to it. In development mode the console will print out the full Sentry payload.

sentrydiscord.dev's People

Contributors

advaith1 avatar attituding avatar ianmitchell avatar melefabrizio avatar prryplatypus avatar tandpfun avatar wdhdev 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

sentrydiscord.dev's Issues

February 28th Database Incident

Stopped receiving Discord alerts since February 29, and can't seem to add any new webhooks on the website. Always getting Sorry, something went wrong. Please try again later.

Add Project Name to Discord message

In my company we have a single #sentry channel on Discord, on which converge issues for 20+ different Sentry Project. The only way we have to distinguish between projects is to look at the error url, which is small and down in the discord card. It would be very helpful to integrate the project name as a tag inside the error title, eg. "[PROJECT] TypeError: cannot read..."

Copy button doesn't work on custom domains

I changed the default URL to my URL and the copy button (the one next to your new sentry->discord webhook) no longer works.

diff --git a/pages/create.tsx b/pages/create.tsx
index 1fb9cc4..6f97975 100644
--- a/pages/create.tsx
+++ b/pages/create.tsx
@@ -30,7 +30,7 @@ export default function Create() {
     setValue(event.currentTarget.value);
   };

-  const getWebhookURL = () => `https://sentrydiscord.dev/api/webhooks/${key}`;
+  const getWebhookURL = () => `http://<my domain>/api/webhooks/${key}`;

   const onClick = async (event) => {
     event.preventDefault();

Wiki

Create wiki with step by step for beginners to be able to configure setnry bot

Question: Why we cannot disable analytics and why do you store anything in the DB?

Hi,

I wanted to make a PR that would include the docker image file and docker-compose for a faster startup, but I got discouraged by the fact that you are using analytics which i cannot disable.

Why is that? why cannot we opt-in to use it, one ENV var would be enough to accomplish this with correct code.

Why do you store anything, why not just pass-through?

Allow Setting Content Field For Webhook

It would be amazing if we could set the content field of a webhook so we could do things such as pinging a certain role that a new issue has been created or something of that sort. I use this integration every single day and I think a feature like this would be really neat.

Changes on discord's domain

Hi !
I'm trying to create a link and actually the discord changed the domain on hook urls, now they are using "discordapp.com".
On the site, when i put this new link, returns to me a error "Please use a Discord webhook URL!".

By the way, thank you so much for this project, so far i have only been able to send alerts to my discord thanks to you!

"Unable to generate code snippet" error

I created a Custom Integration in Sentry and configured it as shown in the image below.
However, an error message "Unable to generate code snippet." is sent to discord.

image
image
image

Sentry alerts not working

I added the webhook in the Sentry settings, but the messages are only triggered when I click "test plugin". When I simulate an error in my application, the problem appears in sentry, but it does not appear in my discord channel.

image

image

image

Please, can you help me?

C++ stack in the message embed being useless / contains no info

Hello, first of all -- thanks for this integration, it's pretty nice.

While using it with C++ I noticed though that the "Stack" section of the embed is pretty useless currently, I would appreciate considering looking into whether it could be improved:
obraz

In comparison with Sentry's UI:
obraz

All of the things seen in the above UI would are pretty important and would be good to be included:

  • library module name
  • relative offset value (to look up in debugger or disassembler)
  • function name, if available
  • file+line, if available

Project fails to build

npm run build

> [email protected] build
> npx prisma generate && next build

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma

✔ Generated Prisma Client (4.8.0 | library) to ./node_modules/@prisma/client in 41ms
You can now start using Prisma Client in your code. Reference: https://pris.ly/d/client

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

(node:47140) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
info  - Loaded env from /Users/voxel/Git/Wildberries/Temp/sentrydiscord.dev/.env
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry

info  - Linting and checking validity of types .Failed to compile.

./lib/message.ts:21:7
Type error: Argument of type '{ name: string; iconURL: string; }' is not assignable to parameter of type 'EmbedFooterOptions'.
  Object literal may only specify known properties, and 'name' does not exist in type 'EmbedFooterOptions'.

  19 |     })
  20 |     .setFooter({
> 21 |       name: "Please consider sponsoring us!",
     |       ^
  22 |       iconURL: "https://sentrydiscord.dev/sponsor.png",
  23 |     })
  24 |     .setTimestamp(parser.getTime(event))

Support for new format of discord webhooks

Goal

Support all available discord webhook formats

Context

It seems like your code does not account for webhooks created via the discord app
When I create a webhook, its URL does not match the rules defined in the API:

// Ensure it's a Discord Webhook
if (!url?.startsWith('https://discord.com/api/webhooks/') &&
!url?.startsWith('https://ptb.discord.com/api/webhooks/') &&
!url?.startsWith('https://canary.discord.com/api/webhooks/') ) {

The webhook created via the discordApp:
https://discordapp.com/api/webhooks/1234/A1B2C3
I was able to modify the above URL to https://discord.com/api/webhooks/1234/A1B2C3 which your form has accepted, and I've been able to retrieve events from Sentry

Extra info

Discord app information:

  • Release Channel: stable,
  • Build Number: 101451

Not working

I followed the steps and clicking the "test plugin" button in sentry WebHooks settings does send a message in the channel, but actual issues that occur in the projects don't get send to the channel through discord webhook, so I'm a bit confused.

Project name in Notification

Hey

If you have multiple projects in Sentry, will be very useful if possible to get info about which project gets the error inside the discord notification. Any ideas? Thanks

Not sending any alert on event

When there is an error, webhook does not send anything. Let me mention that the "Test plugin" is working and sending a test message. How I can fix it?

Fields are undefined

How can I fix this?

What happens:
2cbc567

Payload:

{
  "id": "2450576855",
  "project": "bot",
  "project_name": "bot",
  "project_slug": "bot",
  "logger": null,
  "level": "error",
  "culprit": "PingCommand.exec(bot.commands.utility:Ping)",
  "message": "",
  "url": "https://sentry.io/organizations/alph4/issues/2450576855/?referrer=webhooks_plugin",
  "triggering_rules": [
    "Send all notifications"
  ],
  "event": {
    "event_id": "39e983d6a39b451da0f2c1c7cef8c5a6",
    "level": "error",
    "version": "7",
    "type": "error",
    "fingerprint": [
      "{{ default }}"
    ],
    "culprit": "PingCommand.exec(bot.commands.utility:Ping)",
    "logger": "",
    "platform": "node",
    "timestamp": 1623427750.245,
    "received": 1623427750.355762,
    "environment": "development",
    "contexts": {
      "command_started": {
        "extra": {
          "command": "[Object]",
          "guild": "[Object]",
          "message": "[Object]"
        },
        "type": "command_started",
        "user": {
          "id": "550337381128208396",
          "username": "Xenfo#0001"
        }
      }
    },
    "breadcrumbs": {
      "values": [
        {
          "timestamp": 1623426742.164,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/gateway/bot"
          }
        },
        {
          "timestamp": 1623426742.638,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/794696873750953984/invites"
          }
        },
        {
          "timestamp": 1623426742.641,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/601609698843820033/invites"
          }
        },
        {
          "timestamp": 1623426742.662,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/845010274665889812/invites"
          }
        },
        {
          "timestamp": 1623426742.671,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/701546532054237306/invites"
          }
        },
        {
          "timestamp": 1623426742.672,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/685219613146873876/invites"
          }
        },
        {
          "timestamp": 1623426742.68,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/712571134872387594/invites"
          }
        },
        {
          "timestamp": 1623426742.692,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "GET",
            "status_code": 200,
            "url": "https://discord.com/api/v7/guilds/749626435186196492/invites"
          }
        },
        {
          "timestamp": 1623426742.852,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "POST",
            "status_code": 200,
            "url": "https://cocdiscordlink.azurewebsites.net/api/login"
          }
        },
        {
          "timestamp": 1623426751.409,
          "type": "default",
          "category": "Utility",
          "level": "info",
          "message": "command_started",
          "data": {
            "args": {},
            "command": {
              "aliases": [
                "ping"
              ],
              "category": "Utility",
              "id": "ping"
            },
            "guild": {
              "channel_id": "724146808598560789",
              "id": "685219613146873876",
              "name": "ALPH4 Engines"
            },
            "message": {
              "content": "-ping",
              "id": "852938357947236352"
            },
            "user": {
              "id": "550337381128208396",
              "username": "Xenfo#0001"
            }
          }
        },
        {
          "timestamp": 1623426751.412,
          "type": "default",
          "category": "console",
          "level": "info",
          "message": "Error: Why are you not working?\n    at PingCommand.exec (/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js:18:15)\n    at CommandHandler.runCommand (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:768:39)\n    at CommandHandler.handleDirectCommand (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:439:31)\n    at processTicksAndRejections (internal/process/task_queues.js:95:5)\n    at async CommandHandler.handle (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:379:23)"
        },
        {
          "timestamp": 1623426751.579,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "POST",
            "status_code": 200,
            "url": "https://discord.com/api/v7/channels/724146808598560789/messages"
          }
        },
        {
          "timestamp": 1623426751.679,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "POST",
            "status_code": 200,
            "url": "https://discord.com/api/v7/channels/759062542621605940/messages"
          }
        },
        {
          "timestamp": 1623426751.68,
          "type": "default",
          "category": "Utility",
          "level": "error",
          "message": "command_errored",
          "data": {
            "command": {
              "aliases": [
                "ping"
              ],
              "category": "Utility",
              "id": "ping"
            },
            "guild": {
              "channel_id": "724146808598560789",
              "id": "685219613146873876",
              "name": "ALPH4 Engines"
            },
            "message": {
              "content": "-ping",
              "id": "852938357947236352"
            },
            "user": {
              "id": "550337381128208396",
              "username": "Xenfo#0001"
            }
          }
        },
        {
          "timestamp": 1623427749.922,
          "type": "default",
          "category": "Utility",
          "level": "info",
          "message": "command_started",
          "data": {
            "args": {},
            "command": {
              "aliases": [
                "ping"
              ],
              "category": "Utility",
              "id": "ping"
            },
            "guild": {
              "channel_id": "724146808598560789",
              "id": "685219613146873876",
              "name": "ALPH4 Engines"
            },
            "message": {
              "content": "-ping",
              "id": "852942546023743508"
            },
            "user": {
              "id": "550337381128208396",
              "username": "Xenfo#0001"
            }
          }
        },
        {
          "timestamp": 1623427749.922,
          "type": "default",
          "category": "console",
          "level": "info",
          "message": "Error: Why are you not working?\n    at PingCommand.exec (/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js:18:15)\n    at CommandHandler.runCommand (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:768:39)\n    at CommandHandler.handleDirectCommand (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:439:31)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (internal/process/task_queues.js:95:5)\n    at async CommandHandler.handle (/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js:379:23)"
        },
        {
          "timestamp": 1623427750.125,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "POST",
            "status_code": 200,
            "url": "https://discord.com/api/v7/channels/724146808598560789/messages"
          }
        },
        {
          "timestamp": 1623427750.242,
          "type": "http",
          "category": "http",
          "level": "info",
          "data": {
            "method": "POST",
            "status_code": 200,
            "url": "https://discord.com/api/v7/channels/759062542621605940/messages"
          }
        },
        {
          "timestamp": 1623427750.244,
          "type": "default",
          "category": "Utility",
          "level": "error",
          "message": "command_errored",
          "data": {
            "command": {
              "aliases": [
                "ping"
              ],
              "category": "Utility",
              "id": "ping"
            },
            "guild": {
              "channel_id": "724146808598560789",
              "id": "685219613146873876",
              "name": "ALPH4 Engines"
            },
            "message": {
              "content": "-ping",
              "id": "852942546023743508"
            },
            "user": {
              "id": "550337381128208396",
              "username": "Xenfo#0001"
            }
          }
        }
      ]
    },
    "exception": {
      "values": [
        {
          "type": "Error",
          "value": "Why are you not working?",
          "stacktrace": {
            "frames": [
              {
                "function": "async CommandHandler.handle",
                "module": "discord-akairo.src.struct.commands:CommandHandler",
                "filename": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "abs_path": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "lineno": 379,
                "colno": 23,
                "pre_context": [
                  "                message.util.parsed = parsed;",
                  "            }",
                  "",
                  "            let ran;",
                  "            if (!parsed.command) {",
                  "                ran = await this.handleRegexAndConditionalCommands(message);",
                  "            } else {"
                ],
                "context_line": "                ran = await this.handleDirectCommand(message, parsed.content, parsed.command);",
                "post_context": [
                  "            }",
                  "",
                  "            if (ran === false) {",
                  "                this.emit(CommandHandlerEvents.MESSAGE_INVALID, message);",
                  "                return false;",
                  "            }",
                  ""
                ],
                "in_app": false
              },
              {
                "function": "processTicksAndRejections",
                "module": "task_queues",
                "filename": "internal/process/task_queues.js",
                "abs_path": "internal/process/task_queues.js",
                "lineno": 95,
                "colno": 5,
                "in_app": false
              },
              {
                "function": "runMicrotasks",
                "in_app": true
              },
              {
                "function": "CommandHandler.handleDirectCommand",
                "module": "discord-akairo.src.struct.commands:CommandHandler",
                "filename": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "abs_path": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "lineno": 439,
                "colno": 31,
                "pre_context": [
                  "                        return true;",
                  "                    }",
                  "",
                  "                    command.locker.add(key);",
                  "                }",
                  "            }",
                  ""
                ],
                "context_line": "            return await this.runCommand(message, command, args);",
                "post_context": [
                  "        } catch (err) {",
                  "            this.emitError(err, message, command);",
                  "            return null;",
                  "        } finally {",
                  "            if (key) command.locker.delete(key);",
                  "        }",
                  "    }"
                ],
                "in_app": false
              },
              {
                "function": "CommandHandler.runCommand",
                "module": "discord-akairo.src.struct.commands:CommandHandler",
                "filename": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "abs_path": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/node_modules/discord-akairo/src/struct/commands/CommandHandler.js",
                "lineno": 768,
                "colno": 39,
                "pre_context": [
                  "    async runCommand(message, command, args) {",
                  "        if (command.typing) {",
                  "            message.channel.startTyping();",
                  "        }",
                  "",
                  "        try {",
                  "            this.emit(CommandHandlerEvents.COMMAND_STARTED, message, command, args);"
                ],
                "context_line": "            const ret = await command.exec(message, args);",
                "post_context": [
                  "            this.emit(CommandHandlerEvents.COMMAND_FINISHED, message, command, args, ret);",
                  "        } finally {",
                  "            if (command.typing) {",
                  "                message.channel.stopTyping();",
                  "            }",
                  "        }",
                  "    }"
                ],
                "in_app": false
              },
              {
                "function": "PingCommand.exec",
                "module": "bot.commands.utility:Ping",
                "filename": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js",
                "abs_path": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js",
                "lineno": 18,
                "colno": 15,
                "pre_context": [
                  "                content: 'Provides the ping for ALPH4',",
                  "                usage: null,",
                  "                examples: null",
                  "            }",
                  "        });",
                  "    }",
                  "    async exec(message) {"
                ],
                "context_line": "        throw new Error('Why are you not working?');",
                "post_context": [
                  "        const msg = await message.util.send('Ping?');",
                  "        return message.util.edit([",
                  "            `${EmojiUtils_1.DISCORD_EMOJIS.BELL} Ping:`,",
                  "            '',",
                  "            `• API Ping - \\`${message.client.ws.ping}ms\\``,",
                  "            `• Gateway Ping - \\`${msg.createdTimestamp - message.createdTimestamp}ms\\``",
                  "        ]);"
                ],
                "in_app": true
              }
            ]
          },
          "mechanism": {
            "type": "generic",
            "handled": true
          }
        }
      ]
    },
    "tags": [
      [
        "environment",
        "development"
      ],
      [
        "handled",
        "yes"
      ],
      [
        "level",
        "error"
      ],
      [
        "mechanism",
        "generic"
      ]
    ],
    "sdk": {
      "name": "sentry.javascript.node",
      "version": "6.6.0",
      "integrations": [
        "InboundFilters",
        "FunctionToString",
        "Console",
        "Http",
        "OnUncaughtException",
        "OnUnhandledRejection",
        "LinkedErrors",
        "Mongo"
      ],
      "packages": [
        {
          "name": "npm:@sentry/node",
          "version": "6.6.0"
        }
      ]
    },
    "key_id": "1665297",
    "project": 5812192,
    "grouping_config": {
      "enhancements": "eJybzDRxY3J-bm5-npWRgaGlroGxrpHxBABcYgcZ",
      "id": "newstyle:2019-10-29"
    },
    "_metrics": {
      "bytes.ingested.event": 9499,
      "bytes.stored.event": 12736
    },
    "_ref": 5812192,
    "_ref_version": 2,
    "hashes": [
      "8ceaf41553f44dca358ac0995e9e2ff7",
      "97cd371209b2d32e675e79b133275e6a"
    ],
    "location": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js",
    "metadata": {
      "filename": "/home/xenfo/Desktop/Projects/alph4/alph4-bot/dist/src/bot/commands/utility/Ping.js",
      "function": "PingCommand.exec",
      "type": "Error",
      "value": "Why are you not working?"
    },
    "title": "Error: Why are you not working?",
    "id": "39e983d6a39b451da0f2c1c7cef8c5a6"
  }
}

The issue URL is not added to the message when Sentry is self-hosted

I've noticed that, in my discord server, the message does not embeds the URL of the issue.

I initially thought it was a missing feature; However, inspecting the sources, I've noticed this lines in message.js:

  const link = parser.getLink(event);
  if (
    link.startsWith('https://sentry.io') ||
    link.startsWith('http://sentry.io')
  ) {
    embed.setURL(parser.getLink(event));
  }

Check here: https://github.com/IanMitchell/sentrydiscord.dev/blob/main/lib/message.js#L32

Why is this clause there?

Is there some security reason?

If it's ok to remove this if statement, I can make a PR.

Closing an issue in Sentry generates Discord message

Screenshot 2022-02-17 at 10 49 50

I am using the hosted version (thanks for running that) and I noticed this change in the last couple of weeks
I am unsure if I misconfigured something or sentry started calling the webhooks in new situations
is this a known situation?

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.