Giter Site home page Giter Site logo

gruelbox / orko Goto Github PK

View Code? Open in Web Editor NEW
180.0 19.0 63.0 33.45 MB

Trade on and script multiple crypto exchanges from a single user interface on desktop and mobile. In development.

License: GNU Affero General Public License v3.0

Java 32.61% JavaScript 39.94% HTML 0.03% CSS 0.06% Shell 0.02% Batchfile 0.01% TypeScript 6.25% Less 21.07% Procfile 0.01%
bitcoin cryptocurrency binance bitfinex coinbase-pro kucoin kraken bitmex scripting

orko's Introduction

Orko Twitter

All Contributors

Collaborate on Gitter Current version

CircleCI Sonarcloud Security Rating Sonarcloud Vulnerabilities Sonarcloud Coverage CodeFactor

Fed up of logging into multiple separate cryptocurrency exchanges? Frustrated by missing features? Want to use advanced order types such as trailing stops on exchanges that don't support them?

Orko is a self hosted web application which provides a unified dashboard to control numerous cryptocurrency exchanges, allowing you to trade and manage your portfolio, even if it is spread across multiple exchanges, all from one screen. It works seamlessly on desktop and mobile, so you can have the same trading experience wherever you go.

All this without sharing your API keys with anyone.

Screenshot

Feel like creating your own special order types, such as soft stops, stops triggered off the price of a different asset, or a "Nuke" button which sells all your alt positions? Orko features a scripting API allowing you to design your own bespoke order types.

Scripting UI

Best of all, it's completely free (as in "free speech" as well as "free beer"). Read about some more things it can do.

Status

Beta. Please read the project status page. Particularly, please note that the application has only so far been tested on Chrome desktop and Chrome mobile.

Orko is a new application which has missing features and some well-known bugs. It needs your help. Read more about Orko, why it's free and how to help.

Installation

Windows | Ubuntu/Debian | Docker | Heroku quick | Heroku manual

Deploy to Heroku

Exchange Support

General

Orko does not support the following on any exchange: deposits, withdrawals, funding or account management. It is purely for trading. Margin trading including position management is on the roadmap but not supported yet.

Exchanges with "excellent" support use streaming updates, which means that generally most changes will appear in the UI almost immediately. Without streaming updates, changes can take a number of seconds to be reflected in the UI. Usually, streaming updates are possible for any exchange, but involve considerably more work to implement, so exchanges tend to be added first without streaming updates and get updated later.

By Exchange

Exchange Support level Missing trading features Notes
Binance ✔️ Excellent Dust conversion Almost perfect.
Bitfinex ✔️ Excellent True OCO trades, post only, reduce only, visibility of trades and positions on chart Short on features, but what is supported is supported perfectly.
Coinbase Pro ✔️ Excellent Post only, good-till-cancelled Very good, with one or two minor known issues.
Kucoin ✔️ Good Streaming updates Works well other than the lack of streaming updates.
Bittrex ✔️ Good Streaming updates, stop orders Works well other than the lack of streaming updates.
Bitmex ⚠️ In development Streaming updates, most complex order types, balances, historical trades Not recommended for serious use yet.
Kraken ⚠️ In development Streaming updates, stop orders Read-only.

Help wanted

At the moment this project is a labour of love for just me, I am creating new bug and enhancement issues faster than I am closing them, and I need help!

The back-end server is written in Java and is based on XChange and xstream-stream, to which the project is a significant contributor. Please consider helping these great projects - it has a knock-on effect on Orko.

The front-end UI (mobile and desktop) is written in Javascript and is based on React+Redux.

Everything else

See the wiki!

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Graham Crockford

💻 🖋 📖 🎨 🚇 🚧 🛡️ ⚠️ 📓

lazrfocus

🤔

lowwor

💻 📓

longtran84

🐛

Paul Matthews

💻 🐛 🤔

This project follows the all-contributors specification. Contributions of any kind welcome!

orko's People

Contributors

allcontributors[bot] avatar awoooooo avatar badgerwithagun avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

orko's Issues

