• Stars
    star
    211
  • Rank 186,867 (Top 4 %)
  • Language
    JavaScript
  • License
    GNU General Publi...
  • Created over 7 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ¦„ Learn how to build web apps using the Elm Architecture in "vanilla" JavaScript (step-by-step TDD tutorial)!

Learn Elm Architecture in Plain JavaScript

Learn how to build web applications using the Elm ("Model Update View") Architecture in "plain" JavaScript.

Build Status test coverage dependencies Status devDependencies Status contributions welcome HitCount

We think Elm is the future of Front End Web Development
for all the reasons described in: github.com/dwyl/learn-elm#why
However we acknowledge that Elm is "not everyone's taste"!

What many Front-End Developers are learning/using is React.js.
Most new React.js apps are built using Redux which "takes cues from"
(takes all it's best ideas/features from) Elm:
redux-borrows-elm

Therefore, by learning the Elm Architecture, you will intrinsically understand Redux
which will help you learn/develop React apps.

This step-by-step tutorial is a gentle introduction to the Elm Architecture,
for people who write JavaScript and want a functional, elegant and fast
way of organizing their JavaScript code without having the learning curve
of a completely new (functional) programming language!

Why?

simple-life

Organizing code in a Web (or Mobile) Application is really easy to over-complicate,
especially when you are just starting out and there are dozens of competing ideas all claiming to be the "right way"...

When we encounter this type of "what is the right way?" question,
we always follow Occam's Razor and ask: what is the simplest way?
In the case of web application organization, the answer is: the "Elm Architecture".

When compared to other ways of organizing your code, "Model Update View" (MUV) has the following benefits:

  • Easier to understand what is going on in more advanced apps because there is no complex logic, only one basic principal and the "flow" is always the same.
  • Uni-directional data flow means the "state" of the app is always predictable; given a specific starting "state" and sequence of update actions, the output/end state will always be the same. This makes testing/testability very easy!
  • There's no "middle man" to complicate things (the way there is in other application architectures such as Model-view-Presenter or "Model-View-ViewModel" (MVVM) which is "overkill" for most apps).

Note: don't panic if any of the terms above are strange or even confusing to you right now. Our quest is to put all the concepts into context. And if you get "stuck" at any point, we are here to help! Simply open a question on GitHub: github.com/dwyl/learn-elm-architecture-in-javascript/issues

Who? (Should I Read/Learn This...?)

everybodys-gotta-learn-sometime

Anyone who knows a little bit of JavaScript and wants to learn how to organize/structure
their code/app in a sane, predictable and testable way.

Prerequisites?

all-you-need-is-less

No other knowledge is assumed or implied. If you have any questions, please ask:
github.com/dwyl/learn-elm-architecture-in-javascript/issues

What?

image

A Complete Beginner's Guide to "MUV"

Start with a few definitions:

  • Model - or "data model" is the place where all data is stored; often referred to as the application's state.
  • Update - how the app handles actions performed by people and updates the state, usually organised as a switch with various case statements corresponding to the different "actions" the user can take in your App.
  • View - what people using the app can see; a way to view the Model (in the case of the first tutorial below, the counter) as HTML rendered in a web browser.

elm-muv-architecture-diagram


If you're not into flow diagrams, here is a much more "user friendly" explanation of The Elm Architecture ("TEA"):

In the "View Theatre" diagram, the:

  • model is the ensamble of characters (or "puppets")
  • update is the function that transforms ("changes") the model (the "puppeteer").
  • view what the audience sees through "view port" (stage).

If this diagram is not clear (yet), again, don't panic, it will all be clarified when you start seeing it in action (below)!

How?

1. Clone this Repository

git clone https://github.com/dwyl/learn-elm-architecture-in-javascript.git && cd learn-elm-architecture-in-javascript

2. Open Example .html file in Web Browser

Tip: if you have node.js installed, simply run npm install! That will install live-server which will automatically refresh your browser window when you make changes to the code! (makes developing faster!)

When you open examples/counter-basic/index.html you should see:

elm-architecture-counter

Try clicking on the buttons to increase/decrease the counter.

3. Edit Some Code

In your Text Editor of choice, edit the initial value of the model (e.g: change the initial value from 0 to 9). Don't forget to save the file!

elm-architecture-code-update

4. Refresh the Web Browser

When you refresh the your Web Browser you will see that the "initial state" is now 9 (or whichever number you changed the initial value to):

update-initial-model-to-9

You have just seen how easy it is to set the "initial state" in an App built with the Elm Architecture.

5. Read Through & Break Down the Code in the Example

You may have taken the time to read the code in Step 3 (above) ...
If you did, well done for challenging yourself and getting a "head start" on reading/learning!
Reading (other people's) code is the fastest way to learn programming skills and the only way to learn useful "patterns".
If you didn't read through the code in Step 3, that's ok! Let's walk through the functions now!

As always, our hope is that the functions are clearly named and well-commented,
please inform us if anything is unclear please ask any questions as issues:
github.com/dwyl/learn-elm-architecture-in-javascript/issues

5.1 mount Function Walkthrough

The mount function "initializes" the app and tells the view how to process a signal sent by the user/client.

function mount(model, update, view, root_element_id) {
  var root = document.getElementById(root_element_id); // root DOM element
  function signal(action) {          // signal function takes action
    return function callback() {     // and returns callback
      model = update(model, action); // update model according to action
      view(signal, model, root);     // subsequent re-rendering
    };
  };
  view(signal, model, root);         // render initial model (once)
}

The mount function receives the following four arguments:

  • model: "initial state" of your application (in this case the counter which starts at 0)
  • update: the function that gets executed when ever a "signal" is received from the client (person using the app).
  • view: the function that renders the DOM (see: section 5.3 below)
  • root_element_id is the id of the "root DOM element"; this is the DOM element
    where your app will be "mounted to". In other words your app will be contained within this root element.
    (so make sure it is empty before mounting)

The first line in mount is to get a reference to the root DOM element;
we do this once in the entire application to minimize DOM lookups.

mount > signal > callback ?

The interesting part of the mount function is signal (inner function)!
At first this function may seem a little strange ...
Why are we defining a function that returns another function?
If this your first time seeing this "pattern", welcome to the wonderful world of "closures"!

What is a "Closure" and Why/How is it Useful?

A closure is an inner function that has access to the outer (enclosing) function's variablesβ€”scope chain. The closure has three scope chains: it has access to its own scope (variables defined between its curly brackets), it has access to the outer function's variables, and it has access to the global variables.

In the case of the callback function inside signal, the signal is "passed" to the various bits of UI and the callback gets executed when the UI gets interacted with. If we did not have the callback the signal would be executed immediately when the button is defined.
Whereas we only want the signal (callback) to be triggered when the button is clicked.
Try removing the callback to see the effect:

range-error-stack-exceeded

The signal is triggered when button is created, which re-renders the view creating the button again. And, since the view renders two buttons each time it creates a "chain reaction" which almost instantly exceeds the "call stack" (i.e. exhausts the allocated memory) of the browser!

Putting the callback in a closure means we can pass a reference to the signal (parent/outer) function to the view function.

Further Reading on Closures

5.1.1 mount > render initial view

The last line in the mount function is to render the view function for the first time, passing in the signal function, initial model ("state") and root element. This is the initial rendering of the UI.

5.2 Define the "Actions" in your App

The next step in the Elm Architecture is to define the Actions that can be taken in your application. In the case of our counter example we only have two (for now):

// Define the Component's Actions:
var Inc = 'inc';                     // increment the counter
var Dec = 'dec';                     // decrement the counter

These Actions are used in the switch (i.e. decide what to do) inside the update function.

Actions are always defined as a String.
The Action variable gets passed around inside the JS code
but the String representation is what appears in the DOM
and then gets passed in signal from the UI back to the update function.

One of the biggest (side) benefits of defining actions like this is that it's really quick to see what the application does by reading the list of actions!

5.3 Define the update Function

The update function is a simple switch statement that evaluates the action and "dispatches" to the required function for processing.

In the case of our simple counter we aren't defining functions for each case:

function update(model, action) {     // Update function takes the current model
  switch(action) {                   // and an action (String) runs a switch
    case Inc: return model + 1;      // add 1 to the model
    case Dec: return model - 1;      // subtract 1 from model
    default: return model;           // if no action, return current model.
  }                                  // (default action always returns current)
}

However if the "handlers" for each action were "bigger", we would split them out into their own functions e.g:

// define the handler function used when action is "inc"
function increment(model) {
  return model + 1
}
// define handler for "dec" action
function decrement(model) {
  return model - 1
}
function update(model, action) {     // Update function takes the current state
  switch(action) {                   // and an action (String) runs a switch
    case Inc: return increment(model);  // add 1 to the model
    case Dec: return decrement(model);  // subtract 1 from model
    default: return model;           // if no action, return current state.
  }                                  // (default action always returns current)
}

This is functionally equivalent to the simpler update (above)
But does not offer any advantage at this stage (just remember it for later).

5.4 Define the view Function

The view function is responsible for rendering the state to the DOM.

function view(signal, model, root) {
  empty(root);                                 // clear root element before
  [                                            // Store DOM nodes in an array
    button('+', signal, Inc),                  // create button (defined below)
    div('count', model),                       // show the "state" of the Model
    button('-', signal, Dec)                   // button to decrement counter
  ].forEach(function(el){ root.appendChild(el) }); // forEach is ES5 so IE9+
}

The view receives three arguments:

  • signal defined above in mount tells each (DOM) element how to "handle" the user input.
  • model a reference to the current value of the counter.
  • root a reference to the root DOM element where the app is mounted.

The view function starts by emptying the DOM inside the root element using the empty helper function.
This is necessary because, in the Elm Architecture, we re-render the entire application for each action.

See note on DOM Manipulation and "Virtual DOM" (below)

The view creates a list (Array) of DOM nodes that need to be rendered.

5.4.1 view helper functions: empty, button and div

The view makes use of three "helper" (DOM manipulation) functions:

  1. empty: empty the root element of any "child" nodes. Essentially delete the DOM inside whichever element's passed into empty.
function empty(node) {
  while (node.firstChild) { // while there are still nodes inside the "parent"
      node.removeChild(node.firstChild); // remove any children recursively
  }
}
  1. button: creates a <button> DOM element and attaches a "text node" which is the visible contents of the button the "user" sees.
function button(buttontext, signal, action) {
  var button = document.createElement('button');  // create a button HTML node
  var text = document.createTextNode(buttontext); // human-readable button text
  button.appendChild(text);                       // text goes *inside* button
  button.className = action;                      // use action as CSS class
  button.onclick = signal(action);                // onclick sends signal
  return button;                                  // return the DOM node(s)
}
  1. div: creates a <div> DOM element and applies an id to it, then if some text was supplied in the second argument, creates a "text node" to display that text. (in the case of our counter the text is the current value of the model, i.e. the count)
function div(divid, text) {
  var div = document.createElement('div'); // create a <div> DOM element
  div.id = divid;
  if(text !== undefined) { // if text is passed in render it in a "Text Node"
    var txt = document.createTextNode(text);
    div.appendChild(txt);
  }
  return div;
}

Note: in elm land all of these "helper" functions are in the elm-html package, but we have defined them in this counter example so there are no dependencies and you can see exactly how everything is "made" from "first principals".

Once you have read through the functions (and corresponding comments),
take a look at the tests.

Pro Tip: Writing code is an iterative (repetitive) process, manually refreshing the web browser each time you update some code gets tedious quite fast, Live Server to the rescue!

6. (Optional) Install "Live Server" for "Live Reloading"

Note: Live Reloading is not required, e.g. if you are on a computer where you cannot install anything, the examples will still work in your web browser.

Live Reloading helps you iterate/work faster because you don't have to
manually refresh the page each time.
Simply run the following command:

npm install && npm start

This will download and start live-server which will auto-open your default browser:
Then you can navigate to the desired file. e.g: http://127.0.0.1:8000/examples/counter-basic/

7. Read the Tests!

In the first example we kept everything in one file (index.html) for simplicity.
In order to write tests (and collect coverage), we need to separate out the JavaScript code from the HTML.

For this example there are 3 separate files:

test-example-files

Let's start by opening the /examples/counter-basic-test/index.html file in a web browser:
http://127.0.0.1:8000/examples/counter-basic-test/?coverage

counter-coverage

Because all functions are "pure", testing the update function is very easy:

test('Test Update update(0) returns 0 (current state)', function(assert) {
  var result = update(0);
  assert.equal(result, 0);
});

test('Test Update increment: update(1, "inc") returns 2', function(assert) {
  var result = update(1, "inc");
  assert.equal(result, 2);
});

test('Test Update decrement: update(3, "dec") returns 2', function(assert) {
  var result = update(1, "dec");
  assert.equal(result, 0);
});

open: examples/counter-basic-test/test.js to see these and other tests.

The reason why Apps built using the Elm Architecture are so easy to understand
(or "reason about") and test is that all functions are "Pure".

8. What is a "Pure" Function? (Quick Learning/Recap)

Pure Functions are functions that always return the same output for a given input.
Pure Functions have "no side effects", meaning they don't change anything they aren't supposed to,
they just do what they are told; this makes them very predictable/testable. Pure functions "transform" data into the desired value, they do not "mutate" state.

8.1 Example of an Impure Function

The following function is "impure" because it "mutates" i.e. changes the counter variable which is outside of the function and not passed in as an argument:

// this is an "impure" function that "mutates" state
var counter = 0;
function increment () {
  return ++counter;
}
console.log(increment()); // 1
console.log(increment()); // 2
console.log(increment()); // 3

see: https://repl.it/FIot/1

8.2 Example of an Pure Function

This example is a "pure" function because it will always return same result for a given input.

var counter = 0;
function increment (my_counter) {
  return my_counter + 1;
}
// counter variable is not being "mutated"
// the output of a pure function is always identical
console.log(increment(counter)); // 1
console.log(increment(counter)); // 1
console.log(increment(counter)); // 1
// you can "feed" the output of one pure function into another to get the same result:
console.log(increment(increment(increment(counter)))); // 3

see: https://repl.it/FIpV

8.3 Counter Example written in "Impure" JS

It's easy to get suckered into thinking that the "impure" version of the counter
examples/counter-basic-impure/index.html is "simpler" ...
the complete code (including HTML and JS) is 8 lines:

<button class='inc' onclick="incr()">+</button>
<div id='count'>0</div>
<button class='dec' onclick="decr()">-</button>
<script>
  var el = document.getElementById('count')
  function incr() { el.innerHTML = parseInt(el.textContent, 10) + 1 };
  function decr() { el.innerHTML = parseInt(el.textContent, 10) - 1 };
</script>

This counter does the same thing as our Elm Architecture example (above),
and to the end-user the UI looks identical:

counter-impure-665

The difference is that in the impure example is "mutating state" and it's impossible to predict what that state will be!

Annoyingly, for the person explaining the benefits of function "purity" and the virtues of the Elm Architecture
the "impure" example is both fewer lines of code (which means it loads faster!), takes less time to read
and renders faster because only the <div> text content is being updated on each update!
This is why it can often be difficult to explain to "non-technical" people that code which has similar output
on the screen(s) might not the same quality "behind the scenes"!

Writing impure functions is like setting off on a marathon run after tying your shoelaces incorrectly ...
You might be "OK" for a while, but pretty soon your laces will come undone and you will have to stop and re-do them.

To conclude: Pure functions do not mutate a "global" state and are thus predictable and easy to test; we always use "Pure" functions in Apps built with the Elm Architecture. The moment you use "impure" functions you forfeit reliability.

9. Extend the Counter Example following "TDD": Reset the Count!

As you (hopefully) recall from our Step-by-Step TDD Tutorial, when we craft code following the "TDD" approach, we go through the following steps:

  1. Read and understand the "user story" (e.g: in this case: issues/5) reset-counter-user-story
  2. Make sure the "acceptance criteria" are clear (the checklist in the issue)
  3. Write your test(s) based on the acceptance criteria. (Tip: a single feature - in this case resetting the counter - can and often should have multiple tests to cover all cases.)
  4. Write code to make the test(s) pass.

BEFORE you continue, try and build the "reset" functionality yourself following TDD approach!




9.1 Tests for Resetting the Counter (Update)

We always start with the Model test(s) (because they are the easiest):

test('Test: reset counter returns 0', function(assert) {
  var result = update(6, "reset");
  assert.equal(result, 0);
});

9.2 Watch it Fail!

Watch the test fail in your Web Browser:
reset-counter-failing-test

9.3 Make it Pass (writing the minimum code)

In the case of an App written with the Elm Architecture, the minimum code is:

  • Action in this case var Res = 'reset';
  • Update (case and/or function) to "process the signal" from the UI (i.e. handle the user's desired action)
case Res: return 0;

reset-counter-test-passing

9.4 Write View (UI) Tests

Once we have the Model tests passing we need to give the user something to interact with!
We are going to be "adventurous" and write two tests this time!
(thankfully we already have a UI test for another button we can "copy")

test('reset button should be present on page', function(assert) {
  var reset = document.getElementsByClassName('reset');
  assert.equal(reset.length, 1);
});

test('Click reset button resets model (counter) to 0', function(assert) {
  mount(7, update, view, id); // set initial state
  var root = document.getElementById(id);
  assert.equal(root.getElementsByClassName('count')[0].textContent, 7);
  var btn = root.getElementsByClassName("reset")[0]; // click reset button
  btn.click(); // Click the Reset button!
  var state = root.getElementsByClassName('count')[0].textContent;
  empty(document.getElementById(id)); // Clear the test DOM elements
});

9.5 Watch View/UI Tests Fail!

Watch the UI tests go red in the browser:

reset-counter-failing-tests

9.6 Make UI Tests Pass (writing the minimum code)

Luckily, to make both these tests pass requires a single line of code in the view function!

button('Reset', signal, Res)

reset-counter


10. Next Level: Multiple Counters!

Now that you have understood the Elm Architecture by following the basic (single) counter example, it's time to take the example to the next level: multiple counters on the same page!

Multiple Counters Exercise

Follow your instincts and try to the following:

1. Refactor the "reset counter" example to use an Object for the model (instead of an Integer)
e.g: var model = { counters: [0] }
where the value of the first element in the model.counters Array is the value for the single counter example.

2. Display multiple counters on the same page using the var model = { counters: [0] } approach.

3. Write tests for the scenario where there are multiple counters on the same page.

Once you have had a go, checkout our solutions: examples/multiple-counters
and corresponding writeup: multiple-counters.md


11. Todo List!

The ultimate test of whether you learned/understood something is
applying your knowledge to different context from the one you learned in.

Let's "turn this up to eleven" and build something "useful"!

GOTO: todo-list.md


Futher/Background Reading




tl;dr

Flattening the Learning Curve

The issue of the "Elm Learning Curve" was raised in: github.com/dwyl/learn-elm/issues/45
and scrolling down to to @lucymonie's list we see the Elm Architecture at number four ...
this seems fairly logical (initially) because the Elm Guide uses the Elm Language to explain the Elm Architecture: https://guide.elm-lang.org/architecture

elm-architecture

i.e. it assumes that people already understand the (Core) Elm Language...
This is a fair assumption given the ordering of the Guide however ... we have a different idea:

Hypothesis: Learn (& Practice) Elm Architecture before Learning Elm?

We hypothesize that if we explain the Elm Architecture (in detail) using a language
people are already familiar with (i.e JavaScript) before diving into the Elm Language
it will "flatten" the learning curve.

Note: Understanding the Elm Architecture will give you a massive headstart
on learning Redux which is the "de facto" way of structuring React.js Apps.
So even if you decide not to learn/use Elm, you will still gain great frontend skills!

Isn't DOM Manipulation Super Slow...?

DOM manipulation is the slowest part of any "client-side" web app.
That is why so many client-side frameworks (including Elm, React and Vue.js) now use a "Virtual DOM". For the purposes of this tutorial, and for most small apps Virtual DOM is total overkill!
It's akin to putting a jet engine in a go kart!

What is "Plain" JavaScript?

"Plain" JavaScript just means not using any frameworks or features that require "compilation".

The point is to understand that you don't need anything more than "JavaScript the Good Parts"
to build something full-featured and easy/fast to read!!

babel

If you can build with "ES5" JavaScript:
a) you side-step the noise and focus on core skills that already work everywhere!
(don't worry you can always "top-up" your JS knowledge later with ES6, etc!)
b) you don't need to waste time installing Two Hundred Megabytes of dependencies just to run a simple project!
c) You save time (for yourself, your team and end-users!) because your code is already optimized to run in any browser!

More Repositories

1

english-words

πŸ“ A text file containing 479k English words for all your dictionary/word-based projects e.g: auto-completion / autosuggestion
Python
9,337
star
2

learn-json-web-tokens

πŸ” Learn how to use JSON Web Token (JWT) to secure your next Web App! (Tutorial/Example with Tests!!)
JavaScript
4,178
star
3

learn-to-send-email-via-google-script-html-no-server

πŸ“§ An Example of using an HTML form (e.g: "Contact Us" on a website) to send Email without a Backend Server (using a Google Script) perfect for static websites that need to collect data.
HTML
3,140
star
4

repo-badges

⭐ Use repo badges (build passing, coverage, etc) in your readme/markdown file to signal code quality in a project.
HTML
2,831
star
5

learn-tdd

βœ… A brief introduction to Test Driven Development (TDD) in JavaScript (Complete Beginner's Step-by-Step Tutorial)
JavaScript
2,698
star
6

start-here

πŸ’‘ A Quick-start Guide for People who want to dwyl ❀️ βœ…
1,734
star
7

learn-elixir

πŸ’§ Learn the Elixir programming language to build functional, fast, scalable and maintainable web applications!
Elixir
1,611
star
8

learn-travis

😎 A quick Travis CI (Continuous Integration) Tutorial for Node.js developers
JavaScript
1,251
star
9

Javascript-the-Good-Parts-notes

πŸ“– Notes on the seminal "JavaScript the Good Parts: by Douglas Crockford
1,193
star
10

aws-sdk-mock

🌈 AWSomocks for Javascript/Node.js aws-sdk tested, documented & maintained. Contributions welcome!
TypeScript
1,113
star
11

learn-aws-lambda

✨ Learn how to use AWS Lambda to easily create infinitely scalable web services
JavaScript
1,035
star
12

book

πŸ“— Our Book on Full-Stack Web Application Development covering User Experience (UX) Design, Mobile/Offline/Security First, Progressive Enhancement, Continuous Integration/Deployment, Testing (UX/TDD/BDD), Performance-Driven-Development and much more!
Rust
818
star
13

hapi-auth-jwt2

πŸ”’ Secure Hapi.js authentication plugin using JSON Web Tokens (JWT) in Headers, URL or Cookies
JavaScript
795
star
14

learn-hapi

β˜€οΈ Learn to use Hapi.js (Node.js) web framework to build scalable apps in less time
HTML
794
star
15

phoenix-chat-example

πŸ’¬ The Step-by-Step Beginners Tutorial for Building, Testing & Deploying a Chat app in Phoenix 1.7 [Latest] πŸš€
Elixir
760
star
16

learn-tachyons

😍 Learn how to use Tachyons to craft beautiful, responsive and fast UI with functional CSS!
HTML
673
star
17

learn-phoenix-framework

πŸ”₯ Phoenix is the web framework without compromise on speed, reliability or maintainability! Don't settle for less. πŸš€
Elixir
650
star
18

javascript-todo-list-tutorial

βœ… A step-by-step complete beginner example/tutorial for building a Todo List App (TodoMVC) from scratch in JavaScript following Test Driven Development (TDD) best practice. 🌱
JavaScript
623
star
19

learn-nightwatch

🌜 Learn how to use Nightwatch.js to easily & automatically test your web apps in *real* web browsers.
JavaScript
585
star
20

learn-elm

🌈 discover the beautiful programming language that makes front-end web apps a joy to build and maintain!
HTML
483
star
21

learn-redux

πŸ’₯ Comprehensive Notes for Learning (how to use) Redux to manage state in your Web/Mobile (React.js) Apps.
HTML
446
star
22

hits

πŸ“ˆ General purpose hits (page views) counter
Elixir
432
star
23

learn-devops

🚧 Learn the craft of "DevOps" (Developer Operations) to Deploy your App and Monitor it so it stays "Up"!
Shell
413
star
24

phoenix-liveview-counter-tutorial

🀯 beginners tutorial building a real time counter in Phoenix 1.7.14 + LiveView 1.0 ⚑️ Learn the fundamentals from first principals so you can make something amazing! πŸš€
Elixir
374
star
25

hapi-socketio-redis-chat-example

πŸ’¬ Real-time Chat using Hapi.js + Socket.io + Redis Pub/Sub (example with tests!!)
Elm
366
star
26

hapi-typescript-example

⚑ Hapi.Js + Typescript = Awesomeness
TypeScript
351
star
27

learn-istanbul

🏁 Learn how to use the Istanbul JavaScript Code Coverage Tool
JavaScript
339
star
28

learn-redis

πŸ“• Need to store/access your data as fast as possible? Learn Redis! Beginners Tutorial using Node.js πŸš€
JavaScript
291
star
29

technology-stack

πŸš€ Detailed description + diagram of the Open Source Technology Stack we use for dwyl projects.
JavaScript
288
star
30

phoenix-ecto-encryption-example

πŸ” A detailed example for how to encrypt data in an Elixir (Phoenix v1.7) App before inserting into a database using Ecto Types
Elixir
274
star
31

learn-elasticsearch

πŸ” Learn how to use ElasticSearch to power a great search experience for your project/product/website.
Elixir
265
star
32

elixir-auth-google

πŸ‘€Minimalist Google OAuth Authentication for Elixir Apps. Tested, Documented & Maintained. Setup in 5 mins. πŸš€
Elixir
263
star
33

home

🏑 πŸ‘©β€πŸ’» πŸ’‘ home is where you can [learn to] build the future surrounded by like-minded creative, friendly and [intrinsically] motivated people focussed on health, fitness and making things people and the world need!
246
star
34

learn-docker

🚒 Learn how to use docker.io containers to consistently deploy your apps on any infrastructure.
Dockerfile
220
star
35

learn-environment-variables

πŸ“Learn how to use Environment Variables to keep your passwords and API keys secret. πŸ”
JavaScript
201
star
36

learn-postgresql

🐘 Learn how to use PostgreSQL and Structured Query Language (SQL) to store and query your relational data. πŸ”
JavaScript
195
star
37

learn-tape

βœ… Learn how to use Tape for JavaScript/Node.js Test Driven Development (TDD) - Ten-Minute Testing Tutorial
JavaScript
187
star
38

sendemail

πŸ’Œ Simplifies reliably sending emails from your node.js apps using AWS Simple Email Service (SES)
JavaScript
181
star
39

phoenix-todo-list-tutorial

βœ… Complete beginners tutorial building a todo list from scratch in Phoenix 1.7 (latest)
Elixir
171
star
40

quotes

πŸ’¬ a curated list of quotes that inspire action + code that returns quotes by tag/author/etc. πŸ’‘
Elixir
163
star
41

learn-heroku

🏁 Learn how to deploy your web application to Heroku from scratch step-by-step in 7 minutes!
Python
153
star
42

decache

:shipit: Delete Cached node_modules useful when you need to "un-require" during testing for a fresh state.
JavaScript
151
star
43

learn-chrome-extensions

🌐 Discover how to build and deploy a Google Chrome Extension for your Project!
139
star
44

labels

🏷 Sync GitHub Labels from any Source to Target Repositories for Consistency across all your projects!
Elixir
138
star
45

learn-ab-and-multivariate-testing

πŸ†Ž Tutorial on A/B and multivariate testing βœ”οΈ
137
star
46

ISO-27001-2013-information-technology-security

πŸ” Probably the most boring-but-necessary repo on GitHub. If you care about the security/privacy of your data...! βœ…
136
star
47

auth

πŸšͺ πŸ” UX-focussed Turnkey Authentication Solution for Web Apps/APIs (Documented, Tested & Maintained)
Elixir
135
star
48

web-form-to-google-sheet

A simple example of sending data from an ordinary web form straight to a Google Spreadsheet without a server.
HTML
133
star
49

app

Clear your mind. Organise your life. Ignore distractions. Focus on what matters.
Dart
133
star
50

phoenix-liveview-chat-example

πŸ’¬ Step-by-step tutorial creates a Chat App using Phoenix LiveView including Presence, Authentication and Style with Tailwind CSS
Elixir
130
star
51

learn-circleci

βœ… A quick intro to Circle CI (Continuous Integration) for JavaScript developers.
121
star
52

learn-regex

⁉️ A simple REGular EXpression tutorial in JavaScript
120
star
53

learn-react

"The possibilities are numerous once we decide to act and not react." ~ George Bernard Shaw
HTML
108
star
54

learn-aws-iot

πŸ’‘ Learn how to use Amazon Web Services Internet of Things (IoT) service to build connected applications.
JavaScript
101
star
55

env2

πŸ’» Simple environment variable (from config file) loader for your node.js app
JavaScript
100
star
56

how-to-choose-a-database

How to choose the right dabase
97
star
57

flutter-todo-list-tutorial

βœ… A detailed example/tutorial building a cross-platform Todo List App using Flutter πŸ¦‹
Dart
91
star
58

imgup

πŸŒ… Effortless image uploads to AWS S3 with automatic resizing including REST API.
Elixir
88
star
59

mvp

πŸ“² simplest version of the @dwyl app
Elixir
87
star
60

contributing

πŸ“‹ Guidelines & Workflow for people contributing to our project(s) on GitHub. Please ⭐ to confirm you've read & understood! βœ…
86
star
61

learn-flutter

πŸ¦‹ Learn how to use Flutter to Build Cross-platform Native Mobile Apps
JavaScript
86
star
62

javascript-best-practice

A collection of JavaScript Best Practices
83
star
63

learn-amazon-web-services

⭐ Amazing Guide to using Amazon Web Services (AWS)! ☁️
83
star
64

range-touch

πŸ“± Use HTML5 range input on touch devices (iPhone, iPad & Android) without bloatware!
JavaScript
83
star
65

learn-pre-commit

βœ… Pre-commit hooks let you run checks before allowing a commit (e.g. JSLint or check Test Coverage).
JavaScript
80
star
66

product-owner-guide

πŸš€ A rough guide for people working with dwyl as Product Owners
78
star
67

phoenix-ecto-append-only-log-example

πŸ“ A step-by-step example/tutorial showing how to build a Phoenix (Elixir) App where all data is immutable (append only). Precursor to Blockchain, IPFS or Solid!
Elixir
78
star
68

fields

🌻 fields is a collection of useful field definitions (Custom Ecto Types) that helps you easily define an Ecto Schema with validation, encryption and hashing functions so that you can ship your Elixir/Phoenix App much faster!
Elixir
77
star
69

goodparts

πŸ™ˆ An ESLint Style that only allows JavaScript the Good Parts (and "Better Parts") in your code.
JavaScript
77
star
70

hapi-error

β˜” Intercept errors in your Hapi Web App/API and send a *useful* message to the client OR redirect to the desired endpoint.
JavaScript
76
star
71

process-handbook

πŸ“— Contains our processes, questions and journey to creating a team
HTML
76
star
72

terminate

♻️ Terminate a Node.js Process (and all Child Processes) based on the Process ID
JavaScript
76
star
73

aws-lambda-deploy

☁️ πŸš€ Effortlessly deploy Amazon Web Services Lambda function(s) with a single command. Less to configure. Latest AWS SDK and Node.js v20!
JavaScript
74
star
74

dev-setup

✈️ A quick-start guide for new engineers on how to set up their Dev environment
73
star
75

hapi-login-example-postgres

🐰 A simple registration + login form example using hapi-register, hapi-login & hapi-auth-jwt2 with a PostgreSQL DB
JavaScript
69
star
76

flutter-bloc-tutorial

A step-by-step example/tutorial explaining the benefits of the BLoC architecture and bloc library including tests!
Dart
67
star
77

phoenix-liveview-todo-list-tutorial

βœ… Beginners tutorial building a Realtime Todo List in Phoenix 1.6.10 + LiveView 0.17.10 ⚑️ Feedback very welcome!
Elixir
65
star
78

learn-security

πŸ” For most technology projects Security is an "after thought", it does not have to be that way; let's be proactive!
64
star
79

learn-javascript

A Series of Simple Steps in JavaScript :-)
HTML
63
star
80

chat

πŸ’¬ Probably the fastest, most reliable/scalable chat system on the internet.
Elixir
62
star
81

learn-jsdoc

πŸ“˜ Use JSDoc and a few carefully crafted comments to document your JavaScript code!
CSS
60
star
82

ampl

πŸ“± ⚑ Ampl transforms Markdown into AMP-compliant html so it loads super-fast!
JavaScript
58
star
83

aguid

❄️ A Globally Unique IDentifier (GUID) generator in JS. (deterministic or random - you chose!)
JavaScript
57
star
84

tudo

βœ… Want to see where you could help on an open dwyl issue?
Elixir
57
star
85

learn-apple-watch-development

πŸ“— Learn how to build Native Apple Watch (+iPhone) apps from scratch!
Swift
55
star
86

learn-qunit

βœ… A quick introduction to JavaScript unit testing with QUnit
JavaScript
51
star
87

learn-ngrok

☁️ Learn how to use ngrok to share access to a Web App/Site running on your "localhost" with the world!
HTML
50
star
88

learn-jshint

πŸ’© Learn how to use the ~~jshint~~ code quality/consistency tool.
JavaScript
49
star
89

hapi-auth-jwt2-example

πŸ”’ A functional example Hapi.js app using hapi-auth-jwt2 & Redis (hosted on Heroku) with tests!
JavaScript
49
star
90

tachyons-bootstrap

πŸ‘’Bootstrap recreated using tachyons functional css
HTML
48
star
91

learn-tailwind

🌬️ Learn Tailwind CSS to craft pixel-perfect web apps/sites in less time! 😍
Elixir
48
star
92

esta

πŸ” Simple + Fast ElasticSearch Node.js client. Beginner-friendly defaults & Heroku support βœ… πŸš€
JavaScript
48
star
93

learn-node-js-by-example

☁️ Practical node.js examples.
HTML
47
star
94

elixir-pre-commit

βœ… Pre-commit hooks for Elixir projects
Elixir
46
star
95

product-roadmap

🌐 Because why wouldn't you make your company's product roadmap Public on GitHub?
46
star
96

redis-connection

⚑ Single Redis Connection that can be used anywhere in your node.js app and closed once (e.g in tests)
JavaScript
45
star
97

learn-graphQL

❓Learn to use GraphQL - A query language that allows client applications to specify their data fetching requirements
JavaScript
45
star
98

aws-lambda-test-utils

Mock event and context objects without fluff.
JavaScript
44
star
99

hapi-login

πŸšͺ The Simplest Possible (Email + Password) Login for Hapi.js Apps βœ…
JavaScript
43
star
100

learn-riot

🐎 Riot.js lets you build apps that are simpler and load/run faster than any other JS framework/library.
HTML
43
star