{"componentChunkName":"component---src-templates-blog-post-js","path":"/jupyter_book_to_colab/","result":{"data":{"site":{"siteMetadata":{"title":"tigue.com"}},"markdownRemark":{"id":"28d3f762-5427-58f4-9692-11a3b7d0aaa6","excerpt":"Like any developer with a blog, I occasionally talk about blog\ntooling. Sorry. I just went through ye olde blog overhaul for the\nfirst time in years, so the…","html":"<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 800px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d61d46c29725f1c0d1a8bb6dfbaf9ca1/11d19/jupyter_book_to_colab.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAC4jAAAuIwF4pT92AAABbElEQVQoz41STUvDQBDt/xIRvHgSvIgYv2q19KBCoR5bUOvJD1rryZMKXj0IYtWU5lBEwZQguRgFFbUIofhRTWNMdp+b1DSNLbQDm9nszLx9M/sCYEYphestywIh9iK+804t0K6oMe7tCftYbLmeusk1QDdR0zRcikWIouh4vVp1zm3WHiip7Ztv9hi6BYdHWXB9XVga7kFoaABn5xctmdPvO+DjBDDugfcDgFT9DO152ZZaX8MUN4hoeBzz0Tmc8jl2mQlFUZBOp7Gzu8eyKiA3M6Bv+8BLHChvAw+Lf4DEm+EXa3c2EsYC14tIfzeSyWXIsuzECoUCEok4VlZT7O8V5HoatJIDHmPA8xZwG/MYuuwkSQI3MorQxBgmg0FsZDahqmq9TV3Xndd36rQr1ipj+FkEnjLAT7mZYalUwnE2i3xegCAI4HkehmE4MdM0G2bf5lH+S8ZixX6A1rKhddmYzbJppUM/QOfC/gWOE+kg+haK9AAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"jupyter book to colab\"\n        title=\"jupyter book to colab\"\n        src=\"/static/d61d46c29725f1c0d1a8bb6dfbaf9ca1/11d19/jupyter_book_to_colab.png\"\n        srcset=\"/static/d61d46c29725f1c0d1a8bb6dfbaf9ca1/1abb1/jupyter_book_to_colab.png 250w,\n/static/d61d46c29725f1c0d1a8bb6dfbaf9ca1/7217d/jupyter_book_to_colab.png 500w,\n/static/d61d46c29725f1c0d1a8bb6dfbaf9ca1/11d19/jupyter_book_to_colab.png 800w\"\n        sizes=\"(max-width: 800px) 100vw, 800px\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Like any developer with a blog, I occasionally talk about blog\ntooling. Sorry. I just went through ye olde blog overhaul for the\nfirst time in years, so the sensitive should stop reading now and the\nrest of you have been warned. Stick around for a short story about a\nsmall “good” hack for blogging about Jupyter notebooks.</p>\n<h2>Introduction</h2>\n<p>Static Site Generators (SSGs) have been around for a while and are the\nbee’s knees.  But now they are becoming the next generation markdown\nfiles – the front end explorable explanations to repos, which can\noptionally be wired up to kernel VMs for execution by the more curious\nreader.</p>\n<p>For this rebuild, I used two SSGs: Gatsby and Jupyter Book. The Gatsby\npart is just another story of a classic <a href=\"https://www.gatsbyjs.org/blog/2017-11-08-migrate-from-jekyll-to-gatsby/\">Jekyll to Gatsby\nmigration</a>\nso let’s not talk about it.</p>\n<p>The other part of the SSG story is about <a href=\"https://jupyterbook.org/intro\">Jupyter\nBook</a>, which is used in the rebuild to SSG\ngit repos that are full of Jupyter notebook *.ipynb files. This is the\npart of the story that is interesting because it is about emerging tech, to\nbe described herein.</p>\n<h2>The novelty</h2>\n<p>I’m only going to go over the truly novel bit, which as the title\nimplies is the integration of Jupyter Book and <a href=\"https://colab.research.google.com/\">Google’s\nColab</a>, their free Jupyter hosting\nservice. That is, Jupyter Book renders Jupyter notebook files\n(*.ipynb) for static hosting on tigue.com. Additionally, links into\nColab are made available to spin up a kernel VM for any reader wishing\nto execute a notebook they read on tigue.com.</p>\n<p>The contextual goal is a static site for a software developer. The\nsite’s front consists of a blog and set of projects. The latter\ninvolves a lot of Jupyter notebooks, which are static hostly on the\nstatic site as HTML snapshots of pre-run notebooks. Additionally,\nreader can easily execute the notebooks, without any admin hassles nor\ncosts for me, by clicking through to Google Colab.</p>\n<p>The “clicking through to Google Colab” hack is the novel bit. Jupyter\nBook usually clicks through to JupyterHub or Binder via the Interact\nbuttons on the top of the page, not to Colab. </p>\n<p>(Of course, if executing on Colab, it would be really helpful and more\ninteresting if those notebooks being clicked through to had been\npreviously tested to run on Colab; but that topic is out of the scope\nof this post.)</p>\n<h2>Context</h2>\n<p>I’ve been a long time believer in static site generators (SSGs). For\nthis blog rebuild, I’m using two SSG tools: Gatsby and Jupyter Book. I\nuse Gastby to SSG the blog, and I use Jupyter Book to SSG repos of\nnotebook which act as the demo/web presence for the code projects. The\nSSG notebooks have links into Google Colab if folks want to actually\nrun a given notebook on a VM, rather than just read a static notebook\nrendering.</p>\n<p>Gatsby was the obvious choice since I’ve been using React and GraphQL\nfor a while now. And Jupyter Book is simply the best in class for its\ntask (notebook SSGing). I can report that SSG tooling has come along\nnicely over the last few years.</p>\n<p>Jupyter Book generates the “static site” for a given git repo full of\nnotebooks (*.ipynb files). The static site will have pre-run notebook\nweb pages i.e. cell outputs will be included to demonstrate what the\nsoftware can do.</p>\n<p>Additionally if the reader wishes they can interact with the notebook:\na link in the Jupyter Book generated notebook pages will have a link\nto Colab which will grab the notebook clean from GitHub and provision\na virtual machine within which to run and interact with the notebook.</p>\n<p>Combined these two SSG tools enable a projects-and-blog web presence\nfor a developer to be run completely staticly, without involving say\nMedium for blog hosting and MSFT GitHub for notebook rendering, yet\ncode can also be run “dynamically” on Colab. It makes for a low hassle\nyet high functionality coder’s blog.</p>\n<h2>Interactivity for Jupyter Book</h2>\n<p>I want readers to be able to expeditiously run and interact with\nthe code in said notebooks statically hosted on tigue.com. And I don’t\nwant to manage that nor pay for the provioning of VMs, thank you very\nmuch. Google Colab fits the bill perfectly.</p>\n<p>Jupyter Book has a lot of nice functionality already. I don’t know of\na better equivalent. Nonetheless, for my React-based blog there is\nfunctionality overlap between Gatsby and Jupyter Book. E.g., the\nlatter uses Jekyll for static page generation, which the former is\nalso doing.</p>\n<p>Conceivably, much of Jupyter Book could be reproduced by\nGatsby. But Gatsby is JavaScript; that’s getting away from the Python\nworld so it’s unlikely in the short term. So for now: blog is Gastby\nbased and repo-of-notebooks is Jupyter Book based.</p>\n<h2>Linking Jupyter Book and Colab</h2>\n<p>So, with the context set, the solution boils down to a small hack of\nthe HTML templates in Jupyter Book. It’s not even really a hack, just\nan unexpected novel use, which good technologies enable.</p>\n<p>Jupyter Book already has a customization hook for providing a button\nuses can click to be taken to some site where JupyterHub (or Docker)\nis running. The code where the hook is used in in the\n<a href=\"https://github.com/jupyter/jupyter-book/blob/master/jupyter_book/book_template/_includes/buttons/jupyterhub.html#L9\">jupyterhub.html</a>\ntemplate. It’s a bit gruesome but the point is all the info needed\nto build the equivalent URL for Colab is there: site, repo, branch, etc.:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">{% capture interact_url_jupyterhub %}hub/user-redirect/git-pull?repo={{ site.binder_repo_base }}/{{ site.binder_repo_org }}/{{ site.binder_repo_name }}<span class=\"token entity\" title=\"&amp;\">&amp;amp;</span>branch={{ site.binder_repo_branch }}<span class=\"token entity\" title=\"&amp;\">&amp;amp;</span>subPath={{ page.interact_link | url_encode }}<span class=\"token entity\" title=\"&amp;\">&amp;amp;</span>app={{ hub_app }}{% endcapture %}\n{% capture interact_icon_jupyterhub %}{{ site.images_url | relative_url }}/logo_jupyterhub.svg{% endcapture %}\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>a</span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>{{ site.jupyterhub_url }}/{{ interact_url_jupyterhub }}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button-jupyterhub<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button-logo<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>{{ interact_icon_jupyterhub }}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>Interact<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>{{ site.jupyterhub_interact_text }}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>a</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>So, the “hack” is simply a modification of one of the HTML templates that are in the content repo, not part of the jupyter-book tool’s repo. So this is a good hack. Just change the above to:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">{% capture interact_url_jupyterhub %}{{ site.binder_repo_org }}/{{ site.binder_repo_name }}/blob/{{ site.binder_repo_branch }}/{{ page.interact_link }}{% endcapture %}\n{% capture interact_icon_jupyterhub %}https://colab.research.google.com/assets/colab-badge.svg{% endcapture %}\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>a</span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>{{ site.jupyterhub_url }}/github/{{ interact_url_jupyterhub }}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button-jupyterhub<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>interact-button-logo<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>{{ interact_icon_jupyterhub }}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>Interact<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>{{ site.jupyterhub_interact_text }}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>a</span><span class=\"token punctuation\">></span></span></code></pre></div>","frontmatter":{"title":"Jupyter Book to Colab","date":"January 07, 2020","description":"TODO: a discription for cover card"}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"slug":"/jupyter_book_to_colab/","previous":{"fields":{"slug":"/brightfield_challenge_data_manifest/"},"frontmatter":{"title":"Brightfield Challenge Dataset Manifest"}},"next":{"fields":{"slug":"/colormapping/"},"frontmatter":{"title":"Brightfield colormapping"}}}}}