diff --git a/packages/@uppy/transloadit-preset/LICENSE b/packages/@uppy/transloadit-preset/LICENSE
new file mode 100644
index 000000000..c23747330
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Transloadit
+
+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/packages/@uppy/transloadit-preset/README.md b/packages/@uppy/transloadit-preset/README.md
new file mode 100644
index 000000000..2f94dec54
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/README.md
@@ -0,0 +1,81 @@
+# @uppy/transloadit
+
+
+
+
+
+
+The Transloadit plugin can be used to upload files to Transloadit for all kinds of processing, such as transcoding video, resizing images, zipping/unzipping, [and more](https://transloadit.com/services/).
+
+[Try it live →](https://uppy.io/examples/transloadit/)
+
+Uppy is being developed by the folks at [Transloadit](https://transloadit.com), a versatile file encoding service.
+
+## Example
+
+`transloadit.form` attaches Transloadit to an existing HTML form.
+It could act like the jQuery SDK using the `@uppy/file-input` plugin,
+or it could also add the `@uppy/dashboard`.
+Uploads files on form submission, adds results to a hidden input,
+then really submits the form.
+
+```js
+const transloadit = require('@uppy/transloadit-preset')
+
+transloadit.form('#form', {
+ params: {
+ auth: { key: '' },
+ template_id: ''
+ }
+})
+```
+
+Adding Dashboard could be optional, eg
+
+```js
+transloadit.form('#form', {
+ ...
+ dashboard: true // or css selector, true means input[type=file]
+})
+```
+The file input would be replaced by a button that opens the dashboard modal.
+Needs:
+- a way of having a 'Done' button instead of 'Upload' that closes the modal but doesn't trigger upload.
+
+`transloadit.modal` opens the Dashboard and allows the user to select files.
+When the user is done, presses 'upload', files are uploaded and the modal closes.
+Promise resolves with results.
+
+Needs:
+- `{multi: false}` option in core, so that no new files can be added once `upload()` was called
+- `{autoClose: true}` option in dashboard, that closes it once upload is complete
+
+```js
+transloadit.modal({
+ params: {
+ auth: { key: '' },
+ template_id: ''
+ }
+}).then(({ successful, failed }) => {
+ // successful, failed are uppy.upload() result
+ // perhaps it could be assembly status or assembly results instead
+})
+```
+
+## Installation
+
+```bash
+$ npm install @uppy/transloadit --save
+```
+
+We recommend installing from npm and then using a module bundler such as [Webpack](http://webpack.github.io/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/).
+
+Alternatively, you can also use this plugin in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions.
+
+## Documentation
+
+Documentation for this plugin can be found on the [Uppy website](https://uppy.io/docs/transloadit).
+
+## License
+
+[The MIT License](./LICENSE).
diff --git a/packages/@uppy/transloadit-preset/package.json b/packages/@uppy/transloadit-preset/package.json
new file mode 100644
index 000000000..c6287e508
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "@uppy/transloadit-preset",
+ "description": "Transloadit SDK for browsers based on Uppy",
+ "version": "0.0.0",
+ "license": "MIT",
+ "main": "lib/index.js",
+ "jsnext:main": "src/index.js",
+ "types": "types/index.d.ts",
+ "keywords": [
+ "file uploader",
+ "transloadit",
+ "file encoding",
+ "encoding",
+ "file processing",
+ "video encoding",
+ "crop",
+ "resize",
+ "watermark",
+ "uppy",
+ "uppy-plugin"
+ ],
+ "homepage": "https://uppy.io",
+ "bugs": {
+ "url": "https://github.com/transloadit/uppy/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/transloadit/uppy.git"
+ },
+ "dependencies": {
+ "@uppy/core": "0.27.0",
+ "@uppy/dashboard": "0.27.2",
+ "@uppy/form": "0.27.1",
+ "@uppy/transloadit": "0.27.2",
+ "@uppy/utils": "0.27.0"
+ }
+}
diff --git a/packages/@uppy/transloadit-preset/src/addTransloaditPlugin.js b/packages/@uppy/transloadit-preset/src/addTransloaditPlugin.js
new file mode 100644
index 000000000..798a1b577
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/src/addTransloaditPlugin.js
@@ -0,0 +1,23 @@
+const Transloadit = require('@uppy/transloadit')
+
+const transloaditOptionNames = [
+ 'service',
+ 'waitForEncoding',
+ 'waitForMetadata',
+ 'alwaysRunAssembly',
+ 'importFromUploadURLs',
+ 'signature',
+ 'params',
+ 'fields',
+ 'getAssemblyOptions'
+]
+
+function addTransloaditPlugin (uppy, opts) {
+ const transloaditOptions = {}
+ transloaditOptionNames.forEach((name) => {
+ if (opts.hasOwnProperty(name)) transloaditOptions[name] = opts[name]
+ })
+ uppy.use(Transloadit, transloaditOptions)
+}
+
+module.exports = addTransloaditPlugin
diff --git a/packages/@uppy/transloadit-preset/src/form.js b/packages/@uppy/transloadit-preset/src/form.js
new file mode 100644
index 000000000..f19782aa1
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/src/form.js
@@ -0,0 +1,65 @@
+const Uppy = require('@uppy/core')
+const Form = require('@uppy/form')
+const findDOMElement = require('@uppy/utils/lib/findDOMElement')
+const addTransloaditPlugin = require('./addTransloaditPlugin')
+
+class TransloaditFormResult extends Uppy.Plugin {
+ constructor (uppy, opts) {
+ super(uppy, opts)
+
+ this.id = opts.id || 'TransloaditFormResult'
+ this.type = 'modifier'
+
+ this.onUpload = this.onUpload.bind(this)
+ }
+
+ getAssemblyStatuses (files) {
+ const assemblyIds = []
+ files.forEach((file) => {
+ const assembly = file.transloadit && file.transloadit.assembly
+ if (assembly && assemblyIds.indexOf(assembly) === -1) {
+ assemblyIds.push(assembly)
+ }
+ })
+
+ const tl = this.uppy.getPlugin('Transloadit')
+ return assemblyIds.map((id) => tl.getAssembly(id))
+ }
+
+ onUpload ({ successful, failed }) {
+ const assemblies = this.getAssemblyStatuses(successful)
+ const input = document.createElement('input')
+ input.type = 'hidden'
+ input.name = this.opts.name
+ input.value = JSON.stringify(assemblies)
+
+ const target = findDOMElement(this.opts.target)
+ target.appendChild(input)
+ }
+
+ install () {
+ this.uppy.on('upload', this.onUpload)
+ }
+}
+
+function form (target, opts) {
+ const uppy = Uppy({
+ restrictions: opts.restrictions
+ })
+ addTransloaditPlugin(uppy, opts)
+
+ uppy.use(TransloaditFormResult, {
+ target,
+ name: 'transloadit'
+ })
+
+ uppy.use(Form, {
+ target,
+ submitOnSuccess: true,
+ addResultToForm: false // using custom implementation instead
+ })
+
+ return uppy
+}
+
+module.exports = form
diff --git a/packages/@uppy/transloadit-preset/src/index.js b/packages/@uppy/transloadit-preset/src/index.js
new file mode 100644
index 000000000..7da4d1f14
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/src/index.js
@@ -0,0 +1,9 @@
+const form = require('./form')
+const modal = require('./modal')
+const upload = require('./upload')
+
+module.exports = {
+ form,
+ modal,
+ upload
+}
diff --git a/packages/@uppy/transloadit-preset/src/modal.js b/packages/@uppy/transloadit-preset/src/modal.js
new file mode 100644
index 000000000..6457d9d4c
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/src/modal.js
@@ -0,0 +1,15 @@
+const Uppy = require('@uppy/core')
+const Dashboard = require('@uppy/dashboard')
+const addTransloaditPlugin = require('./addTransloaditPlugin')
+
+function modal (target, opts) {
+ const uppy = Uppy({})
+ addTransloaditPlugin(uppy, opts)
+
+ return new Promise((resolve, reject) => {
+ }).then(() => {
+ return uppy.upload()
+ })
+}
+
+module.exports = modal
diff --git a/packages/@uppy/transloadit-preset/src/upload.js b/packages/@uppy/transloadit-preset/src/upload.js
new file mode 100644
index 000000000..f4e506cb8
--- /dev/null
+++ b/packages/@uppy/transloadit-preset/src/upload.js
@@ -0,0 +1,20 @@
+const Uppy = require('@uppy/core')
+const addTransloaditPlugin = require('./addTransloaditPlugin')
+
+function upload (files, opts) {
+ const uppy = Uppy({})
+
+ addTransloaditPlugin(uppy, opts)
+
+ files.forEach((file) => {
+ uppy.addFile({
+ data: file,
+ type: file.type,
+ name: file.name
+ })
+ })
+
+ return uppy.upload()
+}
+
+module.exports = upload