diff --git a/pkgs/development/web/cypress/cypress-example-kitchensink/README.md b/pkgs/development/web/cypress/cypress-example-kitchensink/README.md
new file mode 100644
index 000000000000..d5a6460ed9f7
--- /dev/null
+++ b/pkgs/development/web/cypress/cypress-example-kitchensink/README.md
@@ -0,0 +1,24 @@
+
+# `cypress-example-kitchensink`
+
+This directory 'packages' [cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink),
+which is used in `cypress.passthru.tests`.
+
+The app is not really intended for deployment, so I didn't bother with actual packaging, just testing.
+If your real-world app looks like `cypress-example-kitchensink`, you'll want to use Nix multiple outputs so you don't deploy your test videos along with your app.
+Alternatively, you can set it up so that one derivation builds your server exe and another derivation takes that server exe and runs it with the cypress e2e tests.
+
+## Peculiarities
+
+**cypress and Cypress** are distinct names.
+  - `cypress` is the npm module, containing the executable `cypress`
+  - whereas the executable `Cypress` comes from `pkgs.cypress`, a binary distribution (as of writing) by cypress.io.
+
+**updateScript** is not provided for this example project. This seems preferable,
+  because updates to it aren't particularly valuable and have a significant overhead.
+  The goal is to smoke test `cypress`; not run the latest test suite (which it isn't anyway).
+
+## Updating
+
+ - update the hash in `src.nix`
+ - run `regen-nix`
diff --git a/pkgs/development/web/cypress/cypress-example-kitchensink/default.nix b/pkgs/development/web/cypress/cypress-example-kitchensink/default.nix
new file mode 100644
index 000000000000..86fec8950002
--- /dev/null
+++ b/pkgs/development/web/cypress/cypress-example-kitchensink/default.nix
@@ -0,0 +1,59 @@
+{ callPackage
+, cypress
+, nodejs-12_x
+, # FIXME: duplicated from ./regen-nix. node2nix should expose this
+  nodePackages
+, xorg
+, pkgs
+, stdenv
+,
+}:
+
+let
+  fromNode2nix = import ./cypress-example-kitchensink.nix {
+    inherit pkgs;
+  };
+
+  nodeDependencies = fromNode2nix.shell.nodeDependencies.overrideAttrs (o: {
+    CYPRESS_INSTALL_BINARY = "0";
+    PUPPETEER_SKIP_DOWNLOAD = "1";
+  });
+
+  fontConfigEtc = (
+    pkgs.nixos { config.fonts.fontconfig.enable = true; }
+  ).config.environment.etc.fonts.source;
+
+in
+stdenv.mkDerivation {
+  name = "cypress-example-kitchensink";
+  src = callPackage ./src.nix { };
+  passthru.fc = fontConfigEtc;
+  nativeBuildInputs = [
+    cypress
+    nodejs-12_x
+    xorg.xorgserver
+    nodePackages.jsonplaceholder
+  ];
+  FONTCONFIG_PATH = fontConfigEtc;
+  postPatch = ''
+    # Use our own offline backend. 15011 means js0n ;)
+    sed -e 's^https://jsonplaceholder.cypress.io^http://localhost:15011^g' -i $(find . -type f)
+  '';
+  buildPhase = ''
+    ln -s ${nodeDependencies}/lib/node_modules ./node_modules
+    PATH="${nodeDependencies}/bin:$PATH"
+    runHook preBuild
+    PORT=15011 jsonplaceholder &
+    # assumption: jsonplaceholder start far quicker than cypress run
+
+    export CYPRESS_RUN_BINARY=${cypress}/bin/Cypress
+    export HOME=$PWD/home
+    mkdir $HOME
+    npm run test
+    runHook postBuild
+  '';
+  installPhase = ''
+    mkdir $out
+    cp -r cypress/videos $out/
+  '';
+}
diff --git a/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix b/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix
new file mode 100755
index 000000000000..86061211d7b3
--- /dev/null
+++ b/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix
@@ -0,0 +1,21 @@
+#!/usr/bin/env nix-shell
+#!nix-shell ./regen-nix.nix
+#!nix-shell -i bash
+
+node2nix \
+  --nodejs-12 \
+  --input $src/package.json \
+  --lock $src/package-lock.json \
+  --composition cypress-example-kitchensink.nix \
+  --development \
+  ;
+
+# node2nix produces opinionated expressions that work for in-repo packaging
+# but aren't ideal for Nixpkgs:
+sed -i cypress-example-kitchensink.nix \
+  -e 's^fetchgit^fetchgit callPackage^'
+sed -i node-packages.nix \
+  -e 's^fetchgit, ^fetchgit, callPackage, ^' \
+  -e 's^src = .*/nix/store/.*-source^src = callPackage ./src.nix {}^' \
+  -e 's^nix-gitignore.gitignoreSourcePure^(ignore: src: src)^' \
+  ;
diff --git a/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix.nix b/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix.nix
new file mode 100644
index 000000000000..f7276c5c2ec4
--- /dev/null
+++ b/pkgs/development/web/cypress/cypress-example-kitchensink/regen-nix.nix
@@ -0,0 +1,8 @@
+{ pkgs ? import ../../../../.. { config = { }; overlays = [ ]; } }:
+
+pkgs.mkShell {
+  nativeBuildInputs = [
+    pkgs.nodePackages.node2nix
+  ];
+  src = pkgs.callPackage ./src.nix { };
+}
diff --git a/pkgs/development/web/cypress/cypress-example-kitchensink/src.nix b/pkgs/development/web/cypress/cypress-example-kitchensink/src.nix
new file mode 100644
index 000000000000..8f9999a704fe
--- /dev/null
+++ b/pkgs/development/web/cypress/cypress-example-kitchensink/src.nix
@@ -0,0 +1,6 @@
+{ fetchFromGitHub }: fetchFromGitHub {
+  owner = "cypress-io";
+  repo = "cypress-example-kitchensink";
+  rev = "1572887a2003c2f35ff46d14f5f1cdfef975c9be";
+  sha256 = "sha256-A7d95b9V707iOzlIg+3nItPPB8HNVVOjPhGqa8MXRPE=";
+}
diff --git a/pkgs/development/web/cypress/default.nix b/pkgs/development/web/cypress/default.nix
index 0b61aa23086f..cf7d3481bf47 100644
--- a/pkgs/development/web/cypress/default.nix
+++ b/pkgs/development/web/cypress/default.nix
@@ -1,4 +1,20 @@
-{ stdenv, lib, fetchzip, autoPatchelfHook, xorg, gtk2, gnome2, gtk3, nss, alsa-lib, udev, unzip, wrapGAppsHook, mesa }:
+{
+  alsa-lib,
+  autoPatchelfHook,
+  callPackage,
+  fetchzip,
+  gnome2,
+  gtk2,
+  gtk3,
+  lib,
+  mesa,
+  nss,
+  stdenv,
+  udev,
+  unzip,
+  wrapGAppsHook,
+  xorg,
+}:
 
 stdenv.mkDerivation rec {
   pname = "cypress";
@@ -9,8 +25,6 @@ stdenv.mkDerivation rec {
     sha256 = "1mr46raha5aqi8ba0cqvyil5z4vcr46hnxqqmpk3fkrr8awd2897";
   };
 
-  passthru.updateScript = ./update.sh;
-
   # don't remove runtime deps
   dontPatchELF = true;
 
@@ -41,6 +55,14 @@ stdenv.mkDerivation rec {
     runHook postInstall
   '';
 
+  passthru = {
+    updateScript = ./update.sh;
+
+    tests = {
+      example = callPackage ./cypress-example-kitchensink {};
+    };
+  };
+
   meta = with lib; {
     description = "Fast, easy and reliable testing for anything that runs in a browser";
     homepage = "https://www.cypress.io";