Code Monkey home page Code Monkey logo

utron's Introduction

utron logo

utron

GoDoc Coverage Status Build Status Join the chat at https://gitter.im/gernest/utron Go Report Card

utron is a lightweight MVC framework in Go (Golang) for building fast, scalable and robust database-driven web applications.

Features

  • Postgres, MySQL, SQLite and Foundation database support
  • Modular (you can choose which components to use)
  • Middleware support. All alice compatible Middleware works out of the box
  • Gopher spirit (write golang, use all the golang libraries you like)
  • Lightweight. Only MVC
  • Multiple configuration files support (currently json, yaml, toml and hcl)

Overview

utron is a lightweight MVC framework. It is based on the principles of simplicity, relevance and elegance.

  • Simplicity. The design is simple, easy to understand, and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day.

  • Relevance. utron doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet.

  • Elegance. utron uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested.

Motivation

After two years of playing with golang, I have looked on some of my projects and asked myself: "How golang is that?"

So, utron is my reimagining of lightweight MVC, that maintains the golang spirit, and works seamlessly with the current libraries.

Installation

utron works with Go 1.4+

 go get github.com/gernest/utron

For the Old API use

go get gopkg.in/gernest/utron.v1

Tutorials

Sample application

Contributing

Start with clicking the star button to make the author and his neighbors happy. Then fork the repository and submit a pull request for whatever change you want to be added to this project.

If you have any questions, just open an issue.

Author

Geofrey Ernest

Twitter : @gernesti

Acknowledgements

These amazing projects have made utron possible:

Licence

This project is released under the MIT licence. See LICENCE for more details.

utron's People

Contributors

ajmeese7 avatar co11ter avatar dushmis avatar gernest avatar gitter-badger avatar haraldnordgren avatar jannickfahlbusch avatar jufracaqui avatar kaleworsley avatar kirilldanshin avatar mattn avatar nicola-spb avatar obra avatar paramah avatar patdhlk avatar radarhere avatar shawnps avatar slacki avatar teancom avatar tomocy avatar txgo avatar unreal 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

utron's Issues

Mapping in controllers

All public methods in controllers are mapped to url path by default.

Maybe will be better if only methods with suffix or prefix "Action" will mapped by default. Some people can`t knew that their methods open for public.

Example:

// this will be parsed to /todo/home by default. Method for routing
func (t *Todo) ActionHome() {
	todos := []models.Todo{}
	....
	t.HTML(http.StatusOK)
}

// this won`t be parsed by default. Simple public method
func (t *Todo) Home2() {
	todos := []models.Todo{}
	....
	t.HTML(http.StatusOK)
}

if user want to set path manual then he can set

func NewTodo() controller.Controller {
	return &Todo{
		Routes: []string{
			"get;/;Home",			
		},
	}
}

Or maybe add some flexible settings for do it.

default parsing here https://github.com/gernest/utron/blob/master/router/routes.go#L230

Middlewares not chained properly when using func(*Context)error

Lets start with working example

There are three middleware functions of type func(http.Handler)http.Handler defined as follows:

func middleware_classic_1(h http.Handler) http.Handler {
    fmt.Println("md_classic_1")
    return h
}
func middleware_classic_2(h http.Handler) http.Handler {
    fmt.Println("md_classic_2")
    return h
}
func middleware_classic_3(h http.Handler) http.Handler {
    fmt.Println("md_classic_3")
    return h
}

The middlewares are then passed to utron.RegisterController

func init() {
    utron.RegisterController(&Index{
        Routes: []string{
            "get;/;Home",
            "post;/login;Login",
        }}, middleware_classic_1, middleware_classic_2, middleware_classic_3)
}

The output of this piece of code is correct, that is
image

Now exactly the same setup, but with middlewares of type func(*Context)error

func middleware1(c *utron.Context) error {
    fmt.Println("md1")
    return nil
}
func middleware2(c *utron.Context) error {
    fmt.Println("md2")
    return nil
}
func middleware3(c *utron.Context) error {
    fmt.Println("md3")
    return nil
}

And they are registered like this

func init() {
    utron.RegisterController(&Index{
        Routes: []string{
            "get;/;Home",
            "post;/login;Login",
        }}, middleware1, middleware2, middleware3)
}

But this time output looks like this:
image

In conclusion (TL;DR)

When there are three middlewares of type func(*Context)error registered with Controller, they are not chained up correctly. Instead the last one is executed three times.

Didn't try to combine those two types of middlewares together.

