After lots of trial and errors, I managed to make sagemath work under Jupyterhub. One cause of constant confusion was that these jsmol, threejs, mathjax are served at /nbextensions. These are not proper nbextensions in Jupyter notebook ecosystem, but just static files. I suppose the proper place to serve them is /static, like /static/jsmol, ....
Fortunately we can use a Jupyter notebook option to serve /static from arbitrary directory that contains jsmol, threejs, and mathjax:
c.NotebookApp.extra_static_paths = ["/path/to/extra/static/files"]
I guess that with some changes mainly replacing "/nbextensions" to "/static", sage 3d and interact outputs all would work fine.
Jupyterhub serves static files at /hub/static, so it would be necessary to forward(alias) /static to /hub/static for sage 3d and interact outputs to work.