Trove Marketplace - My first Meteor website


#1

http://trovemarketplace.meteor.com/


So this is my very first Meteor website. One that I’ve built myself without any sort of step by step tutorial. Just common sense and falling back to my Rails/C# knowledge.

It’s a marketplace for people who play Trove (a minecraft like game mixed with WoW). I chose Meteor because it’s awesome, and because it’s reactivity is the best out there.

If I can bother you guys, I would love some feedback on the source code.

  • Any glaring newbie mistakes?
  • Improvements that can be made to improve maintainability?
  • Any other stuff?

I really appreciate your help. @arunoda’s FlowRouter + BlazeLayout helped me grok publications/subscriptions in Meteor, so thanks again for that man!


#2

This is great! Thanks for open-sourcing this, it’s great to have real examples to point new members to. cc @joshowens might like to see this for his open source examples list.


[quote="sergiotapia, post:1, topic:7808"] If I can bother you guys, I would love some feedback on the source code. [/quote]

Overall this look great! I didn’t look super hard but I didn’t see any glaring errors :thumbsup:

Here are some suggestions (mostly subjective)

1.
The meteor methods won’t retain the latency compensation if there isn’t a copy on the client. I usually throw these in a both/models/ directory so the client can use it for a stub. If you want to hide the implementation you could just add a stripped down version on the client (called a stub). You can test this out by putting a Meteor._sleepForMs(2000) before returning the publication cursor.

I like that these are in meteor methods instead of calling update right in the event handler!

2.
Separating ‘pages’ templates into a pages folder helps me quickly jump to a page. This isn’t a big deal once you’re familiar with the codebase too.

3.

You can make your app more maintainable by abstracting away things that change a lot with things that change very little. This also tends to make it easy to test!

For example, if you make the views very dumb and have them just request data and just call an action that ‘something happened’, it makes it much easier to maintain the view layer. The UI changes a lot while business rules don’t change as much.

Here’s an example that’s held up really well with Blaze (making tons of changes to the Blonk UI)

Views call an action. The Actions are split up into domains and are the middle man. This is imperative (as opposed to flux) but it does let you see exactly what’s being mutated when a user does something (this is a common problem otherwise). You can follow that back to the ‘domain’ object which houses the data getters and the setters (handle action calls).

If you follow the flow by only making a change by calling an action things get easier to follow/debug. If you set a Session variable in an event handler, then it kind of defeats the purpose. Example:

View triggers event (can also pass payload)

Template.SomePage.events({
  'click .btn-logout'() {
    var id = Meteor.userId();
    AppActions.logoutUser(id);
  }
});

Actions call domains that are interested

AppActions = {
  logoutUser(userId) {
    // you could (should) also determine userId here so view does less
    AppDomain.onLogoutUser();
    ProgressDomain.onLogoutUser(userId);
    BarDomain.onLogoutUser(userId);
  }
};

Domains respond to calls made by action(s)

// general 'app' related stuff
AppDomain = {
  onLogoutUser(userId) {
    Meteor.logout();
    FlowRouter.go('LoginPage')
  }
};

ProgressDomain = {
  onLogoutUser(userId) {
    // in real life a reactive-dict works better...
    Session.set('progress:user:'+userId, null);
  }
};

anyhow your app codebase looks great! keep up the good work!

#3

I look at your code especially on the " /my-items route ". I wonder how would you show an items that pertains to a specific user since you did not pass a userId parameter.


#4

So notice that I subscribe to the collection in the router.

return this.register('itemsWithSkip', Meteor.subscribe('itemsWithSkip', offset, limit));

Then in the template helper I further filter out records.

Template.myItems.helpers({
  items: function() {
    var items = Items.find({userId: Meteor.userId()}, { sort: { createdAt: -1 }})
    return items;
  }
});

I should create a publication with only the user’s items, but I haven’t gotten around to it yet.


#5

Thanks for the suggestions @SkinnyGeek1010 - that sounds nice and familiar. I used to do things this way in the C# world (many moons ago). Where would I create this AppActions collection? In the /lib folder so it runs on both client and server?


#6

I strongly suggest to filter it during publication on this specific route since user does not need the other data and perhaps improve latency.


#7

Yep, it’s on the list. :thumbsup:


#8

I place them in /both/actions/ or if you know you won’t need serverside rendering in the future you can put them in 'client/actions/`. Conveniently the folder starts with ‘A’ so it’s loaded first (typically).

Here’s an example (it’s in React with no flux but it’s the same exact code for Blaze too)

My typical folder tree looks like this:

both
   actions
   components
   domains
   models
      post.js (met methods)
      user.js
   pages
   services (business logic)
      onboardUser.js (register, send emails, etc)
client
   lib
   styles
   ...
server
   lib
      ddp_connections.js (connect to other meteor servers)
   methods
     mailer.js (send emails)
   ...
   

If the app is larger i’ll spit up the actions/domains into sections, otherwise on small apps i’ll put most into a generic ‘app actions/domain’. For larger apps think about Spotify, it might have a ControlsDomain, PlaylistDomain, HeaderDomain, FollowersDomain… these are separate areas of the app. I try to not split out until one section become too big.

You may also want to refactor the subscriptions into the template level. FlowRouter 2 allows this but FlowRouter 3 won’t support it (as far as I know). @arunoda is also in the same camp with moving the subscriptions to templates unless you need FastRender support today. In general this is more maintainable and allows you to have more fine grained control on what that template ‘group’ needs for it’s data.

This is a great article by @sacha on how to do this:
https://www.discovermeteor.com/blog/template-level-subscriptions


#9