2021-11-03

Business Model Canvas

The Business Model Canvas (BMC) is a useful tool that can help you to characterize a particular Business Model. Designed by Alexander Osterwalder in the mid-2000, it's considered one of the most effective management and entrepreneurial tool.

This repository provides a well-designed Business Model Canvas. It's also rather easy to use and to install on a local machine, and therefore I strongly recommend it. However, in my opinion, this project has also two important limitations:

  1. Contents cannot be easily saved since it uses the browser's local storage.
  2. Print to PDF can be done only on portrait mode.

It is feasible to repurpose the CSS styling from this project for an HTML-Business Model Canvas, created based on a Jupyter Notebook.

VIM and IPYNB format

Again, here I can use jupytext that allows me to edit an IPYNB file with VIM. The starting notebook has a set of predefined cells for each block of the BMC. Markdown formatted text can be used to fill each section of the canvas, as the figure below shows.

A makefile automates the process that produces an HTML version of the canvas.

pdf: BMC.html
     make html

html:
     jupyter nbconvert  --to html ./BMC.ipynb   --template ./bmc.tpl

with the following template, derived from the index.html of the previous repository.

{%- extends 'basic.tpl' -%}

{% block any_cell %}

{% if 'DF'  in cell['metadata'].get('BM', []) %}
<div id="for" style="display:none">
{{super()}}
</div>
{% endif %}        

{% if '1'  in cell['metadata'].get('BM', []) %}
<div id="kp" style="display:none">
{{super()}}
</div>
{% endif %}        

{% if '2'  in cell['metadata'].get('BM', []) %} 

<div id="ka" style="display:none">
{{super()}}
</div>
{% endif %}        
{% if '3'  in cell['metadata'].get('BM', []) %} 
<div id="kr" style="display:none">
{{super()}}
</div>

{% endif %}                   
{% if '4'  in cell['metadata'].get('BM', []) %} 
<div id="vp" style="display:none">
{{super()}}
</div>


{% endif %}        
{% if '5'  in cell['metadata'].get('BM', []) %} 

<div id="cr" style="display:none">
{{super()}}
</div>


{% endif %}  
{% if '6'  in cell['metadata'].get('BM', []) %} 
<div id="ch" style="display:none">
{{super()}}
</div>



{% endif %}    
{% if '7'  in cell['metadata'].get('BM', []) %} 

<div id="cs" style="display:none">
{{super()}}
</div>


{% endif %}          
{% if '8'  in cell['metadata'].get('BM', []) %} 
{% set co = super() %}

<div id="co" style="display:none">
{{super()}}
</div>

{% endif %}  
{% if '9'  in cell['metadata'].get('BM', []) %} 


<div id="rs" style="display:none">
{{super()}}
</div>
{% endif %}  


