Building CampaignHawk: File Structure and Packages (Part 2)

Sam Corcos
4 min readSep 2, 2015

--

We went over the project scope and the wireframing process in the first part. So now that we have the basic idea of what the app should look like, we need to actually put that into code.

My preferred method is to start by building out the user interface (UI), then connect all the internals. For a project like this where the UI is a big part of the project, I’ll probably spend the majority of my time making the interface clean and user friendly.

And depending on how well-defined the project is, it might also make sense to write some end-to-end tests using Cucumber in advance. I know a lot of people like test driven development (TDD), but I’ve always found it more of a hinderance. It’s nothing personal.

Step 1: Directories and Files

First create the Meteor project:

$ meteor create campaign-hawk
$ cd campaign-hawk

Then set up the basic file structure. Meteor is not very opinionated on file structure, which gives us a lot of flexibility. I’m going to use the following file structure to get started:

├── client
│ ├── components
│ │ ├── App.jsx
│ │ ├── AppLoading.jsx
│ │ ├── AppNotFound.jsx
│ │ ├── Map.jsx
│ │ ├── Login.jsx
│ │ └── Settings.jsx
│ ├── router.jsx
│ ├── index.html
│ └── styles
│ └── styles.scss
├── lib
│ └── collections.js
└── server
│ └── server.jsx
└── scss.json

These can be added manually or with the following command:

$ mkdir client client/components client/styles
$ mkdir lib
$ mkdir server
$ touch client/components/App.jsx
$ touch client/components/AppLoading.jsx
$ touch client/components/AppNotFound.jsx
$ touch client/components/Map.jsx
$ touch client/components/Login.jsx
$ touch client/components/Settings.jsx
$ touch client/router.jsx
$ touch client/index.html
$ touch client/styles/styles.scss
$ touch lib/collections.js
$ touch server/server.jsx
$ touch scss.json

Then trash the template files:

$ trash campaign-hawk.*

If you don’t have trash, I recommend getting it. You can add it with $ brew install trash. If you don’t have Homebrew, you should get it already.

Step 2: Packages

I’m starting this just before Meteor 1.2 comes out, which is not ideal. That said, the release candidate was just released publicly, and I have faith that it’s stable so I’m going to start by upgrading to 1.2. If you’re reading this in the future and 1.2 has already been released, please let me know so I can change this part of the process.

$ meteor update --release METEOR@1.2-rc.7

A few other packages we’re going to need:

meteor add fourseven:scss
meteor add react
meteor add reactrouter:react-router

I’m also going to add the following to the scss.json file to enable auto-prefixing so we don’t have to deal with those annoying vendor prefixes:

{
"enableAutoprefixer": true,
"autoprefixerOptions": {
"browsers": ["> 5%"],
"cascade": false
}
}

That should work for now as far as packages go.

Step 3: Basic Template

Time to put together a few React components and get them to render properly. Within App.jsx:

App = React.createClass({
render() {
return (
<div>
{this.props.children}
</div>
)
}
})

Map.jsx:

Map = React.createClass({
render() {
return (
<h1>This is where the map goes</h1>
)
}
})

Login.jsx:

Login = React.createClass({
render() {
return (
<h1>This is where the login goes</h1>
)
}
})

Now that the components are set up, it’s time to set up the router within the router.jsx file:

const {
Router,
Route,
Redirect
} = ReactRouter;
const history = ReactRouter
.history
.useQueries(ReactRouter.history.createHistory)()
Meteor.startup(function() {
let AppRoutes = (
<Router history={history}>
<Route component={App}>
<Router component={Map} path="/" />
<Router component={Login} path="login" />
</Route>
</Router>
)
React.render(AppRoutes, document.body)
})

This gives access to the browser history and sets up a route to login. Access to login is not actually needed at this point, but it’s easier to set up the router now rather than later. At this point in the process, the app looks like the image below:

Next Steps

I need to decide on what mapping API I want to use. There’s always Google Maps, but there are some better options out there. I’ve used Mapbox in the past and I’ve had a good experience with them. There’s also CartoDB which seems to put more focus on data, and since this is a very data-intensive map application, they might be a good bet.

I’ll make a decision on mapping APIs later on in the process.

I also need to decide on a database. I’ve become a big fan of Neo4j and graph databases in general. That said, I don’t think the data I’m working with will be particularly relational, so sticking with Mongo might be easier.

I’m going to stick with Mongo for the time being, and if my queries start to get too complex and relational for Mongo, then I’ll switch over to Neo4j and the any-db package for Meteor.

--

--

Sam Corcos

Software developer, founder, author - CarDash - Learn Phoenix - SightlineMaps.com