Git Product home page Git Product logo

rack-server-pages's Introduction

Rack Server Pages

Rack middleware and application for serving dynamic pages in very simple way. There are no controllers or models, just only views like a jsp, asp and php!

http://github.com/migrs/rack-server-pages

Build Status Gem Version

Features

  • Serving dynamic pages (default: ERB)
  • Serving static files
  • No requirements (except Rack)
  • Tilt support (optional)
  • Include a partial template
  • Layout template
  • Before/After filters
  • Handle exceptions
  • Include helpers
  • Integrate with any rack applications (Rails, Sinatra, etc...)
  • Extremely simple and easy to use!

Requirements

Install

RubyGems available

gem install rack-server-pages

Basic usage

Run as Rack application

Create config.ru

require 'rack-server-pages'
run Rack::ServerPages

Create public/index.erb

<h1>Hello rack!</h1>
<p><%= Time.now %></p>

Finally running rackup

rackup

and visit http://localhost:9292/

Valid requests,

Use as Rack middleware

Edit config.ru

require 'rack-server-pages'
use Rack::ServerPages
run Rack::ServerPages::NotFound # or your MyApp

And same as above.

Template bindings

  • CoreHelper

    • layout(file)
    • partial(file)
    • redirect(target, status=302) (same as Sinatra)
    • halt(*args) (same as Sinatra)
    • url(path)
  • Rack::Request

    • request
    • env
    • params
    • session
    • cookies
    • logger
  • Rack::Response

    • response
    • headers
    • set_cookies
    • delete_cookie
  • ERB::Util

    • h (alias for: html_escape)
    • u (alias for: url_encode)

Configurations

Rack middleware

with parameter

use Rack::ServerPages, :view_path => 'public'

with block

use Rack::ServerPages do |config|
  config.view_path = 'public'
end

Rack application

with parameter

run Rack::ServerPages[:view_path => 'public']

with block

run Rack::ServerPages.new { |config|
  config.view_path = 'public'
}

Options

  • view_path

    • Views folders to load templates from.
    • default: [views, public]
  • effective_path

    • default: nil
  • default_charset

    • default: utf-8
  • cache_control

    • default: nil
  • failure_app

    • default: nil

Helpers

with helpers block

use Rack::ServerPages do |config|
  config.helpers do
    def three_times(name)
      "#{([name.to_s]*3).join(' ')}!!"
    end
  end
end

in view file (erb)

<%= three_times('blah') %>

with helper module

module SampleHelper
  def three_times(name)
    "#{([name.to_s]*3).join(' ')}!!"
  end
end

use Rack::ServerPages do |config|
  config.helpers SampleHelper
end

with procs

help1 = proc do
  def three_times(name)
    "#{([name.to_s]*3).join(' ')}!!"
  end
end

help2 = proc {...}

use Rack::ServerPages do |config|
  config.helpers help1, help2
end

Filters

with before/after block

use Rack::ServerPages do |config|
  config.before do
    @title = 'Hello!'
  end

  config.after do
    logger.debug 'xxxx'
  end
end

with procs

proc1 = proc { @name = 'Jonny' }
proc2 = proc { @age = 24 }
proc3 = proc { logger.debug 'xxxx' }

use Rack::ServerPages do |config|
  config.before proc1, proc2
  config.after proc3
end

if you define before/after method in helper module, it will be treated as filters

module SampleHelper
  def before
    @title = 'Hello!'
  end

  def three_times(name)
    "#{([name.to_s]*3).join(' ')}!!"
  end
end

use Rack::ServerPages do |config|
  config.helpers SampleHelper
end

in view file

<%= three_times(@title) %>

Tilt support

Tilt is generic interface to multiple Ruby template engines. If you want to use Tilt, just require 'tilt' and require template engine libraries that you want.

require 'rack-server-pages'
require 'tilt'
require 'rdiscount' # markdown library
run Rack::ServerPages

or put your Gemfile

views/article.html.md

A First Level Header
====================

A Second Level Header
---------------------

Now is the time for all good men to come to
the aid of their country. This is just a
regular paragraph.

### Header 3

> This is a blockquote.
> Thank you

