In node.js I generally use a only three layers.
A simple layer that talks directly to the datasource. It's only job is efficiently extracting data from the source and writing to it. The datasource can be anything, a TCP endpoint, a HTTP endpoint, a database, a filesystem, etc.
The domain object layer. This is similar to your "M" in MVC. It's an object representation of a domain object. It has methods for construction, manipulation, validation and other logic.
Note that a single domain object can talk to several different objects from the data layer and that several views can transform a domain object.
The view takes a domain object and transforms in an easily printable way. For example, in the view layer I would convert a timestamp to a human readable string or do my i18n language conversion.
It also does any other view logic. Generally you have multiple view objects for a single domain object.
And of course it also converts data from the domain object into a format you want, whether it's binary, xml, json, html, some arbitary TCP protocol, plain text, csv, etc.
You generally also need some form of IO layer that talks to the other layers.
i.e. the IO layer
- unpacks input
- calls the correct domain object from either data or a domain object instance
- passes the data/domain instance through the view layer
- pipes the raw information returned from the view layer (html/json/binary/...) down the output
Now a single application has these three layers. If I had a dynamic website then I would have these three layers on the server and these three layers on the client.
If I had my own unique data source to talk to then that remote data source would also use these three layers, it would have it's own domain objects, it's own data layer on it's own data sources and it's own view layer which other services talk to when they use me as a data source.