Jump to content
eelkenet

Into Nature (Ember.js + Processwire)

Recommended Posts

I have just delivered this website: Into Nature (Dutch only), about an 'Art expedition' through the province of Drenthe, in The Netherlands. I built the site for Vandejong.

The site is made using two distinct parts/techniques: Processwire for the back-end (through a RESTful json api) and the front-end is built on Ember.js. This is my third large site built this way, and the first I am completely happy about. 

A page called 'API' is the main interface between the two: it uses urlSegments and parses the content from the PW pages into Ember-friendly JSON data. As Ember is very strict (heavily based on the Convention over Configuration concept), and Processwire is extremely versatile, the way Ember requires its data dictates the way I shaped the API. Both @clsource's REST-helper and ProCache are used to format and cache the API responses, making the API very responsive. 

Something that was initially hard to wrap my head around was how to deal with the site's routing/pagetree. While Google now indexes modern 'single-page' web applications, for instance Facebook still scrapes their opengraph from the raw HTML pages. I dealt with this by giving the Ember app and the PW page-tree use the exact same routes / pages. Every Processwire page is a valid starting point for the Ember app, while also including the scrapeable meta tags belonging to that exact URL. As a result, the whole thing is nicely CURL-able and bot-friendly.

  • Like 15

Share this post


Link to post
Share on other sites

It's a very nice website indeed.

I just had an issue while viewing the site from my mobile phone (Chrome on Android): there appears to be no background on the navigation, so it is very hard to read depending on the scroll position. I would suggest to add some kind of background color to make the navigation links more visible.

  • Like 1

Share this post


Link to post
Share on other sites

I just had an issue while viewing the site from my mobile phone (Chrome on Android): there appears to be no background on the navigation, so it is very hard to read depending on the scroll position. I would suggest to add some kind of background color to make the navigation links more visible.

Thanks for the notice, not sure how that one sneaked in there, fixed that.

Share this post


Link to post
Share on other sites

Very nice work!

Could you tell us something about the map? Are you using geojson for the routes/polylines?

Share this post


Link to post
Share on other sites

Thanks @Mats! The map tiles are designed in Mapbox, the map itself is built on Leaflet.js, using the great Ember Leaflet addon. 

Once you get the hang of Ember.js (quite a steep learning curve) and it all starts making sense, it becomes really logical and fast to build upon.

Because it is so strict, you can predict how components and external addons will work, and how to separate your functions. All using the same philosophy. As a result, it's peanuts to toggle markers and other layers on the map that relate to other items in the application.

Let me illustrate how easy it is.

The polylines are added by adding a Polyline-layer, which is part of the Ember Leaflet addon. It requires 'locations': an array of lat/lng points.

The stripped down version of it works like this:

1. From the API we get, for instance, this JSON for the Hoofdroute (main route) -> http://www.intonature.net/api/routes/hoofdroute

2. Through the default Ember Data Rest adapter this JSON gets loaded into the route*  model:

// models/route.js
import DS from 'ember-data';
export default DS.Model.extend({
  title: DS.attr("string"),
  points: DS.attr("array"), 
  color: DS.attr("string"),
});

3. After the model promise is fulfilled, it renders the Template belonging to the Route*, often with help from an Controller to 'decorate' the data.

If that made no sense, you can also read that previous sentence like this: Through the magic of Ember this ends up at the Map Component which is inserted into the Explore template. The stripped down version of the Explore template:

{{!-- templates/explore.hbs --}}
 
   {{map-component
      locations=locations
      currentItem=currentItem
      currentPreviewItem=currentPreviewItem
      routes=routes
    }}

4.And then inside the map component we get the following: 

{{!-- components/map-component.hbs --}}

