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:
- Contents cannot be easily saved since it uses the browser's local storage.
- 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>
©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.