Contents
- FAQ
- Create your Ðapp
- Start your Ðapp
- Add Ðapp styles
- Using ethereum packages
- Ðapp code structure
- Bundle your Ðapp
- Submit your Ðapp
This tutorial will show you how to setup a Meteor app to be used as a Ðapp and probably answer a few questions on why Meteor should be used.
- Create your Ðapp
- Start your Ðapp
- Connect your Ðapp
- Run your Ðapp
- Add Ðapp styles
- Using ethereum:elements
- Ðapp code structure
- Bundle your Ðapp
- Submit your Ðapp
True, Meteor is a full stack framework and its main improvement is realtime web applications, but Meteor is also the first framework (i know of), which fully embraced single page app (SPA) development and provided all necessary tools.
5 reasons why Meteor is a perfect fit:
- Its purely written in JS and has all the tools a SPA needs (Templating engine, Model, on-the-fly compiling, bundling)
- You get a development environment, which has live reload, CSS injection and support for many pre-compilers (LESS, Coffeescript, etc) out of the box
- You can get all frontend code as single
index.html
with onejs
andcss
file plus your assets, using meteor-build-client. You can then host it everywhere or simple run theindex.html
itself or distribute it later on swarm. - It embraces full reactivity, which make building consistent interface much easier (similar to angular.js
$scope
or binding) - It has a great model called Minimongo, which gives you a mongoDB like interface for a reactive in-memory database, which can also be auto-persisted to localstorage or indexedDB
No, using meteor-build-client you can get all the static assets of your Ðapp to run without a server, though if you use a router like iron- or flow-router, you need to use hash (index.html#!/mypath
) routes instead of clean HTML5 pushstate routes.
Install Meteor if don't have already:
$ curl https://install.meteor.com/ | sh
Then create an app:
$ meteor create myDapp
$ cd myDapp
Next add the web3 package:
$ meteor add ethereum:web3
I recommend also to add the following packages:
- ethereum:dapp-styles - The LESS/CSS framework which gives your dapp a nice Mist-consistent look.
- ethereum:tools - This package gives you the
EthTools
object with a set of formatting an conversion functions and template helpers for ether. - ethereum:elements - A set of interface elements specifically made for ethereum.
- ethereum:accounts - Gives you the reactive
EthAccounts
collection with all current available ethereum accounts, where balances will be automatically updated. - ethereum:blocks - Gives you the reactive
EthBlocks
collection with the latest 50 blocks. To get the lastest block useEthBlocks.latest
(It will also have the latest default gasPrice) - frozeman:template-var - Gives you the
TemplateVar
object, that allows you to set reactive variables, which are template instance specific. See the readme for more. - frozeman:persistent-minimongo2 - Allows you to auto persist your minimongo collection in local storage
Meteor doesn't force you to have a specific folder structure, though some folders have specific meaning and will be treated differently when bundling/running your application.
Folders with specific treatment
client
- files in a folder calledclient
will only be loaded by the client part of your app and as we are building a Ðapp, that's where most of our files go.lib
- files in folders calledlib
will load before other files in the same folder. This is an ideal place your init files, libraries, or ethereum specific files.public
- a folder calledpublic
contains assets meteor will make available on the root of your webserver (or later bundled Ðapp)- There are a few more specific folders like
server
,tests
,packages
, etc. If you want to get to know them take a look at the Meteor docs
So to build a Ðapp we ideally create the following folder structure in our myDapp
folder:
- myDapp
- client
- lib
- myDapp.html
- myDapp.js
- myDapp.css
- public
Note The community provides also Meteor Ðapp Boilerplates like this one from Nick Dodson: https://github.com/SilentCicero/meteor-dapp-boilerplate
To connect our dapp we need to start geth
with the right CORS headers in another terminal:
$ geth --rpc --rpccorsdomain "http://localhost:3000"
We also need to set the provider. Ideally we create a file in our lib folder called init.js
and add the following line:
if(typeof web3 === 'undefined')
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
Now we can run our Ðapp by simply running:
$ meteor
If we go to http://localhost:3000
, we should see a website appear and if we open the browser console we can use the web3 object to query the geth node:
> web3.eth.accounts
['0xfff2b43a7433ddf50bb82227ed519cd6b142d382']
If you want your Ðapp to nicely fit later into Mist and have follow the official look use the dapp-styles css css/less framework.
Note that they are under heavy development and the class names and elements may change.
To add it simple add the following packages to your Ðapp:
$ meteor add less
$ meteor add ethereum:dapp-styles
Now rename you myDapp.css
to myDapp.less
and add the following line inside:
// libs
@import '{ethereum:dapp-styles}/dapp-styles.less';
Now you can use all dapp-styles classes and also overwrite all variables of the framework. You can find them in the repo. Overwrite them by copying them to your myDapp.less
file and set different values.
To make your life as a Ðapp developer easier we provide some packages that help you build Ðapps faster.
If you add the recommended packages above you should have the ethereum:tools, ethereum:accounts and ethereum:blocks packages available.
These 3 packages give you the EthTools
, EthAccounts
and Ethblocks
objects, which give you formatter functions, a collection with the accounts from web3.eth.accounts
(with auto updated balance) and a collection of the last 50 blocks.
Most of these functions are reactive so they should make building interfaces a breeze.
If you look into you myDapp.html
you will find the hello
template.
Just add a helper called {{currentBlock}}
some where between the <template name="hello">..</template>
tags.
Now open the myDapp.js
and add after the counter() {..}
the currentBlock
helper:
Template.elements.helpers({
counter() {
...
},
currentBlock() {
return EthBlocks.latest.number;
}
});
Then initialize EthBlocks by adding EthBlocks.init();
after this.counter = new ReactiveVar(0);
If you now check your Ðapp in the browser you should see the latest block number, which will increase once you mine.
For more examples please checkout the packages readmes and the demo (source) for more.
This tutorial won't go into building apps with Meteor. For this please refer to the Meteor's tutorials, A list of good resources, EventMinded (payed tutorials) or books like Building Single-page Web Apps with Meteor or Discover Meteor.
TODO Short:
- put ethereum related stuff into
client/lib/ethereum/somefile.js
- use
myCollection.observe({added: func, changed: func, removed: func})
to communicate to ethereum, keep ethereum logic out of your app as much as possible. This way you just write and read from your reactive collections and the observe functions will handle the rest (e.g. sendTransactions) - Filters etc will add logs etc to your collections. So you keep all the callback mess out of your app logic.
For an example see the Ethereum-Wallet.
To bundle your Ðapp into a local standalone file use meteor-build-client:
$ npm install -g meteor-build-client
$ cd myDapp
$ meteor-build-client ../build --path ""
This will put your Ðapps static files into the build folder, above your myDapp
folder.
The last option --path
will make the linking of all files relative, allowing you to start the app by simply clicking the build/index.html
.
Be aware that when running your app on the file://
protocol, you won't be able to use client side routing, due to web security. Later in mist you will be able to use client side routing, as dapps are served over the eth://
protocol.
In the future you will be able to simply upload your Ðapp on swarm.
To get early traffic to your Ðapp, you can submit your Ðapp to Dapp Insight. This is a most popular Dapp analytics tool which listing all the running Dapps in the world.