$ go version
>>> go version go1.5.2 windows/amd64
$ ver
>>> Microsoft Windows [Version 10.0.10586]

Panic when running todo (or other) application

Followed the README and installed the utron. Then fired up todo app and got this error:

C:\GoProjects\src\github.com\gernest\utron\fixtures\todo>go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x70 pc=0x465e91]

goroutine 1 [running]:
github.com/gernest/utron.Run()
        C:/GoProjects/src/github.com/gernest/utron/utron.go:239 +0x31
main.main()
        C:/GoProjects/src/github.com/gernest/utron/fixtures/todo/main.go:10 +0x1b

goroutine 7 [chan receive]:
database/sql.(*DB).connectionOpener(0xc08212ed20)
        c:/go/src/database/sql/sql.go:634 +0x4c
created by database/sql.Open
        c:/go/src/database/sql/sql.go:481 +0x33d
exit status 2

This is the todo app config

{
    "app_name": "utron web app",
    "base_url": "http://localhost:8090",
    "port": 8090,
    "verbose": false,
    "static_dir": "static",
    "view_dir": "views",
    "database": "mysql",
    "database_conn": "mysql://root:@localhost/todo",
    "automigrate": true
}

I am using MySQL 5.6.24 and Go1.5.2 both running on Microsoft Windows [Version 10.0.10586] 64-bit machine.

Highload bug

Hi!

I write the code:

type info struct {
    c http.ResponseWriter
}

type Test struct {
    *utron.BaseController
}

func (t *Test) Index() {
    fmt.Println(info{t.Ctx.Response()})
    t.Ctx.Redirect("http://123123123.12", http.StatusFound)
}

func NewTest() *Test {
    return &Test{}
}

send many concurent requests to /test:

siege -f urls.txt -c 10 -t30s -i

and have error:

{0xc420691ee0}
{0xc4207ca000}
{0xc4207ca0d0}
{0xc4207ca1a0}
{0xc4207ca270}
{0xc4207ca340}
{0xc4206a4d00}
{0xc4206a4d00}
fatal error: concurrent map writes

goroutine 794 [running]:
runtime.throw(0x9ef0e2, 0x15)
    /usr/lib/go/src/runtime/panic.go:566 +0x95 fp=0xc420505220 sp=0xc420505200
runtime.mapassign1(0x98f7a0, 0xc4207b8c00, 0xc420505330, 0xc420505340)
    /usr/lib/go/src/runtime/hashmap.go:458 +0x8ef fp=0xc420505308 sp=0xc420505220
net/textproto.MIMEHeader.Set(0xc4207b8c00, 0x9e551b, 0x8, 0x9edaf9, 0x13)
    /usr/lib/go/src/net/textproto/header.go:22 +0xca fp=0xc420505368 sp=0xc420505308
net/http.Header.Set(0xc4207b8c00, 0x9e551b, 0x8, 0x9edaf9, 0x13)
    /usr/lib/go/src/net/http/header.go:31 +0x53 fp=0xc4205053a0 sp=0xc420505368
net/http.Redirect(0xe63320, 0xc4206a4d00, 0xc4207b3680, 0x9edaf9, 0x13, 0x12e)
    /usr/lib/go/src/net/http/server.go:1819 +0xd7 fp=0xc420505488 sp=0xc4205053a0
github.com/gernest/utron.(*Context).Redirect(0xc420174e70, 0x9edaf9, 0x13, 0x12e)
    /home/coder/go/src/github.com/gernest/utron/context.go:189 +0x5f fp=0xc4205054c8 sp=0xc420505488

...

Two parallel routines get the same context. Maybe action signature should be

func (c *SomeController) Action(ctx *utron.Context) {}

instead to save the context into the controller??

Make some variables, objects and data global and rethink models.

I am missing access to some data and objects when writing an application with utron.

I would like to provide these three examples, so you can understand what I mean. I will try to show how inaccessible database and configuration, in places other than controller action, affect the code transparency and make Model less important than it should be.

Example 1

Let's say there is some go routine running in background taking care of something. The go routine uses database. To access DB somewhere else than in controller action I had to do this dirty hack (the function is a middleware running on each request, which is not efficient at all)

var DB *utron.Model

func dbGlobal(c *utron.Context) error {
    c.DB.LogMode(true)
    if DB == nil {
        DB = c.DB
    }

    return nil
}

Then finally I can access DB in go routine like this

