diff --git a/src/nbchkr/utils/__init__.py b/src/nbchkr/utils/__init__.py
index 67a65c1..9a8afba 100644
--- a/src/nbchkr/utils/__init__.py
+++ b/src/nbchkr/utils/__init__.py
@@ -27,7 +27,7 @@ def read(nb_path: pathlib.Path, as_version: int = 4) -> dict:
 
 
 def remove_cells(
-    nb_json, tags_regex_patterns_to_ignore=None, solution_regex=None
+    nb_node, tags_regex_patterns_to_ignore=None, solution_regex=None
 ):  # TODO Add typing to this function
     """
     Given a dictionary representation of a notebook, removes:
@@ -42,7 +42,7 @@ def remove_cells(
     if solution_regex is None:
         solution_regex = SOLUTION_REGEX
     cells = []
-    for cell in nb_json["cells"]:
+    for cell in nb_node["cells"]:
         if "tags" not in cell["metadata"] or all(
             not bool(re.match(pattern=pattern, string=tag))
             for tag in cell["metadata"]["tags"]
@@ -61,21 +61,21 @@ def remove_cells(
             except KeyError:  # pragma: no cover
                 pass  # TODO Add test coverage for this statement
             cells.append(cell)
-    nb_json["cells"] = cells
-    return nb_json
+    nb_node["cells"] = cells
+    return nb_node
 
 
-def write(output_path: pathlib.Path, nb_json):
+def write(output_path: pathlib.Path, nb_node: dict):
     """
     Write the python dict representation of a notebook to `output_path`.
     """
-    output_path.write_text(json.dumps(nb_json))
+    output_path.write_text(json.dumps(nb_node))
 
 
-def add_checks(nb_json: dict, source_nb_json: dict, answer_tag_regex=None) -> dict:
+def add_checks(nb_node: dict, source_nb_node: dict, answer_tag_regex=None) -> dict:
     """
-    Given a `nb_json` and a source `source_nb_json`, add the cells in
-    `source_nb` with tags matching `answer_tag_regex` to `source_nb_json`
+    Given a `nb_node` and a source `source_nb_node`, add the cells in
+    `source_nb` with tags matching `answer_tag_regex` to `source_nb_node`
 
     This is used to add a student's answers to the source notebook.
     """
@@ -83,15 +83,15 @@ def add_checks(nb_json: dict, source_nb_json: dict, answer_tag_regex=None) -> di
         answer_tag_regex = ANSWER_TAG_REGEX
     answers = {
         tag: cell
-        for cell in nb_json["cells"]
+        for cell in nb_node["cells"]
         for tag in cell["metadata"].get("tags", [])
         if bool(re.match(pattern=answer_tag_regex, string=tag))
     }
-    for i, cell in enumerate(source_nb_json["cells"]):
+    for i, cell in enumerate(source_nb_node["cells"]):
         for tag in cell["metadata"].get("tags", []):
             if tag in answers:
-                source_nb_json["cells"][i] = answers[tag]
-    return source_nb_json
+                source_nb_node["cells"][i] = answers[tag]
+    return source_nb_node
 
 
 def get_tags(cell: dict, tag_seperator: str = "|") -> Optional[str]:

Clear up variable naming
In particular the following two conventions are currently being used:

- `nb_json`
- `nb_node`

Aim for `nb_node`.
diff --git a/tests/test_check.py b/tests/test_check.py
index 94c9006..ebef0b3 100644
--- a/tests/test_check.py
+++ b/tests/test_check.py
@@ -20,16 +20,16 @@ def test_read_nb_gives_dictionary():
 
 
 def test_add_checks_creates_notebook_with_assertions():
-    nb_json = nbchkr.utils.read(nb_path=NB_PATH / "submission.ipynb")
-    source_nb_json = nbchkr.utils.read(nb_path=NB_PATH / "test.ipynb")
+    nb_node = nbchkr.utils.read(nb_path=NB_PATH / "submission.ipynb")
+    source_nb_node = nbchkr.utils.read(nb_path=NB_PATH / "test.ipynb")
     nb_with_checks = nbchkr.utils.add_checks(
-        nb_json=nb_json, source_nb_json=source_nb_json
+        nb_node=nb_node, source_nb_node=source_nb_node
     )
     assert "assert _ == 55" in str(nb_with_checks)
     assert "sum(i for i in range(10))" in str(nb_with_checks)
 
     output_path = NB_PATH / "feedback.ipynb"
-    nbchkr.utils.write(output_path=output_path, nb_json=nb_with_checks)
+    nbchkr.utils.write(output_path=output_path, nb_node=nb_with_checks)
 
 
 def test_check_with_no_errors_for_original_source():
@@ -65,7 +65,7 @@ Assertion passed:
 def test_check_with_no_errors_for_test_submission():
     nb_node = nbchkr.utils.read(nb_path=NB_PATH / "submission.ipynb")
     source_nb_node = nbchkr.utils.read(nb_path=NB_PATH / "test.ipynb")
-    nb_node = nbchkr.utils.add_checks(nb_json=nb_node, source_nb_json=source_nb_node)
+    nb_node = nbchkr.utils.add_checks(nb_node=nb_node, source_nb_node=source_nb_node)
     score, maximum_score, feedback = nbchkr.utils.check(nb_node=nb_node)
     expected_score = 2
     expected_maximum_score = 10
diff --git a/tests/test_release.py b/tests/test_release.py
index bf5feb6..79b04d9 100644
--- a/tests/test_release.py
+++ b/tests/test_release.py
@@ -46,33 +46,33 @@ def test_read_nb_cells_gives_list():
 
 def test_remove_cells():
     nb_path = NB_PATH / "test.ipynb"
-    nb_json = nbchkr.utils.read(nb_path=nb_path)
-    student_nb = nbchkr.utils.remove_cells(nb_json=nb_json)
+    nb_node = nbchkr.utils.read(nb_path=nb_path)
+    student_nb = nbchkr.utils.remove_cells(nb_node=nb_node)
     expected_length = 4
     assert type(student_nb["cells"]) is list
     assert len(student_nb["cells"]) == expected_length
 
 
-def test_remove_solution_and_keep_original_nb_json_unchanged():
+def test_remove_solution_and_keep_original_nb_node_unchanged():
     """
     This checks that solutions text is not included.
 