Mobile UI is temporary and needs some proper love

The mobile UI at the moment is a bit of an afterthought. It should be "thumbable", easy to use on the move and provide comfortable access to everything (except maybe scripting and other similar features). At the moment it's a bit like BitMex (just stack the panels and make the user scroll around) but I think we can do better than that.

React Native is a possibility, but that's a big change.

Improve demo site

Plan is to make the app effectively multi-tenant by using an in-memory DB and localising persistence to each connection, while expanding the scope of paper trading to demonstrate the entire application and allow more thorough end-to-end testing.

  • Fix paper trading & open orders as they are (currently getting errors)
  • Change the NotAuthenticated component so that it can be closed with a "Use paper trading" button (state saved only to session). Apply it to the trade selector as well.
  • Provide paper balance & trade history.
  • Think a bit harder about the layout of the NotAuthenticated component. It looks a bit dodgy when repeated in three places.
  • Reserve balances when limit orders are active
  • Add unit testing for paper trade engine
  • Add full exchange simulation to XChange
  • Add exchange simulation to Orko
  • Test and prove exchange simulation in UI
    • BUG: Treat NonceException quietly in background process
    • BUG: Be more intelligent about firing of rate limit errors in XChange simulated implementation. It should actually only do it if you exceed a specified rate. Otherwise you'll keep getting them
    • BUG: Dummy orderbook looks unrealistic. Weight towards current price
    • BUG: Provide a starting balance of fiat for the user
    • BUG: Make the background market maker movements more randomised to create a visual effect of activity
    • BUG: Prevent negative prices!
    • BUG: More intelligent "market maker" behaviour in the background to ensure liquidity never runs out (stack orders around the spread and stack more under when price is low and more over when price is high, separate market maker bot from chaos market taker).
    • BUG: Fee handling isn't realistic - should reduce bought amount and reduce sale proceeds, not increase cost
    • FEATURE: Enforce respecting of minimum trade amounts and price scale
  • Add end-to-end tests for the various trade workflows now we can test the whole lot using paper trading
  • Need to use exchange metadata and pricing to calculate initial balances and raise realistic errors.
  • Generally harden paper trading (e.g. use DB persistence)
  • Send out to a few select people for feedback
  • Work out how to host on AWS directly - need more memory
  • Allow socket-scoped H2 in-memory databases so we can make data persistence only last as long as a connection and thus be per-user.

Switch to full commercial TradingView widget

Need #17 in place first
Then need to investigate kline feeds for all the exchanges
Would prioritise KuCoin or other exchanges where hosted TradingView doesn't support coins
Main reason would be to show orders and fills on the graph

Chrome warnings