func thisIsGoRoutine() {
    // wait for first request so middleware is executed and db is accessible
    for DB == nil {
        time.Sleep(100 * time.Millisecond)
    }

    // do some stuff
}

Example 2

There are some components I have to initialize and pass some parameters to them. They are scattered all around the project. I can't store these parameters in config file, because I can't access it (again) anywhere else than in controller action (via context).

var SessionStorage, _ = mysqlstore.NewMySQLStore(
    "root:@tcp(127.0.0.1:3306)/argaroth_automigrate?charset=utf8&parseTime=True&loc=Local",
    "sessions",                  // db table name
    "/",                         // cookie path
    60*60*24*30,                 // expire time
    []byte(SESSION_STORAGE_KEY), // secret key for cookie
)

Example 3

I want to write some so called business logic in models in order to keep controllers tidy and transparent. Then again I can't do that without having global DB access done like in example 1.

In conclusion

At the moment Model part of MVC is reduced to struct definition. In my opinion it shouldn't be that way.

Discussion

I would like to hear what do you think about what i've said. Maybe I am missing something here, then I am open to learn something new.

html/template: "index" is undefined Error

I clone the todo webapp sample code and replace postgres to mysql , i made the same directory structure and filename, when i run the web app, the database output the correct result, but it reports that it could not find the index.html template , app.yml is also correct , when i change view_dir to other name(not 'views') , the app will stop running, so i do not know where i got wrong?

any help will be appreciated.

project structure

│  .gitignore
│  doc.go
│  info.exe
│  main.go
│
├─config
│      app.yml
│
├─controllers
│      todo.go
│
├─models
│      todo.go
│
├─static
│      todo.css
│
└─views
        index.html
app_name: utron web app
base_url: http://localhost:5000
port: 5000
verbose: true
static_dir: static
view_dir: views
database: "mysql"
database_conn: "svc:svc@/services?charset=utf8"
func (t *Todo) Home() {
    todos := []*models.Todo{}
    t.Ctx.DB.Order("created_at desc").Find(&todos)
    fmt.Println("%+v", todos[0])
    t.Ctx.Data["List"] = todos
    t.Ctx.Template = "index"
    t.HTML(http.StatusOK)
}
2016/01/06 10:21:38 >>INFO>> starting server at http://localhost:5000
%+v &{1 23423423 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}
2016/01/06 10:21:45 >>ERR>> html/template: "index" is undefined

Disabling Automigration

Is there a way to disable the automigration of the tables trough some method that utron provides, or I have to do it by changing the source?

cannot find package "github.com/gernest/utron/app"

I use win 10 x64, and get error

cannot find package "github.com/gernest/utron/app" in any of:
C:\Go\src\github.com\gernest\utron\app (from $GOROOT)
C:\Users\HieuLuong\go\src\github.com\gernest\utron\app (from $GOPATH)

List for new features wished to be implemented

Hi @gernest, here is little list of things that I think that should be useful to utron and some suggestions of how to do some of them.

First, is the reiteration of something that @OsvaldoTCF required, that is the support for SQLite. I don't know how to implement this one, but the reason behind is something that he said to me, so in this one, I'm following what he said. Everyone knows that SQLite is a very lightweight database(if we can call it that), but lacks a lot of features that other options have, which is a quite troublesome thing, but it demands little to none maintenance, and can be used, for example, on mobile devices or be included in an embedded applications. This versatility is one of the things that attract our attention to it. We already know that Gorm support it, and should be nice to utron also support it.

Second is the support for HTTPS. I know that I'm repeating myself, but this is an important matter. For a beginning, I think that the easiest way is the one I showed in this issue: #39. It contains a new function that is a little modification of the Run function, and I added that function in the utron.go file. But it depends on the user providing the files for certification, what is a bad thing in my opinion. For me, the right way should be ask in the configuration file the location for the certification files, if no files are provided, the framework should create it for the programmer, like in this example. Of course, the programmer should provide the basic information for the certification in a file, if none is provided, the framework should give default information for the certificate. In the end, a new Run function function for https requests should be provided for our "main" files.

Third is CORS support. Theres a good library for it here on Github that handles it, but it also depends on the programmer of providing some sort of configuration, so should also be good to load the configuration from a file like the way I proposed for HTTPS.

Well, I think this resumes the main features that utron should have, hope that some of them can be implemented. Thank in advance for your attention.

Empty environment variables are ignored

In some environments I want to use the environment variables to override the default values that are set in a config file. For example, in a test environment I may want to use an empty db user (e.g. pass DB_USER="" to a particular command) .