-    Note that, as implemented both `nb_json` and `student_nb` are modified. This
+    Note that, as implemented both `nb_node` and `student_nb` are modified. This
     should be fixed. TODO When fixed remove this line of documentation.
     """
     nb_path = NB_PATH / "test.ipynb"
-    nb_json = nbchkr.utils.read(nb_path=nb_path)
-    assert "sum(i for i in range(11))" in str(nb_json)
-    assert "sum(i for i in range(n + 1))" in str(nb_json)
-    assert "55" in str(nb_json)
+    nb_node = nbchkr.utils.read(nb_path=nb_path)
+    assert "sum(i for i in range(11))" in str(nb_node)
+    assert "sum(i for i in range(n + 1))" in str(nb_node)
+    assert "55" in str(nb_node)
 
-    student_nb = nbchkr.utils.remove_cells(nb_json=nb_json)
+    student_nb = nbchkr.utils.remove_cells(nb_node=nb_node)
     assert "sum(i for i in range(11))" not in str(student_nb)
     assert "sum(i for i in range(n + 1))" not in str(student_nb)
     assert "55" not in str(student_nb)
     # TODO Add test that shows wrong behaviour of changing the imported JSON
     # and document.
-    assert "sum(i for i in range(n + 1))" not in str(nb_json)
+    assert "sum(i for i in range(n + 1))" not in str(nb_node)
 
 
 def test_write_nb():
@@ -83,9 +83,9 @@ def test_write_nb():
     except FileNotFoundError:  # TODO Ensure py3.8 is used so that can pass
         # `missing_ok=True` to `path.unlink`.
         pass
-    nb_json = nbchkr.utils.read(nb_path=nb_path)
-    student_nb = nbchkr.utils.remove_cells(nb_json=nb_json)
-    nbchkr.utils.write(output_path=output_path, nb_json=student_nb)
+    nb_node = nbchkr.utils.read(nb_path=nb_path)
+    student_nb = nbchkr.utils.remove_cells(nb_node=nb_node)
+    nbchkr.utils.write(output_path=output_path, nb_node=student_nb)
 
     student_nb = nbchkr.utils.read(nb_path=output_path)
     assert "sum(i for i in range(11))" not in str(student_nb)

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-flake8 pytest-randomly pytest-sugar interrogate mypy
3.8
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
anyio==4.5.2
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
arrow==1.3.0
asttokens==3.0.0
async-lru==2.0.4
attrs==25.3.0
babel==2.17.0
backcall==0.2.0
beautifulsoup4==4.13.3
bleach==6.1.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
comm==0.2.2
coverage==7.6.1
debugpy==1.8.13
decorator==5.2.1
defusedxml==0.7.1
exceptiongroup==1.2.2
executing==2.2.0
fastjsonschema==2.21.1
flake8==5.0.4
fqdn==1.5.1
h11==0.14.0
httpcore==1.0.7
httpx==0.28.1
idna==3.10
importlib_metadata==8.5.0
importlib_resources==6.4.5
iniconfig==2.1.0
interrogate==1.7.0
ipykernel==6.29.5
ipython==8.12.3
ipywidgets==8.1.5
isoduration==20.11.0
jedi==0.19.2
Jinja2==3.1.6
json5==0.10.0
jsonpointer==3.0.0
jsonschema==4.23.0
jsonschema-specifications==2023.12.1
jupyter==1.1.1
jupyter-console==6.6.3
jupyter-events==0.10.0
jupyter-lsp==2.2.5
jupyter_client==8.6.3
jupyter_core==5.7.2
jupyter_server==2.14.2
jupyter_server_terminals==0.5.3
jupyterlab==4.3.6
jupyterlab_pygments==0.3.0
jupyterlab_server==2.27.3
jupyterlab_widgets==3.0.13
MarkupSafe==2.1.5
matplotlib-inline==0.1.7
mccabe==0.7.0
mistune==3.1.3
mypy==1.14.1
mypy-extensions==1.0.0
-e git+https://github.com/drvinceknight/nbchkr.git@7ac9e38498d7cc9118027495d939f849dae3270c#egg=nbchkr
nbclient==0.10.1
nbconvert==7.16.6
nbformat==5.10.4
nest-asyncio==1.6.0
notebook==7.3.3
notebook_shim==0.2.4
overrides==7.7.0
packaging==24.2
pandocfilters==1.5.1
parso==0.8.4
pexpect==4.9.0
pickleshare==0.7.5
pkgutil_resolve_name==1.3.10
platformdirs==4.3.6
pluggy==1.5.0
prometheus_client==0.21.1
prompt_toolkit==3.0.50
psutil==7.0.0
ptyprocess==0.7.0
pure_eval==0.2.3
py==1.11.0
pycodestyle==2.9.1
pycparser==2.22
pyflakes==2.5.0
Pygments==2.19.1
pytest==8.3.5
pytest-cov==5.0.0
pytest-flake8==1.2.2
pytest-randomly==3.15.0
pytest-sugar==1.0.0
python-dateutil==2.9.0.post0
python-json-logger==3.3.0
pytz==2025.2
PyYAML==6.0.2
pyzmq==26.3.0
referencing==0.35.1
requests==2.32.3
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rpds-py==0.20.1
Send2Trash==1.8.3
six==1.17.0
sniffio==1.3.1
soupsieve==2.6
stack-data==0.6.3
tabulate==0.9.0
termcolor==2.4.0
terminado==0.18.1
tinycss2==1.2.1
tomli==2.2.1
tornado==6.4.2
traitlets==5.14.3
types-python-dateutil==2.9.0.20241206
typing_extensions==4.13.0
uri-template==1.3.0
urllib3==2.2.3
wcwidth==0.2.13
webcolors==24.8.0
webencodings==0.5.1
websocket-client==1.8.0
widgetsnbextension==4.0.13
zipp==3.20.2

name: nbchkr
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=24.2=py38h06a4308_0
  - python=3.8.20=he870216_0
  - readline=8.2=h5eee18b_0
  - setuptools=75.1.0=py38h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.44.0=py38h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - anyio==4.5.2
      - argon2-cffi==23.1.0
      - argon2-cffi-bindings==21.2.0
      - arrow==1.3.0
      - asttokens==3.0.0
      - async-lru==2.0.4
      - attrs==25.3.0
      - babel==2.17.0
      - backcall==0.2.0
      - beautifulsoup4==4.13.3
      - bleach==6.1.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - colorama==0.4.6
      - comm==0.2.2
      - coverage==7.6.1
      - debugpy==1.8.13
      - decorator==5.2.1
      - defusedxml==0.7.1
      - exceptiongroup==1.2.2
      - executing==2.2.0
      - fastjsonschema==2.21.1
      - flake8==5.0.4
      - fqdn==1.5.1
      - h11==0.14.0
      - httpcore==1.0.7
      - httpx==0.28.1
      - idna==3.10
      - importlib-metadata==8.5.0
      - importlib-resources==6.4.5
      - iniconfig==2.1.0
      - interrogate==1.7.0
      - ipykernel==6.29.5
      - ipython==8.12.3
      - ipywidgets==8.1.5
      - isoduration==20.11.0
      - jedi==0.19.2
      - jinja2==3.1.6
      - json5==0.10.0
      - jsonpointer==3.0.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2023.12.1
      - jupyter==1.1.1
      - jupyter-client==8.6.3
      - jupyter-console==6.6.3
      - jupyter-core==5.7.2
      - jupyter-events==0.10.0
      - jupyter-lsp==2.2.5
      - jupyter-server==2.14.2
      - jupyter-server-terminals==0.5.3
      - jupyterlab==4.3.6
      - jupyterlab-pygments==0.3.0
      - jupyterlab-server==2.27.3
      - jupyterlab-widgets==3.0.13
      - markupsafe==2.1.5
      - matplotlib-inline==0.1.7
      - mccabe==0.7.0
      - mistune==3.1.3
      - mypy==1.14.1
      - mypy-extensions==1.0.0
      - nbclient==0.10.1
      - nbconvert==7.16.6
      - nbformat==5.10.4
      - nest-asyncio==1.6.0
      - notebook==7.3.3
      - notebook-shim==0.2.4
      - overrides==7.7.0
      - packaging==24.2
      - pandocfilters==1.5.1
      - parso==0.8.4
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pkgutil-resolve-name==1.3.10
      - platformdirs==4.3.6
      - pluggy==1.5.0
      - prometheus-client==0.21.1
      - prompt-toolkit==3.0.50
      - psutil==7.0.0
      - ptyprocess==0.7.0
      - pure-eval==0.2.3
      - py==1.11.0
      - pycodestyle==2.9.1
      - pycparser==2.22
      - pyflakes==2.5.0
      - pygments==2.19.1
      - pytest==8.3.5
      - pytest-cov==5.0.0
      - pytest-flake8==1.2.2
      - pytest-randomly==3.15.0
      - pytest-sugar==1.0.0
      - python-dateutil==2.9.0.post0
      - python-json-logger==3.3.0
      - pytz==2025.2
      - pyyaml==6.0.2
      - pyzmq==26.3.0
      - referencing==0.35.1
      - requests==2.32.3
      - rfc3339-validator==0.1.4
      - rfc3986-validator==0.1.1
      - rpds-py==0.20.1
      - send2trash==1.8.3
      - six==1.17.0
      - sniffio==1.3.1
      - soupsieve==2.6
      - stack-data==0.6.3
      - tabulate==0.9.0
      - termcolor==2.4.0
      - terminado==0.18.1
      - tinycss2==1.2.1
      - tomli==2.2.1
      - tornado==6.4.2
      - traitlets==5.14.3
      - types-python-dateutil==2.9.0.20241206
      - typing-extensions==4.13.0
      - uri-template==1.3.0
      - urllib3==2.2.3
      - wcwidth==0.2.13
      - webcolors==24.8.0
      - webencodings==0.5.1
      - websocket-client==1.8.0
      - widgetsnbextension==4.0.13
      - zipp==3.20.2
prefix: /opt/conda/envs/nbchkr

tests/test_release.py::test_remove_solution_and_keep_original_nb_node_unchanged tests/test_release.py::test_remove_cells tests/test_release.py::test_write_nb tests/test_check.py::test_check_with_no_errors_for_test_submission tests/test_check.py::test_add_checks_creates_notebook_with_assertions
tests/test_release.py::test_read_nb_cells_gives_list tests/test_release.py::test_read_nb_gives_dictionary tests/test_release.py::test_read_nb_gives_expected_keys tests/test_check.py::test_check_with_no_errors_for_original_source tests/test_check.py::test_read_nb_gives_dictionary
src/nbchkr/utils/__init__.py
src/nbchkr/utils/__init__.py