(not the author, but I'm an Urbit core developer, so I can read this pretty easily)
You're pretty much correct. lib/server.hoon doesn't "set up" the server exactly, that's built into Urbit. In general, apps communicate by sending commands ("poke") and subscribing to data ("watch"). A normal HTTP request is just a poke of type "handle-http-request". The js frontend can also subscribe to your app.
lib/server.hoon is a (mostly standard) library of helper functions that mostly convert from various internal types to HTTP responses, so they add the the HTTP response code, mimetype, octet-stream length, etc. There's also a function that wraps an HTTP response handler to redirect to the login page if they're not logged in. Most apps that have a web interface use these functions, though I think the author may have added a few more filetypes.
app/canvas.hoon, as you guessed, manages the main state of the app and syncs it to other urbits. An app's commands can be seen in +on-poke, which in this case calls +handle-canvas-action, where you can see all the different commands this app takes. For example, %join subscribes to the "canvas" app on another urbit on path /canvas/foo where "foo" is the name of the image. The rest of the commands can be traced in the same away. +process-remote-paint is the part that actually processes a new list of strokes from either another ship or the %paint poke; it updates its own state and gives updates on /canvas/foo.
app/canvas-view.hoon is the app that serves the html/cs/jss and handles browser requests. It has a similar set of pokes, and most of them are just forwarded to app/canvas.hoon, but some of them are handled directly. This is a different app from canvas.hoon to keep separate the essential logic of the app from the work needed to serve it to a browser. One could imagine writing a command-line app which used canvas.hoon, and it wouldn't need to talk to canvas-view.hoon.
You're pretty much correct. lib/server.hoon doesn't "set up" the server exactly, that's built into Urbit. In general, apps communicate by sending commands ("poke") and subscribing to data ("watch"). A normal HTTP request is just a poke of type "handle-http-request". The js frontend can also subscribe to your app.
lib/server.hoon is a (mostly standard) library of helper functions that mostly convert from various internal types to HTTP responses, so they add the the HTTP response code, mimetype, octet-stream length, etc. There's also a function that wraps an HTTP response handler to redirect to the login page if they're not logged in. Most apps that have a web interface use these functions, though I think the author may have added a few more filetypes.
app/canvas.hoon, as you guessed, manages the main state of the app and syncs it to other urbits. An app's commands can be seen in +on-poke, which in this case calls +handle-canvas-action, where you can see all the different commands this app takes. For example, %join subscribes to the "canvas" app on another urbit on path /canvas/foo where "foo" is the name of the image. The rest of the commands can be traced in the same away. +process-remote-paint is the part that actually processes a new list of strokes from either another ship or the %paint poke; it updates its own state and gives updates on /canvas/foo.
app/canvas-view.hoon is the app that serves the html/cs/jss and handles browser requests. It has a similar set of pokes, and most of them are just forwarded to app/canvas.hoon, but some of them are handled directly. This is a different app from canvas.hoon to keep separate the essential logic of the app from the work needed to serve it to a browser. One could imagine writing a command-line app which used canvas.hoon, and it wouldn't need to talk to canvas-view.hoon.