---
title: CanJS Debugging Tutorial
description: CanJS has powerful debugging tools. This tutorial walks through some of the best ones.  Follow along or sit back and watch the video.
image: https://user-images.githubusercontent.com/78602/46263119-b264eb00-c4d0-11e8-93cd-a66981a20946.png
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

 October 11, 2018

# CanJS Debugging Tutorial

 CanJS has powerful debugging tools. This tutorial walks through some of the best ones. Follow along or sit back and watch the video.

![Justin Meyer](https://www.bitovi.com/hubfs/justin.jpeg)

 Justin Meyer

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

This tutorial walks through some of CanJS's most useful debugging features. If you are new to CanJS, and want to be impressed, you might checkout it's two most unique and powerful features first:

- [Understand what happened with logStack](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-caused-a-particular-thing-to-happen-with-logstack) - A change in one value results in a change in another value, which results in another value change. This relationship can be hard to understand and isn't visible in the stack.  Fortunately, CanJS has a stack that lays out exactly why something changed.<https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-changes-the-dom>
- [Understand what changes the DOM](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-changes-the-dom) - If you inspect an element, CanJS can tell you all of the values that went into composing the element's values.

For those actively using CanJS, we encourage you to go through each step:

- [Setup](https://www.bitovi.com/blog/canjs-debugging-tutorial#setup)
- [Log when a property or properties change with .log](https://www.bitovi.com/blog/canjs-debugging-tutorial#log-when-a-property-or-properties-change-with-log)
- [Break when a property changes](https://www.bitovi.com/blog/canjs-debugging-tutorial#break-when-a-property-changes)
- [Understand what caused a particular thing to happen with logStack](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-caused-a-particular-thing-to-happen-with-logstack)
- [Understand what caused a particular thing to happen with logStack's reasonLog](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-caused-a-particular-thing-to-happen-with-logstacks-reasonlog)
- [Logging the state of the ViewModel](https://www.bitovi.com/blog/canjs-debugging-tutorial#logging-the-state-of-the-viewmodel)
- [Understanding what caused something to change with components and logStack](https://www.bitovi.com/blog/canjs-debugging-tutorial#understanding-what-caused-something-to-change-with-components-and-logstack)
- [Logging the scope](https://www.bitovi.com/blog/canjs-debugging-tutorial#logging-the-scope)
- [Logging values in the scope](https://www.bitovi.com/blog/canjs-debugging-tutorial#logging-values-in-the-scope)
- [Debugging the scope](https://www.bitovi.com/blog/canjs-debugging-tutorial#debugging-the-scope)
- [Understand what changes the DOM](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-changes-the-dom)
- [Understand what changes an observable](https://www.bitovi.com/blog/canjs-debugging-tutorial#understand-what-changes-an-observable)

For each of the 12 steps, there's a:

1. Problem you need to solve
2. Guidance on a solution
3. The solution itself

Even better, there's a link to that step performed in this video:

Lets get started!

 

## Setup

[Watch this step on YouTube](https://youtu.be/bJOEr9IltAw?t=40)

### Problem

- In this section, we will make sure that we have access to the debugging in various environments: 
    - Using the `mjs` builds (CodePen).
    - Using StealJS individual builds.

We want to be able to get this component working:

```
Component.extend({
    tag: "my-counter",
    view: `
        Count: <span>{{this.count}}</span>
        <button on:click='this.increment()'>+1</button>
    `,
    ViewModel: {
        count: {default: 0},
        increment() {
            this.count++;
        }
    }
});
```

And then be able to see its `ViewModel` in the CanJS ViewModel inspector:

![image](https://user-images.githubusercontent.com/78602/46239124-b7ebf500-c359-11e8-9952-82066ac81a27.png)

We also want to be able to write `can.debug` and access the debugger helpers:

![image](https://user-images.githubusercontent.com/78602/46239181-6c861680-c35a-11e8-8bb5-36ef87b91558.png)

### What you need to know

#### Chrome Dev Tools

- Install the [Chrome Web Store Extension](https://chrome.google.com/webstore/detail/canjs-devtools/hhdfadlgplkpapjfehnjhcebebgmibcb).

#### CodePen

- Start a new [CodePen](https://codepen.io)
- Import `Component` from `"https://unpkg.com/can/core.mjs"`.
- Make sure to add `<my-counter></my-counter>` to the **HTML**.
- Solution: [CodePen](https://codepen.io/justinbmeyer/pen/PywPeV?editors=1010)

#### Steal

```
mkdir can-steal
cd can-steal
npm init --yes
npm i steal can-component can-debug
npm i steal-conditional --save-dev
```

Configure `steal-conditional` in *package.json*

```
{
  "name": "can-steal",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "can-component": "^4.4.2",
    "can-debug": "^2.0.1",
    "steal": "^2.1.3",
    "steal-conditional": "^1.1.1"
  },
  "steal": {
    "configDependencies": [
      "node_modules/steal-conditional/conditional"
    ]
  }
}
```

**dev.html**

```
<my-counter></my-counter>
<script src="./node_modules/steal/steal.js" main></script>
```

**index.js**

```
import Component from "can-component";

import debug from "can-debug#?./is-dev";
debug();

Component.extend({
    tag: "my-counter",
    view: `
        Count: <span>{{this.count}}</span>
        <button on:click='this.increment()'>+1</button>
    `,
    ViewModel: {
        count: {default: 0},
        increment() {
            this.count++;
        }
    }
});
```

**is-dev.js**

```
import steal from "@steal";
export default !steal.isEnv("production")
```

## Log when a property or properties change

[Watch this step on YouTube](https://youtu.be/bJOEr9IltAw?t=490)

### The problem

This [CodePen](https://codepen.io/justinbmeyer/pen/YJPLVB?editors=1011) changes `confusing`'s properties. The property names write out a message.

### What you need to know

Use `.log()` to log when **any** property changes on an observable. Use `.log(key)` to log when a specific property changes on an observable.

### The solution

Click to See

Add the following after `confusing` is instantiated:

```
// Maybe listen to properties changing here:
confusing.log();
```

The properties changed write out `all` `you` `need` `is` `love`.

 

## Break when a property changes

[Watch this step on YouTube](https://youtu.be/bJOEr9IltAw?t=582)

### The problem

We want to see what's changing a property.

This [CodePen](https://codepen.io/justinbmeyer/pen/rqavrd?editors=1011) is randomly changing `propA`, `propB`, `propC`. When those change, `final` is being incremented:

```
confusing.on("ticker", function(){
  var props = ["propA","propB","propC"];
  var prop = props[rand()];
  confusing[prop]++;
},"domUI");
confusing.on("propA", function canjs(){
  confusing.final++;
},"domUI");
confusing.on("propB", function stealjs(){
  confusing.final++;
},"domUI");
confusing.on("propC", function donejs(){
  confusing.final++;
},"domUI");
```

Which function (`canjs`, `stealjs`, or `donejs`) is the one that is called when `final` is incremented to 5?

### What you need to know

If you simply listen to when a property changes like:

```
map.on("key", function(ev, newVal){
  if(newVal === 5) {
    debugger;
  }
});
```

That handler will **not** be called immediately upon the change of the property. Instead, that handler will be added to the `mutate` queue which fires at the end of a batch of changes.

If we do this with the CodePen:

```
confusing.on("final", function(ev, newVal){
  if(newVal === 5) {
    debugger;
  }
});
```

We see this:

![image](https://user-images.githubusercontent.com/78602/46250961-078af900-c40c-11e8-8048-441daf5f2773.png)

Instead, if you want to be immediately notified of a change, listen to the event in the `"notify"` phase as follows:

```
map.on("prop", function handler(){
  debugger;
}, "notify");
```

### The solution

Click to See

Add the following to the CodePen:

```
confusing.on("final", function(ev, newVal){
  if(newVal === 5) {
    debugger;
  }
},"notify");
```

`` The answer is `stealjs`. ![image](https://user-images.githubusercontent.com/78602/46250970-2ee1c600-c40c-11e8-92df-580ee97c2c00.png)

 

## Understand what caused a particular thing to happen with logStack

[Watch this step on YouTube](https://youtu.be/bJOEr9IltAw?t=824)

### The problem

Figure out the properties that result in the **final** property changing in the following [CodePen](https://codepen.io/justinbmeyer/pen/qJEbyg?editors=1010).  There are 5 properties.  They will spell out a message.

### What you need to know

- The call stack only tells you the first observable to change. Everything else you see are queues functions: ![image](https://user-images.githubusercontent.com/78602/46246701-72fea780-c3c7-11e8-84fc-b1e922dade61.png)
- [can-queues](https://canjs.com/doc/can-queues.html) maintains a stack trace everything it does. CanJS does its best to give descriptive names to what is happening.
- [can.queues.logStack()](https://canjs.com/doc/can-queues.logStack.html) prints this stack.

### The solution

Click to See

The properties changed spell `s` `t` `a` `c` `k`.

![image](https://user-images.githubusercontent.com/78602/46246806-d6d5a000-c3c8-11e8-9b8a-da735c7e2b4f.png)

 

## Understand what caused a particular thing to happen with `logStack`'s reasonLog

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=1114s)

### The problem

While debugging the **final** property changing in the following [CodePen](https://codepen.io/justinbmeyer/pen/oageGJ), you want to know what changed in **message** to cause the **final** change.

### What you need to know

`logStack` entries are really just function calls. Each entry gets logged with an object that includes:

- `args` - The arguments passed to the function
- `context` - The `this` of the function
- `fn` - The function that was called
- `meta` - Additional information queues uses for debugging.

Critically, the `meta` object also includes a `reasonLog`. This is indented to be a human-readable explanation of why that task was queued. CanJS provides it in development mode on most tasks.

![image](https://user-images.githubusercontent.com/78602/46247079-d7bc0100-c3cb-11e8-9f1a-24c06a58f68d.png)

### The Solution

Click to See

The property changed to "reason" from "log":

![image](https://user-images.githubusercontent.com/78602/46247100-15b92500-c3cc-11e8-96c8-2d6d97bf29cb.png)

 

## Logging the state of the ViewModel

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=1329s)

### The problem

There's a `<some-state>` component on the page in [this CodePen](https://codepen.io/justinbmeyer/pen/MPYrZr?editors=1111). Log its `viewModel`'s properties and values.

### What you need to konw

Components elements now have their `viewModel` available as `element.viewModel`. So use:

```
document.querySelector("some-component").viewModel
```

To get the `ViewModel` and:

```
document.querySelector("some-component").viewModel.get()
```

To see it in an object form.

If you inspect the element, you can also use `$0` to reference the last element you inspected:

```
$0.viewModel.get()
```

### The solution

Click to See

Add:

```
console.log(document.querySelector('some-state').viewModel.get())
```

And you should see logged:

```
{ a: "viewModel", property: "makes", sense: "right" }
```

 

## Understand what happened with components and logStack

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=1459s)

### The problem

- Understanding how component bindings (`foo:bind="bar"`) resulted in property updates can be confusing.
- This [CodePen](https://codepen.io/justinbmeyer/pen/Edavrd?editors=1011)'s `<word-and>`'s `you` property is changing as a result of several child components of `<my-app>` passing around the value.
- Can you trace how the value moved from one property to the next?
- Record the word in each "word" component's name and the property that was changed and it will spell a message. 
    - For example, if a component like `<word-hello>`'s `world` property changed, you would record "hello world".
- There are 4 sub components whose properties changed.

### What you need to know

When a binding updates a value, an entry like the following is added to the queue:

```
DOM_UI ran task: <a-component viewModelProp:bind="scopeKey"> updates <a-component>.viewModelProp from {{scopeKey}}
```

This means that `scopeKey` changed and `<a-component>.viewModelProp` was set to its value.

Bindings can also run the other way, so you might see:

```
DOM_UI ran task: <a-component viewModelProp:bind="scopeKey"> updates {{scopeKey}} from <a-component>.viewModelProp
```

This means `<a-component>.viewModelProp` changed and `scopeKey` was set to its value.

### The solution

Click to See

The properties are updated as `can.js` `loves.javascript` `debugging.tools` `and.you`:

![image](https://user-images.githubusercontent.com/78602/46250303-62692400-c3fd-11e8-80f1-c846ea5907de.png)

 

## Log the scope

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=1761s)

### The problem

[This Codepen](https://codepen.io/justinbmeyer/pen/rqagLq?editors=1111) has a class with a student with a missing parent name. Can you figure out which class and student has the missing parent name by exploring the scope?

### What you need to know

You can call `scope.log()` to log stache's scope.

If you don't want to do it all the time, it helps to do it conditionally:

```
{{# if(logTheScope) }} {{ scope.log() }}  {{/if}}
```

> HINT: `{{^ if() }}` can be used to inverse logic.

### The solution

Click to See

Conditionally call `scope.log()`:

```

          {{# for(parent of student.parents) }}
            {{^ if(parent.name) }} {{scope.log()}} {{/ if }}
            <li>\>{{parent.name}}</li>
          {{ /for}}
```

Then exploring the result will show the class is `math` and the student is `Rahim`:

![image](https://user-images.githubusercontent.com/78602/46258380-4e6e0280-c48f-11e8-8df6-23df62f952e6.png)

 

## Log values in the scope

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=1999s)

### The problem

[This Codepen](https://codepen.io/justinbmeyer/pen/rqagLq?editors=1111) has a class with a student with a missing parent name. Can you figure out which class and student has the missing parent name by logging values in the scope?

### What you need to know

You can use `{{ console.log(key) }}` to log values in the scope.

### The solution

Click to See

Use `console.log()`:

```

          {{# for(parent of student.parents) }}
            {{console.log(class.name, student.name, parent.name)}}
            <li>\>{{parent.name}}</li>
          {{ /for}}
```

Then exploring the result will show the class is `math` and the student is `Rahim`:

![image](https://user-images.githubusercontent.com/78602/46258513-a4dc4080-c491-11e8-84df-bae8f9f1ce00.png)

## Debug the scope

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=2103s)

### The problem

[This Codepen](https://codepen.io/justinbmeyer/pen/yRNNMj?editors=1111) has a class with a student with a missing (`undefined`) parent name. Can you figure out which class and student has the missing parent name by debugging the scope?

 The CodePen uses the global build. Click to find out why.

There is a bug in the `.mjs` builds. `scope` and the `get` function are being [dead code eliminated](https://github.com/canjs/canjs/issues/4502). If you use the `.mjs` build, you must write:

```
arguments[2].scope.get("class").name
```

### What you need to know

```
Break anytime this part of the template evaluates
{{debugger()}}

Break when condition is truthy
{{debugger(condition)}}

Break when left equals right
{{debugger(left, right)}}
```

This will break and give you access to a `get` function that reads from the scope like:

```
get("class") //-> DefineMap{}
```

The scope itself is available as `options.scope`:

```
options.scope.get("class") //-> DefineMap{}
```

> PROTIP: If you have `stacheConverters` included, you could use `not()` like:
> 
> ```
> {{ debugger( not(key) ) }}
> ```

### The Solution

Click to See

Use `debugger(parent.name, undefined)`:

```

          {{# for(parent of student.parents) }}
            {{debugger(parent.name, undefined)}}
            <li>\>{{parent.name}}</li>
          {{ /for}}
```

Then exploring the result will show the class is `reading` and the student is `Adisa`:

![image](https://user-images.githubusercontent.com/78602/46262221-f3a2ce00-c4c3-11e8-80d0-9833be3bdfb2.png)

 

## Understand what changes the DOM

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=2287s)

### The problem

[This CodePen](https://codepen.io/justinbmeyer/pen/YJXyeE?editors=1011) has an `<h2>` element that reads a `whatChangesMe` element like:

```
<h2>What Changes Me? {{this.whatChangesMe}}</h2>
```

Can you figure out which two properties properties of the `<my-app>` ViewModel update the `<h2>` element? 

### What you need to know

Use `can.debug.logWhatChangesMe(element)` to log what changes an HTML element:

```
can.debug.logWhatChangesMe(element)
```

### The solution

Click to See

Inspect the `<h2>` element and run the following in the console:

```
can.debug.logWhatChangesMe($0)
```

![image](https://user-images.githubusercontent.com/78602/46263119-b264eb00-c4d0-11e8-93cd-a66981a20946.png)

 

## Understand what changes an observable

[Watch this step on YouTube](https://www.youtube.com/watch?v=bJOEr9IltAw&t=2437s)

### The Problem

[This CodePen](https://codepen.io/justinbmeyer/pen/RePPXV?editors=1011) has a `<my-app>`'s element with a `first` and `last` property. One of the 6 inputs changes the `first` property and one of the 6 inputs changes the `last` property. Can you discover those inputs without changing the inputs?

### What you need to know

`can.debug.logWhatChangesMe(observable [,key] )` will list out all the values (including elements) that change a value.

### The Solution

Click to See

```
can.debug.logWhatChangesMe($0.viewModel, "first")
can.debug.logWhatChangesMe($0.viewModel, "last")
```

First is changed by `Thomas`. Last is changed by `Paula`.

[![Tag for canjs](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) canjs ](https://www.bitovi.com/blog/topic/canjs)

 Previous Post

![marketing-funnel-1](https://www.bitovi.com/hs-fs/hubfs/marketing-funnel-wide.jpg?height=117&name=marketing-funnel-wide.jpg) [ Open Source Theory ](https://www.bitovi.com/blog/open-source-theory)

  

 Next Post

![discovery-launch-liftoff-23764](https://www.bitovi.com/hs-fs/hubfs/discovery-launch-liftoff-23764.jpg?height=117&name=discovery-launch-liftoff-23764.jpg) [ November 2018 DoneJS Community Update ](https://www.bitovi.com/blog/november-2018-donejs-community-update)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/canjs-debugging-tutorial",
    "@type" : "WebPage",
    "description" : "CanJS has powerful debugging tools. This tutorial walks through some of the best ones.  Follow along or sit back and watch the video."
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Justin Meyer"
  },
  "dateModified" : "October 11, 2018, 4:52:24 PM",
  "datePublished" : "2018-10-11 16:35:08",
  "description" : "CanJS has powerful debugging tools. This tutorial walks through some of the best ones.  Follow along or sit back and watch the video.",
  "headline" : "CanJS Debugging Tutorial",
  "image" : {
    "@type" : "ImageObject",
    "url" : "https://user-images.githubusercontent.com/78602/46263119-b264eb00-c4d0-11e8-93cd-a66981a20946.png"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```