diff --git a/doc/source/pre/whatsnew/1.5.rst b/doc/source/pre/whatsnew/1.5.rst
index a509ccc0a16dc525e8330671790459ae5eaa2040..6204a4e02059822c4ab123ebec43b4e59afd5a5e 100644
--- a/doc/source/pre/whatsnew/1.5.rst
+++ b/doc/source/pre/whatsnew/1.5.rst
@@ -3,6 +3,21 @@ What's new in Kwant 1.5
 
 This article explains the user-visible changes in Kwant 1.5.0.
 
+Deprecation of leaving 'norbs' unset for site families
+------------------------------------------------------
+When constructing site families (e.g. lattices) it is now deprecated to
+leave the 'norbs' parameter unset. This will now raise a
+KwantDeprecationWarning and will be disallowed in a future version of
+Kwant. For example, when constructing a square lattice with 1 orbital
+per site, use::
+
+    kwant.lattice.square(norbs=1)
+
+rather than::
+
+    kwant.lattice.square()
+
+
 Automatic addition of Peierls phase terms to Builders
 -----------------------------------------------------
 Kwant 1.4 introduced `kwant.physics.magnetic_gauge` for computing Peierls
diff --git a/doc/source/tutorial/faq.rst b/doc/source/tutorial/faq.rst
index 22f0ad71c08d29c1e8cc3f23f85355c5a982d157..e82d0f1835dae934b8b633d8363802354581cbc9 100644
--- a/doc/source/tutorial/faq.rst
+++ b/doc/source/tutorial/faq.rst
@@ -68,7 +68,7 @@ For example let us create an empty tight binding system and add two sites:
 .. jupyter-execute::
 
     a = 1
-    lat = kwant.lattice.square(a)
+    lat = kwant.lattice.square(a, norbs=1)
     syst = kwant.Builder()
 
     syst[lat(1, 0)] = 4
@@ -165,9 +165,9 @@ the origins of the two lattices:
 
     # Two monatomic lattices
     primitive_vectors = [(1, 0), (0, 1)]
-    lat_a = kwant.lattice.Monatomic(primitive_vectors, offset=(0, 0))
-    lat_b = kwant.lattice.Monatomic(primitive_vectors, offset=(0.5, 0.5))
-    # lat1 is equivalent to kwant.lattice.square()
+    lat_a = kwant.lattice.Monatomic(primitive_vectors, offset=(0, 0), norbs=1)
+    lat_b = kwant.lattice.Monatomic(primitive_vectors, offset=(0.5, 0.5), norbs=1)
+    # lat1 is equivalent to kwant.lattice.square(norbs=1)
 
     syst = kwant.Builder()
 
@@ -182,7 +182,7 @@ two sites in the basis:
 .. jupyter-execute::
 
     # One polyatomic lattice containing two sublattices
-    lat = kwant.lattice.Polyatomic([(1, 0), (0, 1)], [(0, 0), (0.5, 0.5)])
+    lat = kwant.lattice.Polyatomic([(1, 0), (0, 1)], [(0, 0), (0.5, 0.5)], norbs=1)
     sub_a, sub_b = lat.sublattices
 
 The two sublattices ``sub_a`` and ``sub_b`` are nothing else than ``Monatomic``
@@ -204,7 +204,7 @@ In the following example we shall use a kagome lattice, which has three sublatti
 
 .. jupyter-execute::
 
-    lat = kwant.lattice.kagome()
+    lat = kwant.lattice.kagome(norbs=1)
     syst = kwant.Builder()
 
     a, b, c = lat.sublattices  # The kagome lattice has 3 sublattices
@@ -258,7 +258,7 @@ The following example shows how this can be used:
     # Create hopping between neighbors with HoppingKind
     a = 1
     syst = kwant.Builder()
-    lat = kwant.lattice.square(a)
+    lat = kwant.lattice.square(a, norbs=1)
     syst[ (lat(i, j) for i in range(5) for j in range(5)) ] = 4
 
     syst[kwant.builder.HoppingKind((1, 0), lat)] = -1
@@ -271,7 +271,7 @@ the sublattices when creating a ``HoppingKind``:
 .. jupyter-execute::
     :hide-code:
 
-    lat = kwant.lattice.kagome()
+    lat = kwant.lattice.kagome(norbs=1)
     syst = kwant.Builder()
 
     a, b, c = lat.sublattices  # The kagome lattice has 3 sublattices
@@ -323,7 +323,7 @@ that returns a list of ``HoppingKind`` instances that connect sites with their
 
     # Create hoppings with lat.neighbors()
     syst = kwant.Builder()
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[(lat(i, j) for i in range(3) for j in range(3))] = 4
 
     syst[lat.neighbors()] = -1  # Equivalent to lat.neighbors(1)
@@ -344,7 +344,7 @@ sublattices:
 .. jupyter-execute::
 
     # Create the system
-    lat = kwant.lattice.kagome()
+    lat = kwant.lattice.kagome(norbs=1)
     syst = kwant.Builder()
     a, b, c = lat.sublattices  # The kagome lattice has 3 sublattices
 
@@ -382,7 +382,7 @@ region:
 
     # Define the lattice and the (empty) system
     a = 2
-    lat = kwant.lattice.cubic(a)
+    lat = kwant.lattice.cubic(a, norbs=1)
     syst = kwant.Builder()
 
     L = 10
