diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..750baebf4151eb52e380f15cf6a33a059527db79
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+result
+result-*
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..f0b6290635dd71110ea95f96a300390b869222a7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2019 Nikolay Korotkiy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9cd4a2f3ec566f618a197b765f8c986af8bd32a5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# nur-packages
+
+**My personal [NUR](https://github.com/nix-community/NUR) repository**
diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..6f83b9c7418b3be1b597737ebcca42ab45cb5ff6
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,12 @@
+{ pkgs ? import <nixpkgs> {} }:
+
+with pkgs;
+
+let
+  sources = import ./nix/sources.nix;
+in
+{
+  datamaps = callPackage ./pkgs/datamaps { inherit (sources) datamaps; };
+  mbutil = python3Packages.callPackage ./pkgs/mbutil { inherit (sources) mbutil; };
+  gpx-layer = perlPackages.callPackage ./pkgs/gpx-layer { inherit (sources) gpx-layer; };
+}
diff --git a/nix/sources.json b/nix/sources.json
new file mode 100644
index 0000000000000000000000000000000000000000..907db16c97f25228d20f4468f05f86e9f71bee12
--- /dev/null
+++ b/nix/sources.json
@@ -0,0 +1,38 @@
+{
+    "datamaps": {
+        "branch": "master",
+        "description": "Indexes points and lines and generates map tiles to display them",
+        "homepage": null,
+        "owner": "ericfischer",
+        "repo": "datamaps",
+        "rev": "76e620adabbedabd6866b23b30c145b53bae751e",
+        "sha256": "1rdqbyfmgidiv4aqy1s6llls304dxbg5226c7k622smd2rnda2jk",
+        "type": "tarball",
+        "url": "https://github.com/ericfischer/datamaps/archive/76e620adabbedabd6866b23b30c145b53bae751e.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "gpx-layer": {
+        "branch": "master",
+        "description": "Tools to turn GPX files into a GPS map tracing layer",
+        "homepage": null,
+        "owner": "ericfischer",
+        "repo": "gpx-layer",
+        "rev": "746b4723cf1f69fb86d45cf2d4efeaae9e711d2d",
+        "sha256": "0v5vfjqm5flmr30mpgabjwzy4avxl620051pcw03sdf3za8xkpr3",
+        "type": "tarball",
+        "url": "https://github.com/ericfischer/gpx-layer/archive/746b4723cf1f69fb86d45cf2d4efeaae9e711d2d.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "mbutil": {
+        "branch": "master",
+        "description": "Importer and Exporter of MBTiles",
+        "homepage": "http://mapbox.com/developers/",
+        "owner": "mapbox",
+        "repo": "mbutil",
+        "rev": "2fc4161f9be890a65d07f5e7b2ed0c8a0a123ed6",
+        "sha256": "1z48iispxg5mfch86f06amdaqy5mnpq6vsyrp8znspjsvr7s4r3r",
+        "type": "tarball",
+        "url": "https://github.com/mapbox/mbutil/archive/2fc4161f9be890a65d07f5e7b2ed0c8a0a123ed6.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    }
+}
diff --git a/nix/sources.nix b/nix/sources.nix
new file mode 100644
index 0000000000000000000000000000000000000000..2de89a6a4ea350ffb8e5e33cf7cfbac9c719fbb3
--- /dev/null
+++ b/nix/sources.nix
@@ -0,0 +1,96 @@
+# This file has been generated by Niv.
+
+# A record, from name to path, of the third-party packages
+with rec
+{
+  pkgs =
+    if hasNixpkgsPath
+    then
+      if hasThisAsNixpkgsPath
+      then import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {}
+      else import <nixpkgs> {}
+    else
+      import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {};
+
+  sources_nixpkgs =
+    if builtins.hasAttr "nixpkgs" sources
+    then sources.nixpkgs
+    else abort
+      ''
+        Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
+        add a package called "nixpkgs" to your sources.json.
+      '';
+
+  # fetchTarball version that is compatible between all the versions of Nix
+  builtins_fetchTarball = { url, sha256 }@attrs:
+    let
+      inherit (builtins) lessThan nixVersion fetchTarball;
+    in
+      if lessThan nixVersion "1.12" then
+        fetchTarball { inherit url; }
+      else
+        fetchTarball attrs;
+
+  # fetchurl version that is compatible between all the versions of Nix
+  builtins_fetchurl = { url, sha256 }@attrs:
+    let
+      inherit (builtins) lessThan nixVersion fetchurl;
+    in
+      if lessThan nixVersion "1.12" then
+        fetchurl { inherit url; }
+      else
+        fetchurl attrs;
+
+  # A wrapper around pkgs.fetchzip that has inspectable arguments,
+  # annoyingly this means we have to specify them
+  fetchzip = { url, sha256 }@attrs: pkgs.fetchzip attrs;
+
+  # A wrapper around pkgs.fetchurl that has inspectable arguments,
+  # annoyingly this means we have to specify them
+  fetchurl = { url, sha256 }@attrs: pkgs.fetchurl attrs;
+
+  hasNixpkgsPath = (builtins.tryEval <nixpkgs>).success;
+  hasThisAsNixpkgsPath =
+    (builtins.tryEval <nixpkgs>).success && <nixpkgs> == ./.;
+
+  sources = builtins.fromJSON (builtins.readFile ./sources.json);
+
+  mapAttrs = builtins.mapAttrs or (
+    f: set: with builtins;
+    listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
+  );
+
+  # borrowed from nixpkgs
+  functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
+  callFunctionWith = autoArgs: f: args:
+    let
+      auto = builtins.intersectAttrs (functionArgs f) autoArgs;
+    in
+      f (auto // args);
+
+  getFetcher = spec:
+    let
+      fetcherName =
+        if builtins.hasAttr "type" spec
+        then builtins.getAttr "type" spec
+        else "builtin-tarball";
+    in
+      builtins.getAttr fetcherName {
+        "tarball" = fetchzip;
+        "builtin-tarball" = builtins_fetchTarball;
+        "file" = fetchurl;
+        "builtin-url" = builtins_fetchurl;
+      };
+};
+# NOTE: spec must _not_ have an "outPath" attribute
+mapAttrs (
+  _: spec:
+    if builtins.hasAttr "outPath" spec
+    then abort
+      "The values in sources.json should not have an 'outPath' attribute"
+    else
+      if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
+      then
+        spec // { outPath = callFunctionWith spec (getFetcher spec) {}; }
+      else spec
+) sources
diff --git a/pkgs/datamaps/default.nix b/pkgs/datamaps/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..983bff6bc95e3e0b516c342f35ea6a0f573a639d
--- /dev/null
+++ b/pkgs/datamaps/default.nix
@@ -0,0 +1,28 @@
+{ stdenv, libpng, pkg-config, datamaps }:
+
+stdenv.mkDerivation rec {
+  pname = "datamaps";
+  version = stdenv.lib.substring 0 7 src.rev;
+  src = datamaps;
+
+  nativeBuildInputs = [ pkg-config ];
+  buildInputs = [ libpng ];
+
+  makeFlags = [ "PREFIX=$(out)" ];
+  enableParallelBuilding = true;
+
+  installPhase = ''
+    install -Dm755 encode $out/bin/datamaps-encode
+    install -Dm755 enumerate $out/bin/datamaps-enumerate
+    install -Dm755 merge $out/bin/datamaps-merge
+    install -Dm755 render $out/bin/datamaps-render
+  '';
+
+  meta = with stdenv.lib; {
+    description = datamaps.description;
+    homepage = https://github.com/ericfischer/datamaps;
+    license = licenses.bsd2;
+    maintainers = with maintainers; [ sikmir ];
+    platforms = platforms.linux ++ platforms.darwin;
+  };
+}
diff --git a/pkgs/gpx-layer/default.nix b/pkgs/gpx-layer/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..2e791a7c678f73600f7a004b16cf0c498d024c83
--- /dev/null
+++ b/pkgs/gpx-layer/default.nix
@@ -0,0 +1,28 @@
+{ lib, buildPerlPackage, XMLParser, gpx-layer }:
+
+buildPerlPackage rec {
+  pname = "gpx-layer";
+  version = lib.substring 0 7 src.rev;
+  src = gpx-layer;
+
+  outputs = [ "out" ];
+
+  propagatedBuildInputs = [ XMLParser ];
+
+  preConfigure = ''
+    patchShebangs .
+    touch Makefile.PL
+  '';
+
+  installPhase = ''
+    install -Dm755 parse-gpx $out/bin/datamaps-parse-gpx
+  '';
+
+  meta = with lib; {
+    description = gpx-layer.description;
+    homepage = "https://github.com/ericfischer/gpx-layer";
+    license = licenses.free;
+    platforms = platforms.unix;
+    maintainers = with maintainers; [ sikmir ];
+  };
+}
diff --git a/pkgs/mbutil/default.nix b/pkgs/mbutil/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..84e95d19a4a69d3ed7eecaee743dea98cfc612ca
--- /dev/null
+++ b/pkgs/mbutil/default.nix
@@ -0,0 +1,18 @@
+{ lib, buildPythonApplication, nose, mbutil }:
+
+buildPythonApplication rec {
+  pname = "mbutil";
+  version = lib.substring 0 7 src.rev;
+  src = mbutil;
+
+  checkInputs = [ nose ];
+  checkPhase = "nosetests";
+
+  meta = with lib; {
+    description = mbutil.description;
+    homepage = "https://github.com/mapbox/mbutil";
+    license = licenses.bsd3;
+    platforms = platforms.unix;
+    maintainers = with maintainers; [ sikmir ];
+  };
+}