fetchUtil.js:27 GET /api/exchanges 401 (Unauthorized)
nn @ fetchUtil.js:27
(anonymous) @ auth.js:14
w @ runtime.js:62
(anonymous) @ runtime.js:288
e.(anonymous function) @ runtime.js:114
r @ asyncToGenerator.js:3
s @ asyncToGenerator.js:25
(anonymous) @ asyncToGenerator.js:32
(anonymous) @ asyncToGenerator.js:21
(anonymous) @ auth.js:15
(anonymous) @ actions.js:36
w @ runtime.js:62
(anonymous) @ runtime.js:288
e.(anonymous function) @ runtime.js:114
r @ asyncToGenerator.js:3
s @ asyncToGenerator.js:25
(anonymous) @ asyncToGenerator.js:32
(anonymous) @ asyncToGenerator.js:21
(anonymous) @ actions.js:34
(anonymous) @ index.js:8
(anonymous) @ middleware.js:40
dispatch @ redux.js:613
(anonymous) @ actions.js:25
w @ runtime.js:62
(anonymous) @ runtime.js:288
e.(anonymous function) @ runtime.js:114
r @ asyncToGenerator.js:3
s @ asyncToGenerator.js:25
Promise.then (async)
r @ asyncToGenerator.js:13
s @ asyncToGenerator.js:25
(anonymous) @ asyncToGenerator.js:32
(anonymous) @ asyncToGenerator.js:21
(anonymous) @ actions.js:8
(anonymous) @ index.js:8
(anonymous) @ middleware.js:40
value @ AuthContainer.js:11
ja @ react-dom.production.min.js:5304
Pa @ react-dom.production.min.js:5059
Da @ react-dom.production.min.js:5026
Ma @ react-dom.production.min.js:4961
ea @ react-dom.production.min.js:4887
Fa @ react-dom.production.min.js:5491
Ha @ react-dom.production.min.js:5499
Ba.render @ react-dom.production.min.js:5689
(anonymous) @ react-dom.production.min.js:5774
Ia @ react-dom.production.min.js:5421
$a @ react-dom.production.min.js:5773
render @ react-dom.production.min.js:5802
494 @ index.js:7
f @ bootstrap:78
286 @ main.64691239.chunk.js:1
f @ bootstrap:78
t @ bootstrap:45
r @ bootstrap:32
(anonymous) @ main.64691239.chunk.js:1
?frameElementId=tradingview_8557e&symbol=BITTREX%3ADOGEBTC&interval=240&hidesidetoolbar=0&saveimage=1&toolbarbg=f1f3f6&studies=RSI%40tv-basicstudies&theme=Dark&style=1&timezone=UTC&showpopupbutton=1&studies_overrides={}&overrides={}&enabled_features=[]&disabled_features=[]&showpopupbutton=1&locale=en&utm_source=oco-testing.herokuapp.com&utm_medium=widget&utm_campaign=chart&utm_term=BITTREX%3ADOGEBTC:165 [Violation] Avoid using document.write().
(anonymous) @ ?frameElementId=tradingview_8557e&symbol=BITTREX%3ADOGEBTC&interval=240&hidesidetoolbar=0&saveimage=1&toolbarbg=f1f3f6&studies=RSI%40tv-basicstudies&theme=Dark&style=1&timezone=UTC&showpopupbutton=1&studies_overrides={}&overrides={}&enabled_features=[]&disabled_features=[]&showpopupbutton=1&locale=en&utm_source=oco-testing.herokuapp.com&utm_medium=widget&utm_campaign=chart&utm_term=BITTREX%3ADOGEBTC:165
(anonymous) @ ?frameElementId=tradingview_8557e&symbol=BITTREX%3ADOGEBTC&interval=240&hidesidetoolbar=0&saveimage=1&toolbarbg=f1f3f6&studies=RSI%40tv-basicstudies&theme=Dark&style=1&timezone=UTC&showpopupbutton=1&studies_overrides={}&overrides={}&enabled_features=[]&disabled_features=[]&showpopupbutton=1&locale=en&utm_source=oco-testing.herokuapp.com&utm_medium=widget&utm_campaign=chart&utm_term=BITTREX%3ADOGEBTC:172
DOGE:1 [DOM] Input elements should have autocomplete attributes (suggested: "current-password"): (More info: https://goo.gl/9p2vKq) <input placeholder=​"Enter password" type=​"password" value>​
35[Violation] Added non-passive event listener to a scroll-blocking <some> event. Consider marking event handler as 'passive' to make the page more responsive. See <URL>
embed_widget.d0a8194a37389d58a0ca.js:127 [Violation] Added non-passive event listener to a scroll-blocking 'wheel' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
setup @ embed_widget.d0a8194a37389d58a0ca.js:127
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
bind @ vendors_embed.7663894d330dac3c742e.js:110
mousewheel @ embed_widget.d0a8194a37389d58a0ca.js:127
n._setElement @ embed_widget.d0a8194a37389d58a0ca.js:595
_options.body.subscribe.callWithLast @ embed_widget.d0a8194a37389d58a0ca.js:593
t.subscribe @ embed_widget.d0a8194a37389d58a0ca.js:8
n @ embed_widget.d0a8194a37389d58a0ca.js:593
z @ embed_widget.d0a8194a37389d58a0ca.js:619
G @ embed_widget.d0a8194a37389d58a0ca.js:620
le @ embed_widget.d0a8194a37389d58a0ca.js:621
e.exports @ embed_widget.d0a8194a37389d58a0ca.js:623
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:642
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:645
c @ runtime.34e8418f20a130a7d096.js:1
d @ runtime.34e8418f20a130a7d096.js:1
a @ runtime.34e8418f20a130a7d096.js:1
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:1
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:443
n._makeTimeAxisWidget @ embed_widget.d0a8194a37389d58a0ca.js:609
n._makeDefaultGui @ embed_widget.d0a8194a37389d58a0ca.js:604
n._init @ embed_widget.d0a8194a37389d58a0ca.js:595
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:610
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:275
o @ embed_widget.d0a8194a37389d58a0ca.js:568
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:606
n._makeDefaultModel @ embed_widget.d0a8194a37389d58a0ca.js:607
n._init @ embed_widget.d0a8194a37389d58a0ca.js:596
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:610
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:275
o @ embed_widget.d0a8194a37389d58a0ca.js:568
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:606
n._makeDefaultModel @ embed_widget.d0a8194a37389d58a0ca.js:607
n._init @ embed_widget.d0a8194a37389d58a0ca.js:596
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:610
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
o @ embed_widget.d0a8194a37389d58a0ca.js:569
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:606
n._makeDefaultModel @ embed_widget.d0a8194a37389d58a0ca.js:607
n._init @ embed_widget.d0a8194a37389d58a0ca.js:596
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:610
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:595
t.fire @ embed_widget.d0a8194a37389d58a0ca.js:5
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:606
n._makeDefaultModel @ embed_widget.d0a8194a37389d58a0ca.js:607
n._init @ embed_widget.d0a8194a37389d58a0ca.js:596
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:610
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:4
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:569
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:275
o @ embed_widget.d0a8194a37389d58a0ca.js:568
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:275
o @ embed_widget.d0a8194a37389d58a0ca.js:568
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
o @ embed_widget.d0a8194a37389d58a0ca.js:569
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n @ embed_widget.d0a8194a37389d58a0ca.js:465
n._makePaneWidgetsAndSeparators @ embed_widget.d0a8194a37389d58a0ca.js:609
n._updateGui @ embed_widget.d0a8194a37389d58a0ca.js:607
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:4
(anonymous) @ embed_widget.d0a8194a37389d58a0ca.js:569
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
add @ vendors_embed.7663894d330dac3c742e.js:107
(anonymous) @ vendors_embed.7663894d330dac3c742e.js:110
each @ vendors_embed.7663894d330dac3c742e.js:100
each @ vendors_embed.7663894d330dac3c742e.js:99
on @ vendors_embed.7663894d330dac3c742e.js:110
e._init @ embed_widget.d0a8194a37389d58a0ca.js:274
e @ embed_widget.d0a8194a37389d58a0ca.js:272
n.updateLayout @ chart-widget-gui.6d8f5a3d650ae0c07abf.js:6
n._update @ embed_widget.d0a8194a37389d58a0ca.js:605
t @ embed_widget.d0a8194a37389d58a0ca.js:606
vendors_embed.7663894d330dac3c742e.js:107 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952

Re-introduce docker support

Back when the architecture was more microservicey, Docker was the only simple way to deploy the application. This was abandoned as being unnecessarily complex for the use case, but Docker support was removed at the same time (since there was no driver for docker support for the single-app build at the time).

Docker support should be re-introduced and published to Docker Hub with each release, suitably documented and configurable. A simple alpine+openjdk8 image should be quite sufficient.

It would be sensible, having done so, to funnel Heroku deployment via Docker, to ensure consistent architecture. This would also ensure that Docker and Heroku users will be cross-testing.

More info here:

https://devcenter.heroku.com/categories/deploying-with-docker

There is some crossover with #115 here. Do we build the docker image directly from source or from an installer? The latter would have the advantage, again, of making sure installer-based builds are being regularly tested without any additional effort.

Complex order builder

If... this... then... that... or... that... then.... the other

Requires some more job primitives and a nice, slick UI, but the majority of the back-end support is already there.

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.