{{#leaflet-map id='explore-map'}}

  {{tile-layer url=tileLayer}}

  {{#each routes as |route|}}
    {{#if route.points}}
      {{#polyline-layer
        locations=route.points
        color=route.color
      }}
        <span class="route-label">{{route.title}}</span>
      {{/polyline-layer}}
    {{/if}}
   {{/each}}

{{/leaflet-map}}  

And that is essentially it. We load the /explore route*, which loads data from the server and puts it into a model, then renders its template. This template contains a component which draws polylines on top of a tile layer.

My previous large map-oriented / PW- & RequireJS powered project took overall about 300 hours to develop. In large because I had to invent the wheel, discover fire, and then deal with burning wheels everywhere. In short: I was missing a strict, well defined idea of which part is responsible for which function, something that happens to a lot of developers I have noticed. That, combined with the incredible shitty documentation of the non-standard Google Maps stuff and some other setbacks made it quite a tedious project. (The resulting site is still quite nice though: http://www.vangoghroute.nl )

Developing Into Nature took me around 90 hours, of which maybe half map-related. I still had to figure out a lot, yet I don't think I'll quickly return to the old world of "Php-generated html with bits of Javascript here and there and oh let's throw some more Ajax at it shall we?"

Let me clarify: We are dealing with 2 kinds of routes here. First of all the "Into Nature art routes", and then there are the 'Ember Routes'. 

Ember Routes are the urls of the app, and responsible for getting data and injecting that data into models. 

Edited by eelkenet
  • Like 5

Share this post


Link to post
Share on other sites

Thanks for your detailed answer! Very impressive stuff. 

The vangoghroute.nl site is very nice too.

  • Like 2

Share this post


Link to post
Share on other sites

Developing Into Nature took me around 90 hours, of which maybe half map-related. I still had to figure out a lot, yet I don't think I'll quickly return to the old world of "Php-generated html with bits of Javascript here and there and oh let's throw some more Ajax at it shall we?"

Would you go with this approach for a standard content type site?  I really like the idea of decoupling the content store and the rendering - it opens up lots of opportunities.  I can see that you can get the meta tags available to search engines, but what about the content?  Do you have a noscript option on the processwire routes that dumps out an HTML version of the page, or do you rely on Google's best effort indexing of javascript pages?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By VeiJari
      Hello forum, we're trying to use Processwire as our REST-API. We are having problems with our API login to Processwire from frontend. It gives us 403 error.
      We have installed ProcessWire to subdirectory (/api/*) and our frontend is static JS files at root ( / ). Apache access logs gives 404 to our POST-request, but browser devtools shows 403 for our POST /api/login request. 
      Processwire backend panel works. We also have a GET endpoint for the API that returns 200 with correct payload.  So we're wondering why does our GET works but POST doesn't?
      Does this have something to do with Processwire .htaccess, or is this because of our webhost? What should we check first? Any help would be appreciated.
    • By rjgamer
      Hi,
      is there a hook after the current (active) page got created? Or which method got called in the Page class after the Constructor of the current page got initialized?
      Thanks.
       
    • By killedfriendz
      I am very sorry for asking this but i totally do not understand how to set values of checbox using API. 
      I have checbox field on my page with name "order_status". 
      So i've tried few ways to make it checked but it still doesn't work:
       
      $userPage->order_status->value = 1; $userPage->order_status->add(1); $userPage->order_status->add(true); Could you please tell me how to do it?
    • By rjgamer
      Hi guys,
      the field "redirect_last" of type DateTime got not updated. The update on the field "redirect_counter" works and got saved.
      Does anybody know what I did wrong in my code?
      if ($input->urlSegment(1) === 'redirect') { $page->of(false); $page->redirect_last = time(); $page->redirect_counter += 1; if ($page->save('redirect_counter')) { $session->redirect($page->website_url, 302); } } Thanks.
    • By totoff
      Dear all,
      I'm upgrading an older side with the new custom fields for images feature as of 3.0.142. My image field is set to "Automatic" and holds a bunch of images together with their respective description on each page. New custom fields include "caption" among others and to make my live easier I I'm trying to populate "caption" with the value from the (default) description field. But unfortunately I can't seem to find out how to save the newly set values. This is my code:
      <?php foreach (page()->images as $image) { $image->set('caption', $image->description); bd($image->caption); echo files()->render("markup/views/view-card-image-fancybox.php", array('image'=>$image)); } ?> <?php $page->save(); bd($page->save()); ?> This sets the value as intended (see screenshot) but doesn't save it permanently to the database. What am I doing wrong?
      Thanks!
       

×
×
  • Create New...