{% if 'output'  in cell['metadata'].get('BM', []) %} 
        <div class="row">
          <div class="col-lg-9 pt-2">
            <h1 class="h4">Business Model Canvas</h1>
           </div>
        </div>
        <div class="row">
          <div class="col-md-6 col-lg-3">
              <label>Designed For</label>
                <span id="for_"><span> 
          </div>
          <div class="col-md-6 col-lg-3">
              <label>Designed By</label>
          </div>
          <div class="col-md-6 col-lg-3">
              <label>Date</label>
               <span id="ndate"></span>
          </div>
          <div class="col-md-6 col-lg-3">
              <label>Version</label>
          </div>
        </div>
        <div class="row">
          <div class="col-md-2 col-lg-2 mb-4">
            <div class="card firstrow">
              <div class="card-body">
                <h5 class="card-title">Key Partners</h5>
            <div class="cont" id="kp_">
            </div>
              </div>
            </div>
          </div>
          <div class="col-md-3">
            <div class="row">
              <div class="col-12 mb-4">
                <div class="card firstrow">
                  <div class="card-body">
                    <h5 class="card-title">Key Activities</h5>
                    <div class="cont"  id="ka_">
                </div>
                  </div>
                </div>
              </div>
              <div class="col-12 mb-4">
                <div class="card firstrow">
                  <div class="card-body">
                    <h5 class="card-title">Key Resources</h5>

                <div class="cont"  id="kr_">
                </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="col-md-2 mb-4">
            <div class="card firstrow">
              <div class="card-body">
                <h5 class="card-title">Value Propositions</h5>
            <div class="cont"  id="vp_">
            </div>
              </div>
            </div>
          </div>
          <div class="col-md-3">
            <div class="row">
              <div class="col-12 mb-4">
                <div class="card firstrow">
                  <div class="card-body">
                    <h5 class="card-title">Customer Relationships</h5>
                   <div class="cont"  id="cr_">
                    </div>
                  </div>
                </div>
              </div>
              <div class="col-12 mb-4">
                <div class="card firstrow">
                  <div class="card-body">
                    <h5 class="card-title">Channels</h5>

            <div class="cont"  id="ch_">
            </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="col-md-2 mb-4">
            <div class="card firstrow">
              <div class="card-body">
                <h5 class="card-title">Customer Segment</h5>
            <div class="cont"  id="cs_">
            </div>
              </div>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-lg-6 mb-4">
            <div class="card secondrow">
              <div class="card-body">
                <h5 class="card-title">Cost Structure</h5>
            <div class="cont"  id="co_">
            </div>
              </div>
            </div>
          </div>
          <div class="col-lg-6 mb-4">
            <div class="card secondrow">
              <div class="card-body">
                <h5 class="card-title">Revenue Streams</h5>
                     <div class="cont"  id="rs_">
                     </div>
              </div>
            </div>
          </div>
        </div>
        <footer>
          <div class="container-fluid" style="padding:2rem;">
            <div class="row">
              <div class="col-lg-12 text-center">
                <p class="d-print-none">
                  <strong>Notes:</strong> 
                </p>
                <p>
                  &copy;2021
                  <a href="">@seve_py</a>
                </p>
              </div>
            </div>
          </div>
        </footer>
{% endif %}  
      
{% endblock any_cell %}

A final step is required to add style to the raw HTML created by pandoc.


#!/usr/bin/env python
from jinja2 import Template
if __name__ == "__main__":


    with open("./BMC.html") as bcm:
        bcmhtml = bcm.read()
    # pdb.set_trace()
    body= bcmhtml
    tpl ="""
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>Business Model Canvas</title>
    </head>
    <body style="display:none">
    <div class="container-fluid">
    {{ body }}
    </div>

    <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>

    <link
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="./styles.css" />

<style>
$color: rgb(255,215,7);
$colorDark: darken($color, 10%) transparent;
@media print{@page {size:A3 landscape}}
@page {
  size: A3 landscape;
}
</style>
<script>
 $(window).load(function() {


      var autoExpand = function(field) {
        field.style.height = 'inherit'
        var computed = window.getComputedStyle(field)
        var height =
          parseInt(computed.getPropertyValue('border-top-width'), 10) +
          parseInt(computed.getPropertyValue('padding-top'), 10) +
          field.scrollHeight +
          parseInt(computed.getPropertyValue('padding-bottom'), 10) +
          parseInt(computed.getPropertyValue('border-bottom-width'), 10)
        field.style.height = height + 'px'
      }

      document.addEventListener(
        'input',
        function(event) {
          if (event.target.tagName.toLowerCase() !== 'textarea') return
          autoExpand(event.target)
        },
        false
      )

$( "#kp_" ).html( $('#kp').html());
$( "#ka_" ).html( $('#ka').html());
$( "#kr_" ).html( $('#kr').html());
$( "#vp_" ).html( $('#vp').html());
$( "#cr_" ).html( $('#cr').html());
$( "#ch_" ).html( $('#ch').html());
$( "#cs_" ).html( $('#cs').html());
$( "#co_" ).html( $('#co').html());
$( "#rs_" ).html( $('#rs').html());
$( "#for_" ).html( $('#for').html());
   var tdate = new Date();
   var dd = tdate.getDate(); //yields day
   var MM = tdate.getMonth(); //yields month
   var yyyy = tdate.getFullYear(); //yields year
   var currentDate= yyyy + "-" + dd + "-" +( MM+1) ;
$("#ndate").text(currentDate)
})
$( document ).ready(function() {
  $("body").show()
});
</script>

    </body>
    </html>
    """

    T=Template(tpl)
    with open("./BMC.html","w") as bcm:
        bcm.write(T.render(body=body))

Printing to PDF from any browser will produce a PDF version. Here's an example.