Teachable Machine Boilerplate shows transfer learning and k-nearest neighbours in one browser file
Boilerplate code for Teachable Machine
At a glance
- What is it?
- Google's Teachable Machine Boilerplate is a small JavaScript project that trains a classifier live in the browser on webcam images, using a MobileNet activation as the feature extractor and a k-nearest-neighbour classifier on top. It is deliberately minimal, and it is the reference implementation behind Teachable Machine.
- Who is it for?
- Adopt Teachable Machine Boilerplate if you want to see transfer learning applied to a live webcam classifier in a file you can read in one sitting, because the two-stage idea, a pretrained MobileNet activation feeding a KNN classifier, is shown rather than described. Do not adopt it as a production dependency, because the pinned versions are old, with TensorFlow.js at 0.13.0 and the models at 0.2.2, and the build toolchain is a Babel 6 era browserify setup.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 135 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the boilerplate demonstrates
The repository is described as a small boilerplate project that demonstrates how to use tensorflow.js to create projects like Teachable Machine. The README says the code shows how you can create a KNN classifier that can be trained live in the browser on a webcam image, and that it is intentionally kept very simple so it can provide a starting point for new projects.
The simplicity is the point, and the README states it twice. There is one source file, main.js, plus an index.html, and the whole point is that a reader can see the complete pipeline rather than dig through a framework.
The primary language is JavaScript, the licence is Apache-2.0, the default branch is master, and the last push was on 2026-06-10. There are no GitHub releases, and the topics are boilerplate and deeplearnjs. The homepage is the project's own page at googlecreativelab.github.io/teachable-machine-boilerplate, which suggests the boilerplate is published as a site as well as a repository.
What makes it worth reading rather than skipping is the technique it demonstrates. Behind the scenes, the image from the webcam is being processed by an activation of MobileNet. This network is trained to recognize all sorts of classes from the imagenet dataset, and is optimized to be really small, making it useable in the browser. Instead of reading the prediction values from the MobileNet network, the code takes the second to last layer in the neural network and feeds it into a KNN classifier that allows you to train your own classes.
So the MobileNet network is used as a feature extractor and never as a classifier, and the classifier is a k-nearest-neighbour model over those features. The README says this is the benefit of using the MobileNet model instead of feeding the pixel values directly into the KNN classifier: you use the high level abstractions that the neural network has learned in order to recognize the Imagenet classes. This allows you with very few samples to train a classifier that can recognize things like smiles vs frown, or small movements in your body. The technique is called Transfer Learning.
That is the whole idea in three sentences, and it is the idea that makes Teachable Machine work with a handful of examples per class.
Running it: two commands and a webcam
Using the code takes two steps, and both are in the README.
Install the JavaScript dependencies:
npm installThen start the local budo web server:
npm startThat starts a web server on localhost:9966. The README tells you to try it and allow permission to your webcam, and to add some examples by holding down the buttons.
The holding-down detail is the whole user interface of the project. There are no form fields and no configuration. You point the camera at yourself, you hold a button to record examples into the class that button represents, you repeat for the other class, and then the classifier predicts which one is in front of the camera. The buttons are the training set.
The build script in package.json shows the machinery behind the second command. The start script runs budo with main.js as the entry, dist/build.js as the output, and the live and host flags, so budo is a development server with hot rebuild and an explicit host binding rather than the default localhost. The build script runs browserify on main.js into dist/build.js, and there is a pre-commit hook that runs build, so the bundle in dist/ is regenerated before any commit.
The dependency list is small and tells you what the implementation relies on. @tensorflow-models/knn-classifier and @tensorflow-models/mobilenet are the two model packages, both at 0.2.2. @tensorflow/tfjs is the runtime at 0.13.0. And @babel/polyfill is there for async function syntax on older browsers.
The browserify configuration in package.json shows the Babel setup, with babelify applying the es2015 preset and two plugins, syntax-async-functions and transform-regenerator. That is a Babel 6 era toolchain, with babel-core at 6.26.0 and babel-preset-es2015 alongside babel-preset-stage-0, and budo at 10.0.4 in the dev dependencies.
One small oddity in the manifest is worth noting: the license field is an empty string, even though the repository carries a LICENSE file and is described as Apache-2.0. The package name is also cl-teachable-machine-boilerplate, which suggests it was published to npm as part of a set of Creative Lab examples.
The four KNN calls and the two MobileNet calls that matter
The README includes a Quick Reference for the two model packages, and it is short enough to reproduce here because it is effectively the API surface of the project.
For the KNN classifier:
- `knnClassifier.create()`: Returns a KNNImageClassifier.
- `.addExample(example, classIndex)`: Adds an example to the specific class training set.
- `.clearClass(classIndex)`: Clears a specific class for training data.
- `.predictClass(image)`: Runs the prediction on the image, and returns an object with a top class index and confidence score.
The four calls map onto the four things the user does. Creating the classifier is the setup. addExample is the hold-the-button gesture, and it takes a class index so the example lands in the right training set. clearClass is the forget button for one class. And predictClass is the per-frame inference, returning a class index and a confidence.
For MobileNet:
- `.load()`: Loads and returns a model object.
- `.infer(image, endpoint)`: Get an intermediate activation or logit as Tensorflow.js tensors. Takes an image and the optional endpoint to predict through.
The second one carries the design. The endpoint argument is optional, and passing it is how you get the second to last layer rather than the final predictions. The README's description of infer, get an intermediate activation or logit, is exactly the operation the whole approach depends on, and the fact that the endpoint is a parameter rather than a separate model load is what keeps the boilerplate short.
Both packages link to their full implementations on the tensorflow.js models repository, so the boilerplate is a usage example rather than a fork, and the API you are reading is the API of the upstream packages.
The README also notes that Tensorflow has a built in model for doing this, the KNN Classifier, and that this boilerplate code shows how to easily use it. That is a useful framing for judging the project: it is a demonstration of a library, not a framework, and its value is in showing the four lines that turn a pretrained network into a live webcam classifier.
Where the boilerplate is the wrong starting point
Three limits, and the first is about the age of the stack.
The first is the versions. @tensorflow/tfjs is pinned at 0.13.0, the model packages at 0.2.2, babel-core at 6.26.0 and babel-preset-es2015 alongside babel-preset-stage-0. The TensorFlow.js API moved substantially after that era, in both the module structure and the model API, so code written against this boilerplate needs revisiting rather than copying when you start from a current release. The transform-regenerator and syntax-async-functions plugins are there to make async and await work in browsers of the time, which is a whole build layer that a current project would not carry.
The second is that the technique is a demonstration, not a system. The classifier is a KNN model, which means every training example is stored and every prediction is a nearest-neighbour search over that store. That is fine for a demo with a few dozen examples per class and it is exactly why the README says with very few samples. It is not what you want behind a product with thousands of examples per class, or with a latency budget, or with a memory budget on a browser tab.
The third is the model itself. MobileNet is used as a fixed feature extractor, and the README describes it as optimized to be really small, making it useable in the browser. The feature is a second-to-last-layer activation, which is a fixed-width vector per frame, and the classification decision is made by the KNN layer on top. The quality ceiling is therefore set by how well ImageNet abstractions generalise to your categories, and the README's own examples, smiles vs frown and small movements in your body, are the cases where that works. Fine-grained distinctions between similar categories, or categories unlike anything in ImageNet, are where it does not.
The alternative approach for a production classifier is to train a small model on your own data, either a transfer-learned MobileNet with a fresh classification head or a dedicated small architecture, and to serve it through a runtime you control. The difference in approach is that the boilerplate optimises for zero training and instant feedback in a browser tab, while the trained model optimises for accuracy and repeatability at the cost of a data collection and a training step.
There is a middle option the boilerplate points at without building: the same two-stage idea, a pretrained backbone plus a trainable head, is what most production transfer-learning pipelines do. The boilerplate's contribution is making that idea legible in a page of code, which is worth having even if you then replace the KNN head with something better.
Why a KNN head rather than a trained classification head
The choice of a k-nearest-neighbour classifier on top of a pretrained network is the part of the design most worth understanding, because it explains why the project needs no training step and no dataset.
A KNN classifier stores the training examples it is given and classifies a query by finding the nearest stored example, in this case in the feature space rather than the pixel space. The training is the act of adding examples. There is no gradient descent, no loss function to tune and no dataset to collect, which is exactly why the code fits in one file and why the README can say it is trained live in the browser on a webcam image.
The cost is inference cost. Every prediction is a search over the stored examples, so the number of examples per class directly affects how fast prediction runs and how much memory the tab uses. For the demo case, a few dozen examples per class is nothing. For a real application with thousands, it stops being free.
There is a second consequence that is less obvious. Because the classifier is a search rather than a learned boundary, the confidence score the API returns is a distance-based measure, not a calibrated probability. It ranks candidates well and should not be read as a number you can threshold and trust as a probability.
The README also notes that Tensorflow has a built in model for doing this, the KNN Classifier, and that this boilerplate code shows how to easily use it. The upstream package, at @tensorflow-models/knn-classifier, is where the implementation lives, and the boilerplate links to it. That matters for the ageing question: the boilerplate pins a 2019-era version of a package that has moved on, and the parts most worth keeping, the four calls and the MobileNet feature extraction, are still the shape of the current API.
So the lesson transfers even when the code does not. Pretrained backbone, cheap trainable head, and you are collecting examples rather than curating a dataset.
Editorial conclusion
Adopt Teachable Machine Boilerplate if you want to see transfer learning applied to a live webcam classifier in a file you can read in one sitting, because the two-stage idea, a pretrained MobileNet activation feeding a KNN classifier, is shown rather than described. Do not adopt it as a production dependency, because the pinned versions are old, with TensorFlow.js at 0.13.0 and the models at 0.2.2, and the build toolchain is a Babel 6 era browserify setup. Verify first that you are comfortable upgrading the TensorFlow.js version, since the API moved on considerably after 0.13, and that the licence field in the package manifest, which is empty, does not block your use, since the repository itself is under the Apache License 2.0.
Frequently asked questions
What does the Teachable Machine Boilerplate demonstrate?
It demonstrates how to use tensorflow.js to build something like Teachable Machine: a KNN classifier that can be trained live in the browser on webcam images. It is intentionally kept very simple so it can provide a starting point for new projects.
How does the Teachable Machine Boilerplate get good results from few samples?
It uses MobileNet as a feature extractor rather than as a classifier, taking the second to last layer of the network as the feature and feeding that into the KNN classifier. That uses the high level abstractions the network learned on ImageNet, which is transfer learning, and it lets a classifier recognise things like smiles versus frowns with very few samples.
How do I run the Teachable Machine Boilerplate?
Install the JavaScript dependencies with npm install, then run npm start, which starts a budo web server on localhost:9966. Allow webcam permission and add examples by holding down the buttons.
Which tensorflow.js calls does the boilerplate use?
From the KNN classifier, knnClassifier.create() returns a KNNImageClassifier, addExample(example, classIndex) adds to a class training set, clearClass(classIndex) clears one class, and predictClass(image) returns a top class index with a confidence score. From MobileNet, load() loads the model and infer(image, endpoint) returns an intermediate activation or logit, with the optional endpoint selecting which layer to predict through.
How is the Teachable Machine Boilerplate bundled?
The start script runs budo on main.js with output dist/build.js, with live reload and an explicit host, and the build script runs browserify on main.js into dist/build.js. A pre-commit hook runs the build, and browserify is configured with babelify using the es2015 preset plus the syntax-async-functions and transform-regenerator plugins.
Which versions does the Teachable Machine Boilerplate depend on?
@tensorflow/tfjs is pinned at 0.13.0, @tensorflow-models/knn-classifier and @tensorflow-models/mobilenet at 0.2.2, and @babel/polyfill at 7.0.0. The dev toolchain is Babel 6 era with babel-core 6.26.0 and budo 10.0.4.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/googlecreativelab-teachable-machine-boilerplate)Was this useful?