@@ -424,7 +424,7 @@ We can access the sites of a ``Builder`` by using its `~kwant.builder.Builder.si
     :hide-code:
 
     builder = kwant.Builder()
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     builder[(lat(i, j) for i in range(3) for j in range(3))] = 4
 
 .. jupyter-execute::
@@ -472,7 +472,7 @@ First we construct the central system:
     L = 5
     W = 5
 
-    lat = kwant.lattice.honeycomb()
+    lat = kwant.lattice.honeycomb(norbs=1)
     subA, subB = lat.sublattices
 
     syst = kwant.Builder()
@@ -487,7 +487,7 @@ and the lead:
 .. jupyter-execute::
 
     # Create a lead
-    lat_lead = kwant.lattice.square()
+    lat_lead = kwant.lattice.square(norbs=1)
     sym_lead1 = kwant.TranslationalSymmetry((0, 1))
 
     lead1 = kwant.Builder(sym_lead1)
@@ -535,7 +535,7 @@ For example, say we want to create a simple model on a cubic lattice:
 .. jupyter-execute::
 
     # Create 3d model.
-    cubic = kwant.lattice.cubic()
+    cubic = kwant.lattice.cubic(norbs=1)
     sym_3d = kwant.TranslationalSymmetry([1, 0, 0], [0, 1, 0], [0, 0, 1])
     model = kwant.Builder(sym_3d)
     model[cubic(0, 0, 0)] = 4
@@ -587,7 +587,7 @@ system in a `~kwant.physics.PropagatingModes` object:
 
 .. jupyter-execute::
 
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
 
     lead = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
     lead[(lat(0, i) for i in range(3))] = 4
diff --git a/doc/source/tutorial/first_steps.rst b/doc/source/tutorial/first_steps.rst
index 801bb3e5ad4214d14c88205d600a5b2cbe1a1f34..41ed21bb7fdfef0279b95f000db6d9199fa9ed63 100644
--- a/doc/source/tutorial/first_steps.rst
+++ b/doc/source/tutorial/first_steps.rst
@@ -128,14 +128,16 @@ a square lattice. For simplicity, we set the lattice constant to unity:
 .. jupyter-execute::
 
     a = 1
-    lat = kwant.lattice.square(a)
+    lat = kwant.lattice.square(a, norbs=1)
 
 Since we work with a square lattice, we label the points with two
 integer coordinates `(i, j)`. `~kwant.builder.Builder` then
 allows us to add matrix elements corresponding to lattice points:
 ``syst[lat(i, j)] = ...`` sets the on-site energy for the point `(i, j)`,
 and ``syst[lat(i1, j1), lat(i2, j2)] = ...`` the hopping matrix element
-**from** point `(i2, j2)` **to** point `(i1, j1)`.
+**from** point `(i2, j2)` **to** point `(i1, j1)`. In specifying ``norbs=1``
+in the definition of the lattice we tell Kwant that there is 1 degree
+of freedom per lattice site.
 
 Note that we need to specify sites for `~kwant.builder.Builder`
 in the form ``lat(i, j)``. The lattice object `lat` does the
@@ -472,7 +474,8 @@ file and defining the a square lattice and empty scattering region.
 
     # Start with an empty tight-binding system and a single square lattice.
     # `a` is the lattice constant (by default set to 1 for simplicity).
-    lat = kwant.lattice.square(a)
+    # Each lattice site has 1 degree of freedom, hence norbs=1.
+    lat = kwant.lattice.square(a, norbs=1)
 
     syst = kwant.Builder()
 
@@ -681,7 +684,7 @@ return a Kwant ``Builder``:
 .. jupyter-execute::
 
     def make_system(L, W, a=1, t=1.0):
-        lat = kwant.lattice.square(a)
+        lat = kwant.lattice.square(a, norbs=1)
 
         syst = kwant.Builder()
         syst[(lat(i, j) for i in range(L) for j in range(W))] = 4 * t
diff --git a/doc/source/tutorial/graphene.rst b/doc/source/tutorial/graphene.rst
index 4243b7ffe136277d7ddf5631e8c29c6ddf214ab1..792d4521ace547a53620a5b3dff32f6865b0dc2f 100644
--- a/doc/source/tutorial/graphene.rst
+++ b/doc/source/tutorial/graphene.rst
@@ -59,7 +59,8 @@ explicitly here to show how to define a new lattice:
 .. jupyter-execute::
 
     graphene = kwant.lattice.general([(1, 0), (sin_30, cos_30)],
-                                     [(0, 0), (0, 1 / sqrt(3))])
+                                     [(0, 0), (0, 1 / sqrt(3))],
+                                     norbs=1)
     a, b = graphene.sublattices
 
 The first argument to the `~kwant.lattice.general` function is the list of
diff --git a/doc/source/tutorial/magnetic_field.rst b/doc/source/tutorial/magnetic_field.rst
index add388bfccdeb5505343a3c0785a1f74563e9056..a3c98b95ad8c46831334fcdb2824c5a291e276a6 100644
--- a/doc/source/tutorial/magnetic_field.rst
+++ b/doc/source/tutorial/magnetic_field.rst
@@ -137,7 +137,7 @@ a discretization in realspace.
 
 .. jupyter-execute::
 
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
 
     def peierls(to_site, from_site, B):
diff --git a/doc/source/tutorial/plotting.rst b/doc/source/tutorial/plotting.rst
index fc4b65c88325c092c76d73f1c3ff857bf57ce066..bf6b51ae7e148fc6fdad8c37c5f24ed57421a079 100644
--- a/doc/source/tutorial/plotting.rst
+++ b/doc/source/tutorial/plotting.rst
@@ -53,7 +53,7 @@ to previous examples, we will also use hoppings beyond next-nearest neighbors:
 
 .. jupyter-execute::
 
-    lat = kwant.lattice.honeycomb()
+    lat = kwant.lattice.honeycomb(norbs=1)
     a, b = lat.sublattices
 
     def make_system(r=8, t=-1, tp=-0.1):
@@ -241,7 +241,8 @@ It is very easily generated in Kwant with `kwant.lattice.general`:
 .. jupyter-execute::
 
     lat = kwant.lattice.general([(0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)],
-                                [(0, 0, 0), (0.25, 0.25, 0.25)])
+                                [(0, 0, 0), (0.25, 0.25, 0.25)],
+                                norbs=1)
     a, b = lat.sublattices
 
 Note how we keep references to the two different sublattices for later use.
diff --git a/doc/source/tutorial/spectrum.rst b/doc/source/tutorial/spectrum.rst
index 5e70ba9bc7b63e64520c59bd78eec8d3a74b96a2..2b6d86a0a92db6d9b709697b00bea6097e865b22 100644
--- a/doc/source/tutorial/spectrum.rst
+++ b/doc/source/tutorial/spectrum.rst
@@ -54,7 +54,7 @@ usual way:
 
     def make_lead(a=1, t=1.0, W=10):
         # Start with an empty lead with a single square lattice
-        lat = kwant.lattice.square(a)
+        lat = kwant.lattice.square(a, norbs=1)
 
         sym_lead = kwant.TranslationalSymmetry((-a, 0))
         lead = kwant.Builder(sym_lead)
diff --git a/doc/source/tutorial/spin_potential_shape.rst b/doc/source/tutorial/spin_potential_shape.rst
index 05aad2e6480c15ca9f219cf640590a95643fbffb..b87eaa7f6afced106110ca10823e48a6cb667069 100644
--- a/doc/source/tutorial/spin_potential_shape.rst
+++ b/doc/source/tutorial/spin_potential_shape.rst
@@ -109,7 +109,7 @@ we can simply write:
 .. jupyter-execute::
     :hide-code:
 
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=2)
     syst = kwant.Builder()
 
 .. jupyter-execute::
@@ -124,6 +124,9 @@ we can simply write:
     syst[kwant.builder.HoppingKind((0, 1), lat, lat)] = \
         -t * sigma_0 - 1j * alpha * sigma_x / 2
 
+Note that we specify ``norbs=2`` when creating the lattice, as each site
+has 2 degrees of freedom associated with it, giving us 2x2 matrices as
+onsite/hopping terms.
 Note that the Zeeman energy adds to the onsite term, whereas the Rashba
 spin-orbit term adds to the hoppings (due to the derivative operator).
 Furthermore, the hoppings in x and y-direction have a different matrix
@@ -298,7 +301,7 @@ Kwant now allows us to pass a function as a value to
     def onsite(site, pot):
         return 4 * t + potential(site, pot)
 
-    lat = kwant.lattice.square(a)
+    lat = kwant.lattice.square(a, norbs=1)
     syst = kwant.Builder()
 
     syst[(lat(x, y) for x in range(L) for y in range(W))] = onsite
@@ -457,7 +460,7 @@ provided by the lattice:
     a = 1
     t = 1.0
 
-    lat = kwant.lattice.square(a)
+    lat = kwant.lattice.square(a, norbs=1)
     syst = kwant.Builder()
 
     syst[lat.shape(ring, (0, r1 + 1))] = 4 * t
@@ -620,7 +623,7 @@ period of one flux quantum.
         W = 10
         r1, r2 = 10, 20
 
-        lat = kwant.lattice.square()
+        lat = kwant.lattice.square(norbs=1)
         syst = kwant.Builder()
         def ring(pos):
             (x, y) = pos
@@ -675,7 +678,7 @@ period of one flux quantum.
         W = 10
         r1, r2 = 10, 20
 
-        lat = kwant.lattice.square(a)
+        lat = kwant.lattice.square(a, norbs=1)
         syst = kwant.Builder()
         def ring(pos):
             (x, y) = pos
diff --git a/doc/source/tutorial/superconductors.rst b/doc/source/tutorial/superconductors.rst
index 9e0b1d7a5fdb19d700734bb3f7f6256be81f6aae..f2e3b3235653eb24a40c54940ddbb1adf2e99623 100644
--- a/doc/source/tutorial/superconductors.rst
+++ b/doc/source/tutorial/superconductors.rst
@@ -133,7 +133,7 @@ and we declare the square lattice and construct the scattering region with the f
     # Hoppings
     syst[lat.neighbors()] = -t * tau_z
 
-Note the new argument ``norbs`` to `~kwant.lattice.square`. This is
+Note the argument ``norbs`` to `~kwant.lattice.square`. This is
 the number of orbitals per site in the discretized BdG Hamiltonian - of course,
 ``norbs = 2``, since each site has one electron orbital and one hole orbital.
 It is necessary to specify ``norbs`` here, such that we may later separate the
diff --git a/kwant/builder.py b/kwant/builder.py
index 89ec7c24c68393a9916d6d314925e3783168d7b7..b31edc6beeefb0a308ed530f5d79efbf3babcd49 100644
--- a/kwant/builder.py
+++ b/kwant/builder.py
@@ -140,6 +140,10 @@ class SiteFamily(metaclass=abc.ABCMeta):
         self.canonical_repr = canonical_repr
         self.hash = hash(canonical_repr)
         self.name = name
+        if norbs is None:
+            warnings.warn("Not specfying norbs is deprecated. Always specify "
+                          "norbs when creating site families.",
+                          KwantDeprecationWarning, stacklevel=3)
         if norbs is not None:
             if int(norbs) != norbs or norbs <= 0:
                 raise ValueError('The norbs parameter must be an integer > 0.')
diff --git a/kwant/continuum/tests/test_discretizer.py b/kwant/continuum/tests/test_discretizer.py
index b8953e6b860f11d10ed9e68b1d6bd1736e8baba3..6307b1f7c9889cccef6e3b764b35fe782549d993 100644
--- a/kwant/continuum/tests/test_discretizer.py
+++ b/kwant/continuum/tests/test_discretizer.py
@@ -548,14 +548,14 @@ def test_grid(ham, grid_spacing, grid):
 
 
 @pytest.mark.parametrize('ham, grid_offset, offset, norbs', [
-    ('k_x', None, 0, None),
+    ('k_x', None, 0, 1),
     ('k_x', None, 0, 1),
     ('k_x * eye(2)', None, 0, 2),
-    ('k_x', (0,), 0, None),
-    ('k_x', (1,), 1, None),
-    ('k_x + k_y', None, (0, 0), None),
-    ('k_x + k_y', (0, 0), (0, 0), None),
-    ('k_x + k_y', (1, 2), (1, 2), None),
+    ('k_x', (0,), 0, 1),
+    ('k_x', (1,), 1, 1),
+    ('k_x + k_y', None, (0, 0), 1),
+    ('k_x + k_y', (0, 0), (0, 0), 1),
+    ('k_x + k_y', (1, 2), (1, 2), 1),
 ])
 def test_grid_input(ham, grid_offset, offset, norbs):
     # build appriopriate grid
@@ -579,7 +579,7 @@ def test_grid_input(ham, grid_offset, offset, norbs):
 
 def test_grid_offset_passed_to_functions():
     V = lambda x: x
-    grid = Monatomic([[1, ]], offset=[0.5, ])
+    grid = Monatomic([[1, ]], offset=[0.5, ], norbs=1)
     tb = discretize('V(x)', 'x', grid=grid)
     onsite = tb[tb.lattice(0)]
     bools = [np.allclose(onsite(tb.lattice(i), V), V(tb.lattice(i).pos))
@@ -588,11 +588,11 @@ def test_grid_offset_passed_to_functions():
 
 
 @pytest.mark.parametrize("ham, coords, grid", [
-    ("k_x", None, Monatomic([[1, 0]])),
-    ("k_x", 'xy', Monatomic([[1, 0]])),
+    ("k_x", None, Monatomic([[1, 0]], norbs=1)),
+    ("k_x", 'xy', Monatomic([[1, 0]], norbs=1)),
     ("k_x", None, Monatomic([[1, ]], norbs=2)),
     ("k_x * eye(2)", None, Monatomic([[1, ]], norbs=1)),
-    ("k_x+k_y", None, Monatomic([[1, 0], [1, 1]])),
+    ("k_x+k_y", None, Monatomic([[1, 0], [1, 1]], norbs=1)),
 ])
 def test_grid_constraints(ham, coords, grid):
     with pytest.raises(ValueError):
@@ -606,7 +606,7 @@ def test_check_symbol_names(name):
 
 
 def test_rectangular_grid():
-    lat = Monatomic([[1, 0], [0, 2]])
+    lat = Monatomic([[1, 0], [0, 2]], norbs=1)
 
     tb = discretize("V(x, y)", 'xy', grid=lat)
     assert np.allclose(tb[lat(0, 0)](lat(1, 0), lambda x, y: x), 1)
diff --git a/kwant/linalg/tests/test_mumps.py b/kwant/linalg/tests/test_mumps.py
index b28e6f1e9495375db69427b270c8d86008328978..c2d3b56f157a5ee4bd76f5d800e0f4c012f8b100 100644
--- a/kwant/linalg/tests/test_mumps.py
+++ b/kwant/linalg/tests/test_mumps.py
@@ -65,7 +65,7 @@ def test_schur_complement_with_dense():
 def test_error_minus_9(r=10):
     """Test if MUMPSError -9 is properly caught by increasing memory"""
 
-    graphene = honeycomb()
+    graphene = honeycomb(norbs=1)
     a, b = graphene.sublattices
 
     def circle(pos):
diff --git a/kwant/physics/tests/test_dispersion.py b/kwant/physics/tests/test_dispersion.py
index a42d6deadf5d88bb0390318cb5442f88229742dc..745e58b842ca8d6d0119b0d7f79c8e907d7c8d23 100644
--- a/kwant/physics/tests/test_dispersion.py
+++ b/kwant/physics/tests/test_dispersion.py
@@ -17,7 +17,7 @@ from math import pi, cos, sin
 
 def make_lead():
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[[lat(0, 0), lat(0, 1)]] = 3
     syst[lat(0, 1), lat(0, 0)] = -1
     syst[((lat(1, y), lat(0, y)) for y in range(2))] = -1
@@ -35,7 +35,7 @@ def test_band_energies(N=5):
 
 def test_same_as_lead():
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1,)))
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst[lat(0)] = 0
     syst[lat(0), lat(1)] = complex(cos(0.2), sin(0.2))
 
@@ -49,7 +49,7 @@ def test_same_as_lead():
 
 def test_raise_nonhermitian():
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1,)))
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst[lat(0)] = 1j
     syst[lat(0), lat(1)] = complex(cos(0.2), sin(0.2))
     syst = syst.finalized()
@@ -58,7 +58,7 @@ def test_raise_nonhermitian():
 
 def test_band_velocities():
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[lat(0, 0)] = 1
     syst[lat(0, 1)] = 3
     syst[lat(1, 0), lat(0, 0)] = -1
@@ -75,7 +75,7 @@ def test_band_velocities():
 
 def test_band_velocity_derivative():
     syst = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[lat(0, 0)] = 1
     syst[lat(0, 1)] = 3
     syst[lat(1, 0), lat(0, 0)] = -1
diff --git a/kwant/physics/tests/test_leads.py b/kwant/physics/tests/test_leads.py
index e7994941f9e7375d2b292fe8163ace4df3138553..a3b795a27f1070db02db02c6d3fe54f5dad6ad9b 100644
--- a/kwant/physics/tests/test_leads.py
+++ b/kwant/physics/tests/test_leads.py
@@ -267,7 +267,7 @@ def test_modes():
 
 def test_modes_bearded_ribbon():
     # Check if bearded graphene ribbons work.
-    lat = kwant.lattice.honeycomb()
+    lat = kwant.lattice.honeycomb(norbs=1)
     syst = kwant.Builder(kwant.TranslationalSymmetry((1, 0)))
     syst[lat.shape((lambda pos: -20 < pos[1] < 20),
                   (0, 0))] = 0.3
@@ -417,7 +417,7 @@ def test_zero_hopping():
 
 def make_clean_lead(W, E, t):
     syst = kwant.Builder(kwant.TranslationalSymmetry((1, 0)))
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[(lat(0, j) for j in range(W))] = E
     syst[lat.neighbors()] = -t
     return syst.finalized()
diff --git a/kwant/physics/tests/test_noise.py b/kwant/physics/tests/test_noise.py
index 144a298f7173d3ea13b5a00b00e8868353cc1a10..6235c2abf72df72c8b85a1850723b42892275013 100644
--- a/kwant/physics/tests/test_noise.py
+++ b/kwant/physics/tests/test_noise.py
@@ -14,7 +14,7 @@ from kwant.physics import two_terminal_shotnoise
 from kwant._common import ensure_rng
 
 n = 5
-chain = kwant.lattice.chain()
+chain = kwant.lattice.chain(norbs=2)
 
 def twoterminal_system():
     rng = ensure_rng(11)
diff --git a/kwant/solvers/tests/_test_sparse.py b/kwant/solvers/tests/_test_sparse.py
index 8b2efa92b5da98727afea6fd3b7e27d3e36ddd4f..84748086c5bdeb65a68ae35984a63580f4465b81 100644
--- a/kwant/solvers/tests/_test_sparse.py
+++ b/kwant/solvers/tests/_test_sparse.py
@@ -15,8 +15,8 @@ import kwant
 from kwant._common import ensure_rng
 
 n = 5
-chain = kwant.lattice.chain()
-sq = square = kwant.lattice.square()
+chain = kwant.lattice.chain(norbs=1)
+sq = square = kwant.lattice.square(norbs=1)
 
 
 class LeadWithOnlySelfEnergy:
@@ -428,7 +428,7 @@ def test_selfenergy_reflection(greens_function, smatrix):
 
 def test_very_singular_leads(smatrix):
     syst = kwant.Builder()
-    chain = kwant.lattice.chain()
+    chain = kwant.lattice.chain(norbs=2)
     left_lead = kwant.Builder(kwant.TranslationalSymmetry((-1,)))
     right_lead = kwant.Builder(kwant.TranslationalSymmetry((1,)))
     syst[chain(0)] = left_lead[chain(0)] = right_lead[chain(0)] = np.identity(2)
@@ -443,7 +443,7 @@ def test_very_singular_leads(smatrix):
 
 def test_ldos(ldos):
     syst = kwant.Builder()
-    chain = kwant.lattice.chain()
+    chain = kwant.lattice.chain(norbs=1)
     lead = kwant.Builder(kwant.TranslationalSymmetry(chain.vec((1,))))
     syst[chain(0)] = syst[chain(1)] = lead[chain(0)] = 0
     syst[chain(0), chain(1)] = lead[chain(0), chain(1)] = 1
diff --git a/kwant/tests/test_builder.py b/kwant/tests/test_builder.py
index 3885940a6147bbaed2720949c0814459286abe09..7ba00b403513ffe3100acd184820adf1c788ed15 100644
--- a/kwant/tests/test_builder.py
+++ b/kwant/tests/test_builder.py
@@ -28,7 +28,7 @@ def test_bad_keys():
     def setitem(key):
         syst[key] = None
 
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     syst = builder.Builder()
 
     failures = [
@@ -97,9 +97,9 @@ def test_bad_keys():
 
 def test_site_families():
     syst = builder.Builder()
-    fam = builder.SimpleSiteFamily()
-    ofam = builder.SimpleSiteFamily()
-    yafam = builder.SimpleSiteFamily('another_name')
+    fam = builder.SimpleSiteFamily(norbs=1)
+    ofam = builder.SimpleSiteFamily(norbs=1)
+    yafam = builder.SimpleSiteFamily('another_name', norbs=1)
 
     syst[fam(0)] = 7
     assert syst[fam(0)] == 7
@@ -162,7 +162,7 @@ class VerySimpleSymmetry(builder.Symmetry):
 # made.
 def check_construction_and_indexing(sites, sites_fd, hoppings, hoppings_fd,
                                     unknown_hoppings, sym=None):
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     syst = builder.Builder(sym)
     t, V = 1.0j, 0.0
     syst[sites] = V
@@ -212,7 +212,7 @@ def check_construction_and_indexing(sites, sites_fd, hoppings, hoppings_fd,
 
 def test_construction_and_indexing():
     # Without symmetry
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     sites = [fam(0, 0), fam(0, 1), fam(1, 0)]
     hoppings = [(fam(0, 0), fam(0, 1)),
                 (fam(0, 1), fam(1, 0)),
@@ -250,7 +250,7 @@ def test_hermitian_conjugation():
             raise ValueError
 
     syst = builder.Builder()
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     syst[fam(0)] = syst[fam(1)] = ta.identity(2)
 
     syst[fam(0), fam(1)] = f
@@ -266,7 +266,7 @@ def test_hermitian_conjugation():
 def test_value_equality_and_identity():
     m = ta.array([[1, 2], [3j, 4j]])
     syst = builder.Builder()
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
 
     syst[fam(0)] = m
     syst[fam(1)] = m
@@ -378,7 +378,7 @@ def test_finalization():
 
     # Build scattering region from blueprint and test it.
     syst = builder.Builder()
-    fam = kwant.lattice.general(ta.identity(2))
+    fam = kwant.lattice.general(ta.identity(2), norbs=1)
     for site, value in sr_sites.items():
         syst[fam(*site)] = value
     for hop, value in sr_hops.items():
@@ -488,8 +488,11 @@ def test_site_ranges():
         ranges = syst.finalized().site_ranges
         expected = [(0, lat.norbs, 0), (10, 0, 10 * lat.norbs)]
         assert ranges == expected
-        # poison system with a single site with no norbs defined
-        syst[kwant.lattice.chain()(0)] = 1
+        # poison system with a single site with no norbs defined.
+        # Also catch the deprecation warning.
+        with warnings.catch_warnings():
+            warnings.simplefilter("ignore")
+            syst[kwant.lattice.chain(norbs=None)(0)] = 1
         ranges = syst.finalized().site_ranges
         assert ranges == None
 
@@ -506,7 +509,7 @@ def test_hamiltonian_evaluation():
     edges = [(0, 1), (0, 2), (0, 3), (1, 2)]
 
     syst = builder.Builder()
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     sites = [fam(*tag) for tag in tags]
     syst[(fam(*tag) for tag in tags)] = f_onsite
     syst[((fam(*tags[i]), fam(*tags[j])) for (i, j) in edges)] = f_hopping
@@ -570,7 +573,7 @@ def test_dangling():
         #       / \
         #    3-0---2-4-5  6-7  8
         syst = builder.Builder()
-        fam = builder.SimpleSiteFamily()
+        fam = builder.SimpleSiteFamily(norbs=1)
         syst[(fam(i) for i in range(9))] = None
         syst[[(fam(0), fam(1)), (fam(1), fam(2)), (fam(2), fam(0))]] = None
         syst[[(fam(0), fam(3)), (fam(2), fam(4)), (fam(4), fam(5))]] = None
@@ -596,7 +599,7 @@ def test_dangling():
 
 
 def test_builder_with_symmetry():
-    g = kwant.lattice.general(ta.identity(3))
+    g = kwant.lattice.general(ta.identity(3), norbs=1)
     sym = kwant.TranslationalSymmetry((0, 0, 3), (0, 2, 0))
     syst = builder.Builder(sym)
 
@@ -642,7 +645,7 @@ def test_builder_with_symmetry():
 
 
 def test_fill():
-    g = kwant.lattice.square()
+    g = kwant.lattice.square(norbs=1)
     sym_x = kwant.TranslationalSymmetry((-1, 0))
     sym_xy = kwant.TranslationalSymmetry((-1, 0), (0, 1))
 
@@ -658,7 +661,7 @@ def test_fill():
                        lambda pos: True),
                       (builder.NoSymmetry(),
                        lambda pos: ta.dot(pos, pos) < 17)]:
-        cubic = kwant.lattice.general(ta.identity(3))
+        cubic = kwant.lattice.general(ta.identity(3), norbs=1)
 
         # Make a weird system.
         orig = kwant.Builder(sym)
@@ -769,7 +772,7 @@ def test_fill():
     assert sorted(target.hoppings()) == sorted(should_be_syst.hoppings())
 
     ## test that 'fill' respects the symmetry of the target builder
-    lat = kwant.lattice.chain(a=1)
+    lat = kwant.lattice.chain(a=1, norbs=1)
     template = builder.Builder(kwant.TranslationalSymmetry((-1,)))
     template[lat(0)] = 2
     template[lat.neighbors()] = -1
@@ -796,7 +799,7 @@ def test_fill():
         target.fill(template, lambda x: True, lat(0))
 
     # Test for warning when one of the starting sites is outside the template
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     template = builder.Builder(kwant.TranslationalSymmetry((-1, 0)))
     template[lat(0, 0)] = None
     template[lat.neighbors()] = None
@@ -811,7 +814,7 @@ def test_fill_sticky():
     separately.
     """
     # Generate model template.
-    lat = kwant.lattice.kagome()
+    lat = kwant.lattice.kagome(norbs=1)
     template = kwant.Builder(kwant.TranslationalSymmetry(
         lat.vec((1, 0)), lat.vec((0, 1))))
     for i, sl in enumerate(lat.sublattices):
@@ -844,7 +847,7 @@ def test_fill_sticky():
 
 def test_attach_lead():
     fam = builder.SimpleSiteFamily(norbs=1)
-    fam_noncommensurate = builder.SimpleSiteFamily(name='other')
+    fam_noncommensurate = builder.SimpleSiteFamily(name='other', norbs=1)
 
     syst = builder.Builder()
     syst[fam(1)] = 0
@@ -901,7 +904,7 @@ def test_attach_lead():
 
 
 def test_attach_lead_incomplete_unit_cell():
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst = kwant.Builder()
     lead = kwant.Builder(kwant.TranslationalSymmetry((2,)))
     syst[lat(1)] = lead[lat(0)] = lead[lat(1)] = 0
@@ -912,7 +915,7 @@ def test_attach_lead_incomplete_unit_cell():
 def test_neighbors_not_in_single_domain():
     sr = builder.Builder()
     lead = builder.Builder(VerySimpleSymmetry(-1))
-    fam = builder.SimpleSiteFamily()
+    fam = builder.SimpleSiteFamily(norbs=1)
     sr[(fam(x, y) for x in range(3) for y in range(3) if x >= y)] = 0
     sr[builder.HoppingKind((1, 0), fam)] = 1
     sr[builder.HoppingKind((0, 1), fam)] = 1
@@ -935,7 +938,7 @@ def test_closest():
     rng = ensure_rng(10)
     for sym_dim in range(1, 4):
         for space_dim in range(sym_dim, 4):
-            lat = kwant.lattice.general(ta.identity(space_dim))
+            lat = kwant.lattice.general(ta.identity(space_dim), norbs=1)
 
             # Choose random periods.
             while True:
@@ -967,7 +970,7 @@ def test_closest():
 
 
 def test_update():
-    lat = builder.SimpleSiteFamily()
+    lat = builder.SimpleSiteFamily(norbs=1)
 
     syst = builder.Builder()
     syst[[lat(0,), lat(1,)]] = 1
@@ -1006,8 +1009,8 @@ def test_update():
 # ghgh    hhgh
 #
 def test_HoppingKind():
-    g = kwant.lattice.general(ta.identity(3), name='some_lattice')
-    h = kwant.lattice.general(ta.identity(3), name='another_lattice')
+    g = kwant.lattice.general(ta.identity(3), name='some_lattice', norbs=1)
+    h = kwant.lattice.general(ta.identity(3), name='another_lattice', norbs=1)
     sym = kwant.TranslationalSymmetry((0, 2, 0))
     syst = builder.Builder(sym)
     syst[((h if max(x, y, z) % 2 else g)(x, y, z)
@@ -1047,8 +1050,8 @@ def test_HoppingKind():
 
 
 def test_invalid_HoppingKind():
-    g = kwant.lattice.general(ta.identity(3))
-    h = kwant.lattice.general(np.identity(3)[:-1])  # 2D lattice in 3D
+    g = kwant.lattice.general(ta.identity(3), norbs=1)
+    h = kwant.lattice.general(np.identity(3)[:-1], norbs=1)  # 2D lattice in 3D
 
     delta = (1, 0, 0)
 
@@ -1062,7 +1065,7 @@ def test_invalid_HoppingKind():
 
 
 def test_ModesLead_and_SelfEnergyLead():
-    lat = builder.SimpleSiteFamily()
+    lat = builder.SimpleSiteFamily(norbs=1)
     hoppings = [builder.HoppingKind((1, 0), lat),
                 builder.HoppingKind((0, 1), lat)]
     rng = Random(123)
@@ -1139,7 +1142,7 @@ def test_ModesLead_and_SelfEnergyLead():
 
 
 def test_site_pickle():
-    site = kwant.lattice.square()(0, 0)
+    site = kwant.lattice.square(norbs=1)(0, 0)
     assert pickle.loads(pickle.dumps(site)) == site
 
 
@@ -1202,7 +1205,7 @@ def test_discrete_symmetries():
 # all the deprecation warnings in the test logs
 @pytest.mark.filterwarnings("ignore:.*'args' parameter")
 def test_argument_passing():
-    chain = kwant.lattice.chain()
+    chain = kwant.lattice.chain(norbs=1)
 
     # Test for passing parameters to hamiltonian matrix elements
     def onsite(site, p1, p2):
@@ -1336,7 +1339,7 @@ def test_subs():
         salt = str(b) + str(c)
         return kwant.digest.uniform(ta.array((sitea.tag, siteb.tag)), salt=salt)
 
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
 
     def make_system(sym=kwant.builder.NoSymmetry(), n=3):
         syst = kwant.Builder(sym)
@@ -1389,7 +1392,7 @@ def test_subs():
     assert lead.parameters == {'lead_a', 'lead_b', 'lead_c'}
 
 def test_attach_stores_padding():
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst = kwant.Builder()
     syst[lat(0)] = 0
     lead = kwant.Builder(kwant.TranslationalSymmetry(lat.prim_vecs[0]))
@@ -1400,7 +1403,7 @@ def test_attach_stores_padding():
 
 
 def test_finalization_preserves_padding():
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst = kwant.Builder()
     for i in range(10):
         syst[lat(i)] = 0
@@ -1420,7 +1423,7 @@ def test_finalization_preserves_padding():
 
 def test_add_peierls_phase():
 
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst = kwant.Builder()
     syst[(lat(i, j) for i in range(5) for j in range(5))] = 4
     syst[lat.neighbors()] = lambda a, b, t: -t
diff --git a/kwant/tests/test_comprehensive.py b/kwant/tests/test_comprehensive.py
index 9989bf59fca3d7f9d76a2f0d862e064cdca26316..11f82ae30cb154488dca10c3263262fdc0c6feb7 100644
--- a/kwant/tests/test_comprehensive.py
+++ b/kwant/tests/test_comprehensive.py
@@ -18,7 +18,7 @@ def test_qhe(W=16, L=8):
         x, y = pos
         return -L < x < L and abs(y) < W - 5.5 * math.exp(-x**2 / 5**2)
 
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst = kwant.Builder()
 
     syst[lat.shape(central_region, (0, 0))] = onsite
diff --git a/kwant/tests/test_lattice.py b/kwant/tests/test_lattice.py
index e803514b9057460b91e1fd9bc76930e903bed74b..5e7a9976ed74ef881ece72ada167c48c39f8ff13 100644
--- a/kwant/tests/test_lattice.py
+++ b/kwant/tests/test_lattice.py
@@ -6,6 +6,7 @@
 # the file AUTHORS.rst at the top-level directory of this distribution and at
 # http://kwant-project.org/authors.
 
+import warnings
 from math import sqrt
 import numpy as np
 import tinyarray as ta
@@ -17,40 +18,42 @@ import pytest
 
 def test_closest():
     rng = ensure_rng(4)
-    lat = lattice.general(((1, 0), (0.5, sqrt(3)/2)))
+    lat = lattice.general(((1, 0), (0.5, sqrt(3)/2)), norbs=1)
     for i in range(50):
         point = 20 * rng.random_sample(2)
         closest = lat(*lat.closest(point)).pos
         assert np.linalg.norm(point - closest) <= 1 / sqrt(3)
-    lat = lattice.general(rng.randn(3, 3))
+    lat = lattice.general(rng.randn(3, 3), norbs=1)
     for i in range(50):
         tag = rng.randint(10, size=(3,))
         assert lat.closest(lat(*tag).pos) == tag
 
 
 def test_general():
-    for lat in (lattice.general(((1, 0), (0.5, 0.5))),
+    for lat in (lattice.general(((1, 0), (0.5, 0.5)), norbs=1),
                 lattice.general(((1, 0), (0.5, sqrt(3)/2)),
-                                     ((0, 0), (0, 1/sqrt(3))))):
+                                ((0, 0), (0, 1/sqrt(3))),
+                                norbs=1,
+                               )):
         for sl in lat.sublattices:
             tag = (-5, 33)
             site = sl(*tag)
             assert tag == sl.closest(site.pos)
 
     # Test 2D lattice with 1 vector.
-    lat = lattice.general([[1, 0]])
+    lat = lattice.general([[1, 0]], norbs=1)
     site = lat(0)
     raises(ValueError, lat, 0, 1)
 
 
 def test_neighbors():
-    lat = lattice.honeycomb(1e-10)
+    lat = lattice.honeycomb(1e-10, norbs=1)
     num_nth_nearest = [len(lat.neighbors(n)) for n in range(5)]
     assert num_nth_nearest == [2, 3, 6, 3, 6]
-    lat = lattice.general([(0, 1e8, 0, 0), (0, 0, 1e8, 0)])
+    lat = lattice.general([(0, 1e8, 0, 0), (0, 0, 1e8, 0)], norbs=1)
     num_nth_nearest = [len(lat.neighbors(n)) for n in range(5)]
     assert num_nth_nearest == [1, 2, 2, 2, 4]
-    lat = lattice.chain(1e-10)
+    lat = lattice.chain(1e-10, norbs=1)
     num_nth_nearest = [len(lat.neighbors(n)) for n in range(5)]
     assert num_nth_nearest == 5 * [1]
 
@@ -59,7 +62,7 @@ def test_shape():
     def in_circle(pos):
         return pos[0] ** 2 + pos[1] ** 2 < 3
 
-    lat = lattice.honeycomb()
+    lat = lattice.honeycomb(norbs=1)
     sites = list(lat.shape(in_circle, (0, 0))())
     sites_alt = list()
     sl0, sl1 = lat.sublattices
@@ -88,7 +91,7 @@ def test_wire():
     vecs = rng.randn(3, 3)
     vecs[0] = [1, 0, 0]
     center = rng.randn(3)
-    lat = lattice.general(vecs, rng.randn(4, 3))
+    lat = lattice.general(vecs, rng.randn(4, 3), norbs=1)
     syst = builder.Builder(lattice.TranslationalSymmetry((2, 0, 0)))
     def wire_shape(pos):
         pos = np.array(pos)
@@ -103,8 +106,8 @@ def test_wire():
 
 def test_translational_symmetry():
     ts = lattice.TranslationalSymmetry
-    f2 = lattice.general(np.identity(2))
-    f3 = lattice.general(np.identity(3))
+    f2 = lattice.general(np.identity(2), norbs=1)
+    f3 = lattice.general(np.identity(3), norbs=1)
     shifted = lambda site, delta: site.family(*ta.add(site.tag, delta))
 
     raises(ValueError, ts, (0, 0, 4), (0, 5, 0), (0, 0, 2))
@@ -112,7 +115,7 @@ def test_translational_symmetry():
     raises(ValueError, sym.add_site_family, f2)
 
     # Test lattices with dimension smaller than dimension of space.
-    f2in3 = lattice.general([[4, 4, 0], [4, -4, 0]])
+    f2in3 = lattice.general([[4, 4, 0], [4, -4, 0]], norbs=1)
     sym = ts((8, 0, 0))
     sym.add_site_family(f2in3)
     sym = ts((8, 0, 1))
@@ -150,7 +153,7 @@ def test_translational_symmetry():
                         (site, shifted(site, hop)))
 
     # Test act for hoppings belonging to different lattices.
-    f2p = lattice.general(2 * np.identity(2))
+    f2p = lattice.general(2 * np.identity(2), norbs=1)
     sym = ts(*(2 * np.identity(2)))
     assert sym.act((1, 1), f2(0, 0), f2p(0, 0)) == (f2(2, 2), f2p(1, 1))
     assert sym.act((1, 1), f2p(0, 0), f2(0, 0)) == (f2p(1, 1), f2(2, 2))
@@ -160,7 +163,7 @@ def test_translational_symmetry():
     # generated symmetry with proper vectors.
     rng = ensure_rng(30)
     vec = rng.randn(3, 5)
-    lat = lattice.general(vec)
+    lat = lattice.general(vec, norbs=1)
     total = 0
     for k in range(1, 4):
         for i in range(10):
@@ -176,7 +179,7 @@ def test_translational_symmetry():
 
 def test_translational_symmetry_reversed():
     rng = ensure_rng(30)
-    lat = lattice.general(np.identity(3))
+    lat = lattice.general(np.identity(3), norbs=1)
     sites = [lat(i, j, k) for i in range(-2, 6) for j in range(-2, 6)
                           for k in range(-2, 6)]
     for i in range(4):
@@ -194,9 +197,9 @@ def test_translational_symmetry_reversed():
 
 
 def test_monatomic_lattice():
-    lat = lattice.square()
-    lat2 = lattice.general(np.identity(2))
-    lat3 = lattice.square(name='no')
+    lat = lattice.square(norbs=1)
+    lat2 = lattice.general(np.identity(2), norbs=1)
+    lat3 = lattice.square(name='no', norbs=1)
     assert len(set([lat, lat2, lat3, lat(0, 0), lat2(0, 0), lat3(0, 0)])) == 4
 
 @pytest.mark.parametrize('prim_vecs, basis', [
@@ -210,16 +213,22 @@ def test_monatomic_lattice():
 ])
 def test_lattice_constraints(prim_vecs, basis):
     with pytest.raises(ValueError):
-        lattice.general(prim_vecs, basis)
+        lattice.general(prim_vecs, basis, norbs=1)
 
 
 def test_norbs():
     id_mat = np.identity(2)
     # Monatomic lattices
-    assert lattice.general(id_mat).norbs == None
+    # Catch deprecation warning
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore")
+        assert lattice.general(id_mat).norbs == None
     assert lattice.general(id_mat, norbs=2).norbs == 2
     # Polyatomic lattices
-    lat = lattice.general(id_mat, basis=id_mat, norbs=None)
+    # Catch deprecation warning
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore")
+        lat = lattice.general(id_mat, basis=id_mat, norbs=None)
     for l in lat.sublattices:
         assert l.norbs == None
     lat = lattice.general(id_mat, basis=id_mat, norbs=2)
@@ -237,8 +246,14 @@ def test_norbs():
     raises(ValueError, lattice.general, id_mat, norbs=1.5)
     raises(ValueError, lattice.general, id_mat, id_mat, norbs=1.5)
     raises(ValueError, lattice.general, id_mat, id_mat, norbs=[1.5, 1.5])
+    # should raise ValueError if norbs is <= 0
+    raises(ValueError, lattice.general, id_mat, norbs=0)
+    raises(ValueError, lattice.general, id_mat, norbs=-1)
     # test that lattices with different norbs are compared `not equal`
-    lat = lattice.general(id_mat, basis=id_mat, norbs=None)
+    # Catch deprecation warning
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore")
+        lat = lattice.general(id_mat, basis=id_mat, norbs=None)
     lat1 = lattice.general(id_mat, basis=id_mat, norbs=1)
     lat2 = lattice.general(id_mat, basis=id_mat, norbs=2)
     assert lat != lat1
@@ -247,7 +262,7 @@ def test_norbs():
 
 
 def test_symmetry_act():
-    lat = lattice.square()
+    lat = lattice.square(norbs=1)
     sym = lattice.TranslationalSymmetry((1, 0), (0, 1))
     site = lat(0, 0)
     hopping = (lat(0, 0), lat(1, 0))
diff --git a/kwant/tests/test_operator.py b/kwant/tests/test_operator.py
index 6bb05593f2237ae1599d0ea24d124c9d4ca0efd0..bb8a185e6675356d90552ee3d21b06d241fda83c 100644
--- a/kwant/tests/test_operator.py
+++ b/kwant/tests/test_operator.py
@@ -6,6 +6,7 @@
 # the file AUTHORS.rst at the top-level directory of this distribution and at
 # http://kwant-project.org/authors.
 
+import warnings
 import functools as ft
 from collections import deque
 import pickle
@@ -59,7 +60,10 @@ def test_operator_construction():
     N = len(fsyst.sites)
 
     # test construction failure if norbs not given
-    latnone = kwant.lattice.chain()
+    # Catch deprecation warning
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore")
+        latnone = kwant.lattice.chain()
     syst[latnone(0)] = 1
     for A in opservables:
         raises(ValueError, A, syst.finalized())
diff --git a/kwant/tests/test_plotter.py b/kwant/tests/test_plotter.py
index a8358284528c23ea5c70e7adbcadfe3177a151db..9edc902748c20d14372a881dda0093a68ac27a20 100644
--- a/kwant/tests/test_plotter.py
+++ b/kwant/tests/test_plotter.py
@@ -91,7 +91,7 @@ def syst_2d(W=3, r1=3, r2=8):
 
 
 def syst_3d(W=3, r1=2, r2=4, a=1, t=1.0):
-    lat = kwant.lattice.general(((a, 0, 0), (0, a, 0), (0, 0, a)))
+    lat = kwant.lattice.general(((a, 0, 0), (0, a, 0), (0, 0, a)), norbs=1)
     syst = kwant.Builder()
 
     def ring(pos):
@@ -162,7 +162,8 @@ def test_plot_more_site_families_than_colors():
     # https://gitlab.kwant-project.org/kwant/kwant/issues/257
     ncolors = len(pyplot.rcParams['axes.prop_cycle'])
     syst = kwant.Builder()
-    lattices = [kwant.lattice.square(name=i) for i in range(ncolors + 1)]
+    lattices = [kwant.lattice.square(name=i, norbs=1)
+                for i in range(ncolors + 1)]
     for i, lat in enumerate(lattices):
         syst[lat(i, 0)] = None
     with tempfile.TemporaryFile('w+b') as out:
@@ -172,7 +173,7 @@ def test_plot_more_site_families_than_colors():
 @pytest.mark.skipif(not _plotter.mpl_available, reason="Matplotlib unavailable.")
 def test_plot_raises_on_bad_site_spec():
     syst = kwant.Builder()
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[(lat(i, j) for i in range(5) for j in range(5))] = None
 
     # Cannot provide site_size as an array when syst is a Builder
@@ -252,7 +253,7 @@ def test_spectrum():
     def ham_2d(a, b, c):
         return np.eye(2) * (a**2 + b**2 + c**2)
 
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst = kwant.Builder()
     syst[(lat(i) for i in range(3))] = lambda site, a, b: a + b
     syst[lat.neighbors()] = lambda site1, site2, c: c
@@ -376,7 +377,7 @@ def _border_is_0(field):
 def _test_border_0(interpolator):
     ## Test that current is always identically zero at box boundaries
     syst = kwant.Builder()
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst[[lat(0, 0), lat(1, 0)]] = None
     syst[(lat(0, 0), lat(1, 0))] = None
     syst = syst.finalized()
@@ -503,7 +504,7 @@ def test_current_interpolation():
 
     ### Tests on a divergence-free current (closed system)
 
-    lat = kwant.lattice.general([(1, 0), (0.5, np.sqrt(3) / 2)])
+    lat = kwant.lattice.general([(1, 0), (0.5, np.sqrt(3) / 2)], norbs=1)
     syst = kwant.Builder()
     sites = [lat(0, 0), lat(1, 0), lat(0, 1), lat(2, 2)]
     syst[sites] = None
diff --git a/kwant/tests/test_system.py b/kwant/tests/test_system.py
index 7b3241935f04816ca955bb8e918ec1dbf3023edf..9bba152bc881013cd57bc949f46fca3244aa4153 100644
--- a/kwant/tests/test_system.py
+++ b/kwant/tests/test_system.py
@@ -17,7 +17,7 @@ from kwant._common import ensure_rng
 
 def test_hamiltonian_submatrix():
     syst = kwant.Builder()
-    chain = kwant.lattice.chain()
+    chain = kwant.lattice.chain(norbs=1)
     for i in range(3):
         syst[chain(i)] = 0.5 * i
     for i in range(2):
@@ -87,7 +87,7 @@ def test_hamiltonian_submatrix():
 def test_pickling():
     syst = kwant.Builder()
     lead = kwant.Builder(symmetry=kwant.TranslationalSymmetry([1.]))
-    lat = kwant.lattice.chain()
+    lat = kwant.lattice.chain(norbs=1)
     syst[lat(0)] = syst[lat(1)] = 0
     syst[lat(0), lat(1)] = 1
     lead[lat(0)] = syst[lat(1)] = 0
diff --git a/kwant/tests/test_wraparound.py b/kwant/tests/test_wraparound.py
index aa53e1c3268043e8334bf8081754b5d24ef3f469..90014b603c69093a1f76e000e7953b5352ef9c34 100644
--- a/kwant/tests/test_wraparound.py
+++ b/kwant/tests/test_wraparound.py
@@ -37,7 +37,8 @@ def _simple_syst(lat, E=0, t=1+1j, sym=None):
 
 def test_consistence_with_bands(kx=1.9, nkys=31):
     kys = np.linspace(-np.pi, np.pi, nkys)
-    for lat in [kwant.lattice.honeycomb(), kwant.lattice.square()]:
+    for lat in [kwant.lattice.honeycomb(norbs=1),
+                kwant.lattice.square(norbs=1)]:
         syst = _simple_syst(lat)
         wa_keep_1 = wraparound(syst, keep=1).finalized()
         wa_keep_none = wraparound(syst).finalized()
@@ -56,7 +57,7 @@ def test_consistence_with_bands(kx=1.9, nkys=31):
 
 
 def test_opposite_hoppings():
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
 
     for val in [1j, lambda a, b: 1j]:
         syst = kwant.Builder(kwant.TranslationalSymmetry((1, 1)))
@@ -74,7 +75,8 @@ def test_opposite_hoppings():
 def test_value_types(k=(-1.1, 0.5), E=2, t=1):
     k = dict(zip(('k_x', 'k_y', 'k_z'), k))
     sym_extents = [1, 2, 3]
-    lattices = [kwant.lattice.honeycomb(), kwant.lattice.square()]
+    lattices = [kwant.lattice.honeycomb(norbs=1),
+                kwant.lattice.square(norbs=1)]
     lat_syms = [
         (lat, kwant.TranslationalSymmetry(lat.vec((n, 0)), lat.vec((0, n))))
         for n, lat in itertools.product(sym_extents, lattices)
@@ -112,7 +114,7 @@ def test_value_types(k=(-1.1, 0.5), E=2, t=1):
 
 
 def test_signatures():
-    lat = kwant.lattice.square()
+    lat = kwant.lattice.square(norbs=1)
     syst = kwant.Builder(kwant.TranslationalSymmetry((-3, 0), (0, 1)))
     # onsites and hoppings that will be bound as sites
     syst[lat(-2, 0)] = 4
@@ -162,7 +164,7 @@ def test_signatures():
 
 
 def test_symmetry():
-    syst = _simple_syst(kwant.lattice.square())
+    syst = _simple_syst(kwant.lattice.square(norbs=1))
 
     matrices = [np.random.rand(2, 2) for i in range(4)]
     laws = (matrices, [(lambda a: m) for m in matrices])
@@ -190,10 +192,10 @@ def test_symmetry():
 
 @pytest.mark.skipif(not _plotter.mpl_available, reason="Matplotlib unavailable.")
 def test_plot_2d_bands():
-    chain = kwant.lattice.chain()
-    square = kwant.lattice.square()
-    cube = kwant.lattice.general([(1, 0, 0), (0, 1, 0), (0, 0, 1)])
-    hc = kwant.lattice.honeycomb()
+    chain = kwant.lattice.chain(norbs=1)
+    square = kwant.lattice.square(norbs=1)
+    cube = kwant.lattice.general([(1, 0, 0), (0, 1, 0), (0, 0, 1)], norbs=1)
+    hc = kwant.lattice.honeycomb(norbs=1)
 
     syst_1d = kwant.Builder(kwant.TranslationalSymmetry(*chain._prim_vecs))
     syst_1d[chain(0)] = 2
@@ -245,7 +247,7 @@ def test_fd_mismatch():
     # around in all directions, but could not be wrapped around when 'keep' is
     # provided.
     sqrt3 = np.sqrt(3)
-    lat = kwant.lattice.general([(sqrt3, 0), (-sqrt3/2, 1.5)])
+    lat = kwant.lattice.general([(sqrt3, 0), (-sqrt3/2, 1.5)], norbs=1)
     T = kwant.TranslationalSymmetry((sqrt3, 0), (0, 3))
 
     syst1 = kwant.Builder(T)
@@ -269,7 +271,8 @@ def test_fd_mismatch():
     ## Test that spectrum of non-trivial system (including above cases)
     ## is the same, regardless of the way in which it is wrapped around
     lat = kwant.lattice.general([(sqrt3, 0), (-sqrt3/2, 1.5)],
-                                [(sqrt3 / 2, 0.5), (0, 1)])
+                                [(sqrt3 / 2, 0.5), (0, 1)],
+                                norbs=1)
     a, b = lat.sublattices
     T = kwant.TranslationalSymmetry((3 * sqrt3, 0), (0, 3))
     syst = kwant.Builder(T)
@@ -302,7 +305,7 @@ def test_fd_mismatch():
     assert all(np.allclose(E, E[0]) for E in E_k)
 
     # Test square lattice with oblique unit cell
-    lat = kwant.lattice.general(np.eye(2))
+    lat = kwant.lattice.general(np.eye(2), norbs=1)
     translations = kwant.lattice.TranslationalSymmetry([2, 2], [0, 2])
     syst = kwant.Builder(symmetry=translations)
     syst[lat.shape(lambda site: True, [0, 0])] = 1
@@ -314,7 +317,7 @@ def test_fd_mismatch():
 
     # Test Rocksalt structure
     # cubic lattice that contains both sublattices
-    lat = kwant.lattice.general(np.eye(3))
+    lat = kwant.lattice.general(np.eye(3), norbs=1)
     # Builder with FCC translational symmetries.
     translations = kwant.lattice.TranslationalSymmetry([1, 1, 0], [1, 0, 1], [0, 1, 1])
     syst = kwant.Builder(symmetry=translations)
@@ -341,7 +344,7 @@ def test_fd_mismatch():
     def shape(site):
         return abs(site.tag[2]) < 4
 
-    lat = kwant.lattice.general(np.eye(3))
+    lat = kwant.lattice.general(np.eye(3), norbs=1)
     # First choice: primitive UC
     translations = kwant.lattice.TranslationalSymmetry([1, 1, 0], [1, -1, 0], [1, 0, 1])
     syst = kwant.Builder(symmetry=translations)