Right now, config.go cannot distinguish between a zero-length environment variable and a environment variable that is not present.

Default addr for network 'localhost' unknown

Trying to connect to mysql with the following in app.json

        "database": "mysql",
        "database_conn": "mysql://utron:pass@localhost/utron_todo"

Loggin into the mysql terminal from promp with the credentials is fine and working in PHP also. Any ideas?

Content-Type is never set.

In https://github.com/gernest/utron/blob/master/controller.go in the functions HTML(), String(), and JSON() b.Ctx.Set(code) is called before b.Ctx.JSON(). Since Set() ends up calliing ResponseWriter.WriterHeader, the call to b.Ctx.JSON() will end up being ignored.

The documentation for ResponseWriter says

        // Header returns the header map that will be sent by
        // WriteHeader. Changing the header after a call to
        // WriteHeader (or Write) has no effect unless the modified
        // headers were declared as trailers by setting the
        // "Trailer" header before the call to WriteHeader (see example).
        // To suppress implicit response headers, set their value to nil.
        Header() Header

utron chat room

hi,
utron have a gitter or slack (gophers.slack.com) chat room?

tks
Joao

You're awesome

That's all!

I hope someone hires you and your friends!

There exists a bug in view/view_test.go

     for _, tpl := range tpls {
		verr := v.Render(out, tpl, data)
		if verr != nil {
                        // HERE
			t.Error(err)
		}
		if !strings.Contains(out.String(), data.Name) {
			t.Errorf("expeted %s to contain %s", out.String(), data.Name)
		}
	}

Default 404 and 500 page with utron

Hi, how can I write a default response from my server to these errors with utron? For example, if someone tries to access myserver.com/not_a_valide_resource, how can I handle it? Thanks in advance for the help

Routes into Routes file

@gernest First of all thanks for such a great tool, utron looks very nice, i really appreciate finding this kind of tool that makes things easier.

I've been talking with one of my teammates about the routes inside utron and wanted to know if it sounds reasonable for you to move the routes to a separate file and apply the routes by reading a routes configuration file.

One of the good thing is that in utron Controller the Routes attribute is a slice, which means we could read these from a JSON/YAML/TOML source file.

Thoughts on this ?

Environment configuration

@gernest What do you think about reading some config values from the ENV before reading from the config.{ json | yaml | toml } file?

I'm thinking that in some cases utron will need different values for the database connection and other configuration elements like the port depending on the environment we're running the app, for example our Production database url will be different than our development/testing URL.

Maybe utron could make the app read ENV variables and if these are not satisfied then read from the config file.

Other alternative we could do it provide environment specific configuration in the config.{json | yaml | toml} file, but in some cases reading from the ENV would be needed as well.

Again and as usual, once you agree with one of the alternatives i would be very happy to help.

Split databaseconnection string into multiple environment variables

To use this very nice framwork, I tried to setup docker-compose. RubyOnRails and co use a much easier way to connect to databases, namely environment variables shipped by postgresl:latest container.

I setup you example inside the docker environment:
https://github.com/PatWie/ultron-webapp-container

However, your library refuses the connection. A dump of available variables are:

DB_ENV_POSTGRES_USERNAME=databaseuser
DB_PORT_5432_TCP_ADDR=172.17.0.3
DB_PORT_5403_TCP=tcp://172.17.0.3:5403
DB_PORT=tcp://172.17.0.3:5403
DB_ENV_POSTGRES_PASSWORD=c9aca452d8b439b1e484855a0d4ed105
DB_ENV_LANG=en_US.utf8
DB_ENV_GOSU_VERSION=1.7
DB_PORT_5432_TCP=tcp://172.17.0.3:5432
DB_ENV_PG_MAJOR=9.5
DB_ENV_affinity:container==19e9f7ed42720d5a332c3402fb784276cb2c579e78fc304a28aef7dd1cb1fb72
DB_PORT_5403_TCP_PORT=5403
DB_ENV_POSTGRES_DBNAME=database
DB_PORT_5432_TCP_PROTO=tcp
DB_ENV_PG_VERSION=9.5.4-1.pgdg80+1
DB_PORT_5403_TCP_PROTO=tcp
DB_PORT_5403_TCP_ADDR=172.17.0.3

These should be automatically already there. So why not rely on these?

If your framework can be run inside these dockers, it would be an additional argument for using the framework.

The error-message comes from:

+ exec app
`` is not officially supported, running under compatibility mode.
2016/09/12 17:23:54 sql: unknown driver "" (forgotten import?)
hipanic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x70 pc=0x46a68a]

goroutine 1 [running]:
panic(0x8c7ec0, 0xc42000c0a0)
    /usr/local/go/src/runtime/panic.go:500 +0x1a1
github.com/gernest/utron.Run()
    /go/src/github.com/gernest/utron/utron.go:240 +0x3a
main.main()
    /go/src/app/main.go:12 +0xa4

which basically belongs to this line
https://github.com/gernest/utron/blob/master/utron.go#L240

HTTPS with Utron

I've seen that to make a HTTPS server with Go, I have to use the ListenAndServeTls instead of the ListenAndServe. But this is only if make the hard work that I don't want to. Utron already do this work for me, so I can worry with others things. But how can I configure Utron to work with HTTPS? Because a quick look doesn't show the use of it, and I am not comfortable to change your code. Thank you in advance for your answer

Use of sessions

There was I, just browsing some code at Github, when I decided to read Utron's wiki. Then I stumbled upon the middlewares' page, and a doubt was spawned in my head: how the heck I would use this?Do I just have to follow the Gorilla tutorial, or make use of some gimmick to achieve that?

Questions about controller lifecycle

I'm curious how the controller lifecycle works. Does a new instance of controller get created on every request? If not, how is the t.Ctx field made threadsafe between different concurrent requests?

Sub categories problems

Thanks for this framework.
I am new in Go, and I tries to make multi level blog categories, for example:
-dev
-- php
-- mysql
and i want to catch this url site.com/dev/php/somepost.html
but i cant setup routes to catch dev/php in category variable and somepost.html in id variable.

and file routes.json not loads, because rules in this file not works

How to fix it? I have no idea :(

Multiple Controllers

Hi, I'm a newbie in Golang, and recently discovered this amazing framework that is utron. From now on, I will use it, because it seems much more comfortable to work with than the others I've seen around. But I want to expose this doubt I have. Is a good practice to write one different controller for each service(url) my application offers?

utron not creates tables in db

I try to start example todo, and it says (line with table error shows only after i tries to open any page):

2016/05/15 18:40:59 >>INFO>> starting server at http://127.0.0.1:8090

(Error 1146: Table 'test_db.todos' doesn't exist) 
[2016-05-15 18:41:02]  

as i understand it not uses migrations... i dont know why.
my config:

{
    "app_name": "Test Site",
    "base_url": "http://127.0.0.1:8090",
    "port": 8090,
    "verbose": false,
    "static_dir": "static",
    "view_dir": "views",
    "database": "mysql",
    "database_conn": "test_user:test_password@tcp(127.0.0.1:3306)/test_db?charset=utf8"
}

what is wrong?

Sorry for bad English

Session store

I`m start learning golang. I want to change sessionStore to redis and I found this code. Is it right? May be should be "return ctx.SessionStore.Get" ?

//GetSession retrieves session with a given name.
func (ctx *Context) GetSession(name string) (*sessions.Session, error) {
	if ctx.SessionStore != nil {
		return ctx.SessionStore.New(ctx.Request(), name)
	}
	return nil, errNoStore
}

Secure config

In context.go you send config to view (by default). Users can save passwords and tokens in config file. I think it`s not secure. If user will want to have config in view then he put it himself.

if c.Cfg != nil {
	c.Data["Config"] = c.Cfg // add configuration to the view data context
}

What do you think?

Simple project fails when no model is defined

Hi!
Turns out that the presence of at least one model is mandatory.

I fund out that:

  1. Running an application without model structs is fine
  2. Running an application without a valid database connection url will result in a null-pointer dereferentiation and subsequent crash.

I think this should be avoided.

I think the Run function in github.com/gernest/utron/utron.go should check for the presence of a database configuration key in the configuration file and if not present skip the 'AutoMigrateAll` function call.

I might fork and patch it myself, but I assure nothing, and I'm opening this issue in the meantime.

Raw Body

Sorry for the noobness, but how I get the raw body data for a POST or PUT request? Thank you in advance for the answer

Rename tag 1.0 to v1.0 in order to use gopkg.in

As the title says, it would be nice to let users use stable release with go get and the easiest way is to use gopkg.in.

With the current tag name 1.0 the service is unable to access 1.0 release.

GitHub repository at https://github.com/gernest/utron has no branch or tag "v1", "v1.N" or "v1.N.M"

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.