diff --git a/IHP/Zip/ControllerFunctions.hs b/IHP/Zip/ControllerFunctions.hs
new file mode 100644
--- /dev/null
+++ b/IHP/Zip/ControllerFunctions.hs
@@ -0,0 +1,65 @@
+module IHP.Zip.ControllerFunctions
+( renderZip
+, renderZipUnnamed
+) where
+
+import IHP.Prelude
+import IHP.Controller.Context
+import IHP.ControllerSupport
+import Network.Wai
+import Network.HTTP.Types
+
+import qualified Codec.Archive.Zip as Zip
+
+-- | Sends a ZIP Archive to be downloaded by the browser. The downloaded file will be named after the given file name.
+--
+-- __Example:__
+--
+-- > import IHP.Zip.ControllerFunctions
+-- > import qualified Codec.Archive.Zip as Zip
+-- >
+-- > action ExportAction = do
+-- >     zipArchive <- ["FileA.txt", "FileB.txt"]
+-- >         |> Zip.addFilesToArchive [] Zip.emptyArchive
+-- >
+-- >     renderZip "Export.zip" archive
+--
+--
+-- If you don't care about the downloaded file name, use 'renderZipUnnamed'.
+--
+-- See https://hackage.haskell.org/package/zip-archive-0.4.1/docs/Codec-Archive-Zip.html for full reference of how build a zip archive
+renderZip :: (?context :: ControllerContext, ?request :: Request, ?respond :: Respond) => Text -> Zip.Archive -> IO ()
+renderZip filename archive = respondAndExit $ responseLBS status200 headers (archive |> Zip.fromArchive)
+    where
+        contentType = (hContentType, "application/zip")
+        contentDisposition = (hContentDisposition, "attachment; filename=\"" <> cs filename <> "\"")
+
+        headers :: ResponseHeaders
+        headers = [ contentType, contentDisposition ]
+
+-- | Sends a ZIP Archive to be downloaded by the browser.
+--
+-- __Example:__
+--
+-- > import IHP.Zip.ControllerFunctions
+-- > import qualified Codec.Archive.Zip as Zip
+-- >
+-- > action ExportAction = do
+-- >     zipArchive <- ["FileA.txt", "FileB.txt"]
+-- >         |> Zip.addFilesToArchive [] Zip.emptyArchive
+-- >
+-- >     renderZipUnnamed archive
+--
+-- To name the downloaded file, use 'renderZip'.
+--
+-- See https://hackage.haskell.org/package/zip-archive-0.4.1/docs/Codec-Archive-Zip.html for full reference of how build a zip archive
+renderZipUnnamed :: (?context :: ControllerContext, ?request :: Request, ?respond :: Respond) => Zip.Archive -> IO ()
+renderZipUnnamed archive = respondAndExit $ responseLBS status200 headers (archive |> Zip.fromArchive)
+    where
+        contentType = (hContentType, "application/zip")
+        contentDisposition = (hContentDisposition, "attachment;")
+
+        headers :: ResponseHeaders
+        headers = [ contentType, contentDisposition ]
+
+hContentDisposition = "Content-Disposition"
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2020 digitally induced GmbH
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+# Support for making ZIP Archives with IHP
+
+## Install
+
+
+1. Add `ihp-zip` and `zip-archive` to the `haskellDeps` in your `default.nix`:
+    ```nix
+    let
+        ...
+        haskellEnv = import "${ihp}/NixSupport/default.nix" {
+            ihp = ihp;
+            haskellDeps = p: with p; [
+                # ...
+                ihp-zip
+                zip-archive
+            ];
+        ...
+    ```
+2. Run `make -B .envrc`
+3. Add `IHP.Zip.ControllerFunctions` to your `Web.Controller.Prelude`:
+    ```haskell
+    module Web.Controller.Prelude
+    ( module Web.Types
+    , module Application.Helper.Controller
+    , module IHP.ControllerPrelude
+    , module Generated.Types
+    , module IHP.Zip.ControllerFunctions -- <------- ADD THIS EXPORT
+    )
+    where
+
+    import Web.Types
+    import Application.Helper.Controller
+    import IHP.ControllerPrelude
+    import Generated.Types
+    import IHP.Zip.ControllerFunctions -- <----- ADD THIS IMPORT
+    ```
+## Usage
+
+In your action use it like this:
+
+```haskell
+module Web.Controller.Users where
+
+import Web.Controller.Prelude
+
+import qualified Codec.Archive.Zip as Zip
+
+instance Controller UsersController where
+    action ExportAction = do
+        archive <- ["FileA", "FileB"]
+                |> Zip.addFilesToArchive [] Zip.emptyArchive
+
+        renderZip "Export.zip" archive
+````
diff --git a/ihp-zip.cabal b/ihp-zip.cabal
new file mode 100644
--- /dev/null
+++ b/ihp-zip.cabal
@@ -0,0 +1,64 @@
+cabal-version:       2.2
+name:                ihp-zip
+version:             0.1.0
+synopsis:            Support for making ZIP archives with IHP
+description:         Provides the @renderZip@ / @renderZipUnnamed@ controller
+                     helpers for streaming a @Codec.Archive.Zip.Archive@
+                     back to the browser as the response of an IHP action.
+license:             MIT
+license-file:        LICENSE
+author:              digitally induced GmbH
+maintainer:          hello@digitallyinduced.com
+homepage:            https://ihp.digitallyinduced.com/
+bug-reports:         https://github.com/digitallyinduced/ihp-zip/issues
+copyright:           (c) digitally induced GmbH
+category:            Web, IHP
+build-type:          Simple
+extra-source-files:  README.md
+
+source-repository head
+    type:     git
+    location: https://github.com/digitallyinduced/ihp-zip
+
+library
+    default-language: GHC2021
+    build-depends:
+          base        >= 4.17 && < 4.22
+        , ihp         >= 1.5  && < 2
+        , zip-archive >= 0.4  && < 0.5
+        , wai         >= 3.2  && < 3.3
+        , http-types  >= 0.12 && < 0.13
+    default-extensions:
+        OverloadedStrings
+        , NoImplicitPrelude
+        , ImplicitParams
+        , Rank2Types
+        , NamedFieldPuns
+        , TypeSynonymInstances
+        , FlexibleInstances
+        , DisambiguateRecordFields
+        , DuplicateRecordFields
+        , OverloadedLabels
+        , FlexibleContexts
+        , DataKinds
+        , QuasiQuotes
+        , TypeFamilies
+        , PackageImports
+        , ScopedTypeVariables
+        , RecordWildCards
+        , TypeApplications
+        , InstanceSigs
+        , DeriveGeneric
+        , MultiParamTypeClasses
+        , TypeOperators
+        , DeriveDataTypeable
+        , DefaultSignatures
+        , BangPatterns
+        , FunctionalDependencies
+        , PartialTypeSignatures
+        , BlockArguments
+        , LambdaCase
+        , StandaloneDeriving
+    hs-source-dirs: .
+    exposed-modules:
+        IHP.Zip.ControllerFunctions
