Democracy for the 21st century.
- Make sure you have the system level dependencies:
- Fork this repo.
- Clone down:
git clone https://github.com/YOU/democracy.space.git
- Install required node modules:
npm install
source .template.env
npm start
Your local version should now be running at http://localhost:3000
.
Read .template.env
and write your own environment.bat
file. It should look like the text below:
set API_URL=https://api.democracy.space
set APP_NAME=Democracy Space
set WWW_PORT=3000
set WWW_URL=http://localhost:%WWW_PORT%
set WWW_DOMAIN=democracy.space
set ASSETS_URL=%WWW_URL%/assets
set APP_LOGO=%WWW_URL%/assets/democracy-space-logo.png
set GOOGLE_GEOCODER_KEY=AIzaSyCJYJN-fUm5FqN8-DvFYz-9GH8hokSCbdQ
set NODE_ENV=development
set STRIPE_API_PUBLIC_KEY=pk_test_hLhLcJepsaktxBMieH9tApxE
set TWILIO_ACCOUNT_SID=
set TWILIO_AUTH_TOKEN=
set IPAPI_KEY=
Then run your environment.bat
file and start the application:
environment.bat
npm start
At a high-level, the webapp is a single function (State, Event) -> (State, HTML Event) that is run whenever an event is
dispatched (usually caused by user input). This update function lives in app.js
.
The library raj
is used to run this loop, and
lighterhtml
is used to construct the HTML.
The update function in app.js
is the only update function run, but its
composed of smaller update functions in models/
to keep the file manageable.
views/
contains view functions.models/
contains update functions which take the current event and state and produce a new state and effects.effects/
contains effect functions shared by different update functions. This can be lazy-loaded to reduce bundle size.
The app is started in browser.js
or server.js
in the browser and on the server. This is where initial state
and events are declared.
The update function receives the current state and event, and returns a new state and any effects that produce
more events asynchronously. It lives in app.js
.
The update function takes two arguments event
and state
, and returns an array [newState, effect] which has the new
state and an effect that might produce more events asynchronously (fetching data over the network, for example).
The reason it returns an array is for easy destructuring.
Effects are functions which take the dispatch function as the argument, and dispatch new events after performing some side effect.
const effect = (dispatch) => {
someAsyncFunction(() => {
dispatch({ type: 'eventName', data: { some: 'event data' }, otherData: { some: 'other event data' } })
})
}
Events are objects which must have a type
property with the event name to distinguish them from other events,
and can include any other properties used by the update function.
Views are functions that take two arguments state
and dispatch
, and return HTML.
const { html } = require('../helpers')
const view = (state, dispatch) => {
return html`
<div onclick=${(event) => dispatch({ type: 'someClickEvent', event })}>Hello, World</div>
`
}
This helper can be used for submit and change form events. It will deal with parsing the form values and merging them into the event object before dispatching.
To debug the application, enable
debug output by setting the
DEBUG=demspace:*
environment variable or localStorage.setItem('debug', 'demspace:*')
in the
browser. Every event and associated state change will be logged to the console.