[source](http://github.com/migrs/rack-server-pages)

http://localhost:9292/article.html

<h1>A First Level Header</h1>

<h2>A Second Level Header</h2>

<p>Now is the time for all good men to come to
the aid of their country. This is just a
regular paragraph.</p>

<h3>Header 3</h3>

<blockquote><p>This is a blockquote.
Thank you</p></blockquote>

<p><a href="http://github.com/migrs/rack-server-pages">source</a></p>

views/about.html.slim

doctype html
html
  head
    title Slim Core Example
    meta name="keywords" content="template language"

  body
    h1 Markup examples

    div id="content" class="example1"
      p Nest by indentation

http://localhost:9292/about.html

<!DOCTYPE html>
<html>
  <head>
    <title>Slim Core Example</title>
    <meta content="template language" name="keywords" />
  </head>
  <body>
    <h1>Markup examples</h1>
    <div class="example1" id="content">
      <p>Nest by indentation</p>
    </div>
  </body>
</html>

views/betty.css.sass

$blue: #3bbfce
$margin: 16px

.content-navigation
  border-color: $blue
  color: darken($blue, 9%)

.border
  padding: $margin / 2
  margin: $margin / 2
  border-color: $blue

http://localhost:9292/betty.css

.content-navigation {
  border-color: #3bbfce;
  color: #2ca2af; }

.border {
  padding: 8px;
  margin: 8px;
  border-color: #3bbfce; }

views/contact.xml.builder

xml.instruct!
xml.result do |result|
  result.name "John"
  result.phone "910-1974"
end

http://localhost:9292/contact.xml

<result>
  <name>John</name>
  <phone>910-1974</phone>
</result>

views/script.js.coffee

number   = 42
opposite = true

number = -42 if opposite

square = (x) -> x * x

list = [1, 2, 3, 4, 5]

math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

http://localhost:9292/script.js

(function() {
  var list, math, number, opposite, square;

  number = 42;

  opposite = true;

  if (opposite) number = -42;

  square = function(x) {
    return x * x;
  };

  list = [1, 2, 3, 4, 5];

  math = {
    root: Math.sqrt,
    square: square,
    cube: function(x) {
      return x * square(x);
    }
  };

}).call(this);

see more http://localhost:9292/examples/

Integrate with Rack applications

At first, create sample file: public/hello.erb or views/hello.html.erb

<p>Hello Rack Server Pages!</p>
<p><%= Time.now %></p>

Rails

Add to config/environment.rb (Rails2) or config/application.rb (Rails3)

config.middleware.use Rack::ServerPages

And run

Rails2

script/server

Rails3

rails s

Sinatra

Create sinatra_sample.rb

require 'sinatra'
require 'rack-server-pages'

use Rack::ServerPages

get '/' do
  '<p>Hello Sinatra!</p>'
end

And run

ruby sinatra_sample.rb

Customization

Customize file extension associations

e.g. .php as ERB

ERBTemplate (default)

Rack::ServerPages::Template::ERBTemplate.extensions << 'php'

TiltTemplate (see. Template Mappings)

Tilt.register Tilt::ERBTemplate, 'php'

And create public/info.php :)

<%= phpinfo(); %>

http://localhost:9292/info.php

Demo site

http://rack-server-pages.heroku.com/

ToDo

Implements

  • Static file generator (for designer)

Tasks

  • Tutorials
    • for PHP user
    • for Designer
    • for Windows user
  • More documents
    • Deployment using apache / passenger / nginx
  • Complete Tilt examples
  • Philosophy
  • Benchmark

License

rack-server-pages is Copyright (c) 2012-2016 Masato Igarashi(@migrs) and Contributors.

Distributed under the MIT license.

rack-server-pages's People

Contributors

dblock avatar migrs 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

rack-server-pages's Issues

Folders with periods is unreachable

It doesn't seem like folders with periods in it resolve correctly.

Consider a file in the following relative location public/vendor/bootstrap-4.1/test.html.

When hitting the expected URL: http://localhost:9292/vendor/bootstrap-4.1/test.html

It returns:

 Not Found: /vendor/bootstrap-4.1/test.html

Not compatible with rack 2

Via slack-ruby/slack-ruby-bot-server#31.

1) SlackRubyBotServer::Api returns a robots.txt that disallows indexing
     Failure/Error: get '/robots.txt'

     NoMethodError:
       undefined method `call' for nil:NilClass
       Did you mean?  caller
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/file.rb:31:in `call'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-server-pages-0.0.6/lib/rack/server_pages.rb:47:in `serving'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-server-pages-0.0.6/lib/rack/server_pages.rb:37:in `call'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-rewrite-1.5.1/lib/rack/rewrite.rb:24:in `call'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-cors-0.4.0/lib/rack/cors.rb:80:in `call'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get'
     # ./spec/api/robots_spec.rb:7:in `block (2 levels) in <top (required)>'
     # ./spec/support/database_cleaner.rb:15:in `block (3 levels) in <top (required)>'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/database_cleaner-1.5.3/lib/database_cleaner/generic/base.rb:16:in `cleaning'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/database_cleaner-1.5.3/lib/database_cleaner/base.rb:98:in `cleaning'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/database_cleaner-1.5.3/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
     # /Users/dblock/.rvm/gems/ruby-2.3.1/gems/database_cleaner-1.5.3/lib/database_cleaner/configuration.rb:87:in `cleaning'
     # ./spec/support/database_cleaner.rb:14:in `block (2 levels) in <top (required)>'

Add support for Rack 3

Looks like gem is broken for Rack 3.

09:09:33 web.1  | 127.0.0.1 - - [15/Jun/2024:09:09:33 -0400] "GET /img/favicons/favicon-16x16.png HTTP/1.1" 500 79751 0.0123
09:09:34 web.1  | NoMethodError: undefined method `call' for #<File:public>
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:46:in `serving'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:36:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-robotz-0.0.4/lib/rack/robotz/middleware.rb:20:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-rewrite-1.5.1/lib/rack/rewrite.rb:24:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-cors-2.0.2/lib/rack/cors.rb:102:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/tempfile_reaper.rb:20:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/lint.rb:66:in `response'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/lint.rb:41:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/show_exceptions.rb:31:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/common_logger.rb:43:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/rack-3.1.3/lib/rack/content_length.rb:20:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/newrelic_rpm-9.10.2/lib/new_relic/agent/instrumentation/middleware_tracing.rb:99:in `call'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:634:in `process_client'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:739:in `worker_loop'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/gems/unicorn-6.1.0/bin/unicorn:128:in `<top (required)>'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/bin/unicorn:25:in `load'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/bin/unicorn:25:in `<main>'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/bin/ruby_executable_hooks:22:in `eval'
09:09:34 web.1  | 	/Users/dblock/.rvm/gems/ruby-3.0.5/bin/ruby_executable_hooks:22:in `<main>'

Didn't dig deeper (yet).ruby

Involuntary inclusion of tilt gem causes dependency failure

I am working on a project that relies upon both rack-server-pages, and sidekiq-scheduler. sidekiq-scheduler has tilt as a dependency, which triggers rack-server-pages to attempt to utilize tilt, which I have not explicitly required or autoloaded.

Stack Trace:

Puma caught this error: undefined method `[]' for Tilt:Module
 
           @tilt ||= Tilt[@file]
                         ^^^^^^^ (NoMethodError)
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:232:in `find_template'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:185:in `[]'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:45:in `serving'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-server-pages-0.1.0/lib/rack/server_pages.rb:36:in `call'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-rewrite-1.5.1/lib/rack/rewrite.rb:24:in `call'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/rack-cors-1.1.1/lib/rack/cors.rb:100:in `call'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/otr-activerecord-2.1.2/lib/otr-activerecord/middleware/connection_management.rb:14:in `call'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/configuration.rb:252:in `call'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/request.rb:77:in `block in handle_request'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/thread_pool.rb:340:in `with_force_shutdown'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/request.rb:76:in `handle_request'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/server.rb:441:in `process_client'
 /Users/aberkowitz/.rvm/gems/ruby-3.1.1/gems/puma-5.6.4/lib/puma/thread_pool.rb:147:in `block in spawn_thread'

Engineering Notes

Require tilt in the TiltTemplate class would match the behavior of the ERBTemplate class within Rack::ServerPages::Template. The Readme suggests a solution, but that solution would be an unnecessary burden if -like in my case- I was unaware that tilt was included in one of my dependencies.

"redirect" causes "Rack::Lint::LintError at /file.erb, a header value must be a String, but the value of 'Content-Type' is a NilClass"

I have this line in index.erb:

<% redirect("ok.erb") %>

which produces the error documented below.

@dblock @rkh @rtomayko could you please help me fix this. It seems that @migrs is no longer mantaining this repository :( Possibly it has to do with changes in new Ruby versions?

I'm on Windows 7 64bit running ruby 2.3.0p0 (2015-12-25 revision 53290) [x64-mingw32] and rack-server-pages 0.0.6.

Thanks!

Rack::Lint::LintError at /index.erb
a header value must be a String, but the value of 'Content-Type' is a NilClass

c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/lint.rb: in assert
          raise LintError, message...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/lint.rb: in block in check_headers
        assert("a header value must be a String, but the value of " +...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/utils.rb: in block in each
          yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/utils.rb: in each
        super do |k, v|...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/utils.rb: in each
        super do |k, v|...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/lint.rb: in check_headers
      header.each { |key, value|...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/lint.rb: in _call
      check_headers headers...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/lint.rb: in call
      dup._call(env)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/showexceptions.rb: in call
      @app.call(env)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/commonlogger.rb: in call
      status, header, body = @app.call(env)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/chunked.rb: in call
      status, headers, body = @app.call(env)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/content_length.rb: in call
      status, headers, body = @app.call(env)...
c:/Ruby/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/handler/webrick.rb: in service
        status, headers, body = @app.call(env)...
c:/Ruby/lib/ruby/2.3.0/webrick/httpserver.rb: in service
      si.service(req, res)...
c:/Ruby/lib/ruby/2.3.0/webrick/httpserver.rb: in run
          server.service(req, res)...
c:/Ruby/lib/ruby/2.3.0/webrick/server.rb: in block in start_thread
          block ? block.call(sock) : run(sock)

How do I render a template with halt?

I'd like to render a template when calling halt (for bad request, not authorized etc) and can't seem to find a way to do it.

In other words, halt seems to take a string as an argument for body but how do I render a template in the views directory to use as input to halt?

Can someone please help? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.