Permalink
Browse files

starting a project with raxx.kit

  • Loading branch information...
CrowdHailer committed May 28, 2018
0 parents commit c49efa1f811cf84ecbd7e51844aeea8ae923aa72
@@ -0,0 +1,17 @@
# The directory Mix will write compiled artifacts to.
/_build
# If you run "mix test --cover", coverage assets end up here.
/cover
# The directory Mix downloads your dependencies sources to.
/deps
# Where 3rd-party dependencies like ExDoc output generated docs.
/doc
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
@@ -0,0 +1,15 @@
# Watercooler
- Install dependencies with `mix deps.get`
- Start your service with `iex -S mix`
- Run project test suite with `mix test`
## Learn more
- Raxx documentation: https://hexdocs.pm/raxx
- Slack channel: https://elixir-lang.slack.com/messages/C56H3TBH8/
## Building a distributed chatroom with Raxx.Kit
This is the code example for a distributed chatroom built with Raxx.Kit.
The full discussion around building it can be found in [this blog post](http://crowdhailer.me/2018-05-01/building-a-distributed-chatroom-with-raxx-kit/).
@@ -0,0 +1,4 @@
use Mix.Config
config :exsync,
extra_extensions: [".js", ".css"]
@@ -0,0 +1,2 @@
defmodule Watercooler do
end
@@ -0,0 +1,45 @@
defmodule Watercooler.Application do
@moduledoc false
use Application
def start(_type, _args) do
config = %{}
cleartext_options = [port: port, cleartext: true]
secure_options = [port: secure_port, cleartext: :false, certfile: certificate_path(), keyfile: certificate_key_path()]
children = [
Supervisor.child_spec({Watercooler.WWW, [config, cleartext_options]}, id: :www_cleartext),
Supervisor.child_spec({Watercooler.WWW, [config, secure_options]}, id: :www_secure),
]
opts = [strategy: :one_for_one, name: Watercooler.Supervisor]
Supervisor.start_link(children, opts)
end
defp port() do
with raw when is_binary(raw) <- System.get_env("PORT"), {port, ""} = Integer.parse(raw) do
port
else
_ -> 8080
end
end
defp secure_port() do
with raw when is_binary(raw) <- System.get_env("SECURE_PORT"), {secure_port, ""} = Integer.parse(raw) do
secure_port
else
_ -> 8443
end
end
defp certificate_path() do
Application.app_dir(:watercooler, "priv/localhost/certificate.pem")
end
defp certificate_key_path() do
Application.app_dir(:watercooler, "priv/localhost/certificate_key.pem")
end
end
Binary file not shown.
@@ -0,0 +1,60 @@
/* Reset */
body {
margin: 0;
}
/* Make everything a border-box, because why not? */
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
html {
min-height: 100%;
}
body {
font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
font-size: 1.6em // Currently ems cause chrome bug misinterpreting rems on body element;
font-weight: 300;
letter-spacing: .01em;
line-height: 1.6;
color: white;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#45484d+0,000000+100 */
background: rgb(69,72,77); /* Old browsers */
background: -moz-linear-gradient(right , rgba(69,72,77,1) 0%, rgba(0,0,0,1) 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(right, rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to left, rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#45484d', endColorstr='#000000',GradientType=0 ); /* IE6-9 */
}
h1 {
margin: 0;
font-size: 6.6rem;
font-weight: 300;
line-height: 1.2;
}
.centered {
margin-left: auto;
margin-right: auto;
max-width: 80rem;
}
.accent {
border-left: #00ff9c 2px solid;
margin: 50px;
padding: 30px;
}
nav {
letter-spacing: 3.5em
}
nav a {
color: #00ff9c;
letter-spacing: 0.05em
}
@@ -0,0 +1 @@
console.log("Hello")
@@ -0,0 +1,13 @@
defmodule Watercooler.WWW do
use Ace.HTTP.Service, [port: 8080, cleartext: true]
use Raxx.Router, [
{%{method: :GET, path: []}, Watercooler.WWW.HomePage},
{_, Watercooler.WWW.NotFoundPage}
]
@external_resource "lib/watercooler/public/main.css"
@external_resource "lib/watercooler/public/main.js"
use Raxx.Static, "./public"
use Raxx.Logger, level: :info
end
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>watercooler </title>
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
<link rel="stylesheet" href="/main.css">
</head>
<body>
<%= content %>
<script type="text/javascript" src="/main.js"> </script>
</body>
</html>
@@ -0,0 +1,10 @@
defmodule Watercooler.WWW.HomePage do
use Raxx.Server
use Watercooler.WWW.HTMLView
@impl Raxx.Server
def handle_request(_request, _state) do
response(:ok)
|> render(%{})
end
end
@@ -0,0 +1,10 @@
<main class="centered">
<section class="accent">
<h1>Raxx.Kit</h1>
<h2>Simply cloud native</h2>
<nav>
<a href="https://github.com/CrowdHailer/raxx">SOURCE CODE</a>
<a href="https://elixir-lang.slack.com/messages/C56H3TBH8/">CHAT</a>
</nav>
</section>
</main>
@@ -0,0 +1,28 @@
defmodule Watercooler.WWW.HTMLView do
layout_path = Path.join(__DIR__, "_layout.html.eex")
require EEx
EEx.function_from_file(:def, :render_layout, layout_path, [:content, :assigns], engine: Phoenix.HTML.Engine)
defmacro __using__(_options) do
quote do
file_path = case String.split(__ENV__.file, ~r/\.ex(s)?$/) do
[path_and_name, ""] ->
path_and_name <> ".html.eex"
_ ->
raise "Needs to be an `.ex` file"
end
require EEx
EEx.function_from_file(:defp, :render_content, file_path, [:assigns], engine: Phoenix.HTML.Engine)
def render(response, assigns) do
{:safe, io_list} = unquote(__MODULE__).render_layout(render_content(assigns), assigns)
response
|> Raxx.set_header("content-type", "text/html")
|> Raxx.set_body("#{io_list}")
end
end
end
end
@@ -0,0 +1,10 @@
defmodule Watercooler.WWW.NotFoundPage do
use Raxx.Server
use Watercooler.WWW.HTMLView
@impl Raxx.Server
def handle_request(_request, _state) do
response(:not_found)
|> render(%{})
end
end
@@ -0,0 +1,5 @@
<main class="centered">
<section class="accent">
<h1>Nothing here!</h1>
</section>
</main>
26 mix.exs
@@ -0,0 +1,26 @@
defmodule Watercooler.Mixfile do
use Mix.Project
def project do
[app: :watercooler,
version: "0.1.0",
elixir: "~> 1.6.4",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps()]
end
def application do
[extra_applications: [:logger],
mod: {Watercooler.Application, []}]
end
defp deps do
[
{:ace, "~> 0.16.4"},
{:phoenix_html, "~> 2.11"},
{:raxx_static, "~> 0.6.1"},
{:exsync, "~> 0.2.3", only: :dev},
]
end
end
@@ -0,0 +1,12 @@
%{
"ace": {:hex, :ace, "0.16.4", "8e3fe95f4f5b32c094037610f648c059b2f9fafafe9a33662908ad5b6022f9ed", [:mix], [{:hpack, "~> 0.2.3", [hex: :hpack_erl, repo: "hexpm", optional: false]}, {:raxx, "~> 0.15.2", [hex: :raxx, repo: "hexpm", optional: false]}], "hexpm"},
"cookie": {:hex, :cookie, "0.1.1", "89438362ee0f0ed400e9f076d617d630f82d682e3fbcf767072a46a6e1ed5781", [:mix], [], "hexpm"},
"exsync": {:hex, :exsync, "0.2.3", "a1ac11b4bd3808706003dbe587902101fcc1387d9fc55e8b10972f13a563dd15", [:mix], [{:file_system, "~> 0.2", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"},
"file_system": {:hex, :file_system, "0.2.5", "a3060f063b116daf56c044c273f65202e36f75ec42e678dc10653056d3366054", [:mix], [], "hexpm"},
"hpack": {:hex, :hpack_erl, "0.2.3", "17670f83ff984ae6cd74b1c456edde906d27ff013740ee4d9efaa4f1bf999633", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.2.0", "78adaa84832b3680de06f88f0997e3ead3b451a440d183d688085be2d709b534", [:mix], [], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.11.2", "86ebd768258ba60a27f5578bec83095bdb93485d646fc4111db8844c316602d6", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plug": {:hex, :plug, "1.5.1", "1ff35bdecfb616f1a2b1c935ab5e4c47303f866cb929d2a76f0541e553a58165", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.3", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
"raxx": {:hex, :raxx, "0.15.4", "62e4a487e55e9469d1ba2d5de590672167f51eaac310f027f3f871018cb6a9fc", [:mix], [{:cookie, "~> 0.1.0", [hex: :cookie, repo: "hexpm", optional: false]}], "hexpm"},
"raxx_static": {:hex, :raxx_static, "0.6.1", "8b48254fc3d1b8b1e473b7c307fbba0ae767c60482754ce823c664544c85d729", [:mix], [{:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:raxx, "~> 0.15.2", [hex: :raxx, repo: "hexpm", optional: false]}], "hexpm"},
}
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDPjCCAiYCCQDrSpjNLJXcbTANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJV
SzEPMA0GA1UECAwGTG9uZG9uMQ8wDQYDVQQHDAZMb25kb24xHDAaBgNVBAoME1dv
cmtzaG9wIDE0IExpbWl0ZWQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzA0Mjkx
NzEyMTJaFw0xODA0MjkxNzEyMTJaMGExCzAJBgNVBAYTAlVLMQ8wDQYDVQQIDAZM
b25kb24xDzANBgNVBAcMBkxvbmRvbjEcMBoGA1UECgwTV29ya3Nob3AgMTQgTGlt
aXRlZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAmNvyeepIRsAm6QuUezhFf3KXTygBoYX4oYMfXb6ZklDQ8QAT9Brs
YUW1+QDDHPF3foDa+k4Mm8XL6/yHqQFutnhqqYysd/XovCG1ff7Vq0TpX7GAHGEv
rTj/Q63xqVOmyZINgvi9TfRTIKZ5LIo6O0dV5LSv6cLTXa8bFBxybigTxL+HgzY0
e3kQzuFSYLOxvLCd4j7YnTzOsYY8M49mNRDbja4SkDcRxqV0mJDUkUxayaDWXY06
eY1RtiYHFeZQF/2iEKBnsm62VJcFiq/vnjNkc1SBxqIoXE7BrRe+yLi1TniMds8g
GDUX0QqnhbuG/USuB0ev0VZNg+LiUYA/dQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQAJaUbgakfrvtbD84hqpCGe0LmfCbjUEE5NIpu/TEvTjDgnuPVhwF2VBcVT6w96
YPL3hxt9DsMUsXapaD5v+rGOVJGReKWyl1JN1nqd2BRkYD++6AznOul5WepXOSHO
mCQOVPV2C3M+OYEDgLf9dcrGvpPJdexLLpy/xR1s9ZiNHKYGAfXxU6Va1uUi60lh
g2jjTNkYhthLiqygatEViZ25D/N7GBUtbCLf7YBRDPId5JnAd2sFI4vGeJJZMee/
RCWKyzC+ttY9AHClpUcLc9YdJUofFfwHjO+jFf1u19WfUxlC3GPh45hSFZ/g+Hz8
OxDc8YfSk8VAjJHu2ap7G9+G
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAmNvyeepIRsAm6QuUezhFf3KXTygBoYX4oYMfXb6ZklDQ8QAT
9BrsYUW1+QDDHPF3foDa+k4Mm8XL6/yHqQFutnhqqYysd/XovCG1ff7Vq0TpX7GA
HGEvrTj/Q63xqVOmyZINgvi9TfRTIKZ5LIo6O0dV5LSv6cLTXa8bFBxybigTxL+H
gzY0e3kQzuFSYLOxvLCd4j7YnTzOsYY8M49mNRDbja4SkDcRxqV0mJDUkUxayaDW
XY06eY1RtiYHFeZQF/2iEKBnsm62VJcFiq/vnjNkc1SBxqIoXE7BrRe+yLi1TniM
ds8gGDUX0QqnhbuG/USuB0ev0VZNg+LiUYA/dQIDAQABAoIBAQCOfA9ExzbCBGEA
wFOSnDxj9UvHdDI4/ulonBIDzyPVeFGbJAh1dRc8AMAEMEqvUwGgwLndsh0cor5X
5dgKmJQ7sHk0PDWTyHw9yWok3QMMl7q2AX26dnj7jfKbgquNu7TvlZ3UpMnIvWMz
Pxoag2qOUQtmmWqUio99dzjVgULFHFOufcSfPsM1s71BhcZwcssG2JxmbjsG8r1w
wR80p1VQjWzQdBe5Kgc+ZZZidf1SSW3W65zrdAV3tT9A78hmTdvhdXG9SOTu3Vt8
Eab1eAewfds0FGJtUIzpJe6DCWFBnpAsGbWCf2CMkPRhWcLHVFN8jHO6KpKdqq0b
bjXmZTAhAoGBAMZdXGqpFQWD73nVqrbdyZhtDU8VCAeT0d5XmlNQwvVPyPch50FL
zDt2H9k6+Ko3p8wjSIWdKFvsqYuCFbBI8Lf4b3+Tu2Vi9ajFrnHyGUlB0X1Ny+nt
iXpAUYCsGnp6hylzkNCGMQXQ55oDVjXr8/m/M8QpsGbAicu05HLuene5AoGBAMVF
0pyZNhjNBiJ/p/9AR1Rao8jWC5e70jxXdqX3kbWzobD1+qNEEP0klpnJGUIMASTb
P99OrY5Fo1bxJecLjrwpQU63d90erAnirq7luIjQnXHAT6lg7CZX4uNW+P/iqc8p
bvmcue6ptWf4HPtqtLpxXzbAlAA6SN5UDpFLbuudAoGAGaVOYnfTwO/K0Uyfkp7g
BnXq55OHgztIQd+/kw/49LBJAjJ+7IE5OWLPQU2PgqpJZmoVYTjtU90oGmJKHY2A
mbhj6fGWo8gEjLpqEE9Fl6QLypB5UZglUwnnv6QAlF8tBF3tlhgTVHYqy02tIrGL
zHk83xqotNAlwJF1i6praPkCgYABMGGLlhTQY3P1A0X08OM9K+quzDN3r6cdu/04
FNzo9nM0CNeA4mkjzXOm66JeVoovOa8R3nyHTf4lCQEMenJayfjdy5dKWuP4j0g0
P6g0EuXQCLOyNqZVuNPiQOTxTeFuITbNBFfOi3FPdhxem48JTKOhRdnegntr85++
2nCJtQKBgE9wMkBbQGKQxgV1VtNuLdhBPrCnvFvInX+/M5eaOLmg9IeDWER1vv5m
kHbAa6t+jvi70ZQPrwMmAVT6YawpUuR7Ttaga/QMThw0dSvUuiPLXPno3ZZl9GM4
OwKJHTSsqQf3jIT86Bm3wh375B8Dw0PPJUtraAkE4ioidTKuDnD4
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCVUsxDzANBgNVBAgMBkxvbmRvbjEPMA0G
A1UEBwwGTG9uZG9uMRwwGgYDVQQKDBNXb3Jrc2hvcCAxNCBMaW1pdGVkMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCY
2/J56khGwCbpC5R7OEV/cpdPKAGhhfihgx9dvpmSUNDxABP0GuxhRbX5AMMc8Xd+
gNr6Tgybxcvr/IepAW62eGqpjKx39ei8IbV9/tWrROlfsYAcYS+tOP9DrfGpU6bJ
kg2C+L1N9FMgpnksijo7R1XktK/pwtNdrxsUHHJuKBPEv4eDNjR7eRDO4VJgs7G8
sJ3iPtidPM6xhjwzj2Y1ENuNrhKQNxHGpXSYkNSRTFrJoNZdjTp5jVG2JgcV5lAX
/aIQoGeybrZUlwWKr++eM2RzVIHGoihcTsGtF77IuLVOeIx2zyAYNRfRCqeFu4b9
RK4HR6/RVk2D4uJRgD91AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAXlpo5GxS
oAavAybmPwlPYq9UekjsucRUx7q8MdI9+6JFgVZkJ47NZeq1ynuFM0QFGWC3Sbyx
q0yKD3/UHIItta/4nQev366jAfi2Se6IE9RYYcmly36joHUB0MtceLYEGwazJbaB
yq5nI0wgLDlQ318Uh9g+rc0DAohuEm+Guvq5xIVOXrkidhlPOiSHcXtIgGzHbfnz
oir5rhtRgpCgulFq18ZWeQpIZ1UvTz0QbPvnnUZiVDxQVvKHwdRAjtVoJmuD9fuz
F1ZiqKQWe4nqEw5pJuCK5tBdquB9hlWxaJhs/sR4dhcrjvX+8VxbGGaLlJV2mcrA
EheSjS4N675U3w==
-----END CERTIFICATE REQUEST-----
@@ -0,0 +1 @@
ExUnit.start()
@@ -0,0 +1,15 @@
defmodule Watercooler.WWW.HomePageTest do
use ExUnit.Case
alias Watercooler.WWW.HomePage
test "returns the Raxx.Kit home page" do
request = Raxx.request(:GET, "/")
response = HomePage.handle_request(request, %{})
assert response.status == 200
assert response.headers == [{"content-type", "text/html"}]
assert String.contains?(response.body, "Raxx.Kit")
end
end
@@ -0,0 +1,5 @@
defmodule WatercoolerTest do
use ExUnit.Case
doctest Watercooler
end

0 comments on commit c49efa1

Please sign in to comment.