Index: templates/edge/AppxBlockMap.xml.tmpl
diff --git a/templates/edge/AppxBlockMap.xml.tmpl b/templates/edge/AppxBlockMap.xml.tmpl
deleted file mode 100644
index 7c0d4a7b59c99a6080a86ca6db2e171eb11d3d5e..0000000000000000000000000000000000000000
--- a/templates/edge/AppxBlockMap.xml.tmpl
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<BlockMap xmlns="http://schemas.microsoft.com/appx/2010/blockmap" HashMethod="http://www.w3.org/2001/04/xmlenc#sha256">
-  {% for file in files -%}
-  <File Name="{{file.name}}" Size="{{file.size}}" LfhSize="{{file.lfh_size}}">
-    {% for block in file.blocks -%}
-    <Block Hash="{{block.hash}}"/>
-    {% endfor -%}
-  </File>
-  {% endfor -%}
-</BlockMap>
Index: templates/edge/AppxManifest.xml.tmpl
diff --git a/templates/edge/AppxManifest.xml.tmpl b/templates/edge/AppxManifest.xml.tmpl
deleted file mode 100644
index db0f9931fe65af58ee0ef3d8a68a6e797f3d7966..0000000000000000000000000000000000000000
--- a/templates/edge/AppxManifest.xml.tmpl
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<Package
-  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
-  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
-  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
-  IgnorableNamespaces="uap3">
-
-  <Identity
-    Name="{{app_id}}"
-    Publisher="{{metadata.get('general', 'publisher_id')}}"
-    Version="{{version}}" />
-
-  <Properties>
-    <DisplayName>{{display_name}}</DisplayName>
-    <PublisherDisplayName>{{metadata.get('general', 'author')}}</PublisherDisplayName>
-    <Logo>{{logo_50}}</Logo>
-  </Properties>
-
-  <Dependencies>
-    <TargetDeviceFamily
-      Name="Windows.Desktop"
-      MinVersion="{{windows_version.min}}"
-      MaxVersionTested="{{windows_version.max}}" />
-  </Dependencies>
-
-  <Resources>
-    <Resource Language="en-us"/>
-  </Resources>
-
-  <Applications>
-    <Application Id="App">
-      <uap:VisualElements
-        AppListEntry="none"
-        DisplayName="{{display_name}}"
-        Square150x150Logo="{{logo_150}}"
-        Square44x44Logo="{{logo_44}}"
-        Description="{{description}}"
-        BackgroundColor="{{metadata.get('general', 'background_color')}}">
-      </uap:VisualElements>
-      <Extensions>
-      <uap3:Extension Category="windows.appExtension">
-        <uap3:AppExtension Name="com.microsoft.edge.extension"
-          Id="{{app_extension_id}}"
-          PublicFolder="Extension"
-          DisplayName="{{display_name}}">
-          <uap3:Properties>
-            <Capabilities>
-              <Capability Name="websiteContent"/>
-              <Capability Name="browserStorage"/>
-              <Capability Name="websiteInfo"/>
-              <Capability Name="browserWebRequest"/>
-            </Capabilities>
-          </uap3:Properties>
-        </uap3:AppExtension>
-      </uap3:Extension>
-      </Extensions>
-    </Application>
-  </Applications>
-
-</Package>
Index: templates/edge/[Content_Types].xml.tmpl
diff --git a/templates/edge/[Content_Types].xml.tmpl b/templates/edge/[Content_Types].xml.tmpl
deleted file mode 100644
index 54b5c2f0d4d7344443fb1a40b79f44e060392ecb..0000000000000000000000000000000000000000
--- a/templates/edge/[Content_Types].xml.tmpl
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
-  {% for extension, content_type in defaults.items() -%}
-  <Default Extension="{{ extension }}" ContentType="{{ content_type }}"/>
-  {% endfor -%}
-  {% for part_name, content_type in overrides.items() -%}
-  <Override PartName="{{ part_name }}" ContentType="{{ content_type }}"/>
-  {% endfor -%}
-</Types>
Index: tests/expecteddata/AppxManifest_edge_devenv.xml
diff --git a/tests/expecteddata/AppxManifest_edge_devenv.xml b/tests/expecteddata/AppxManifest_edge_devenv.xml
deleted file mode 100644
index 621dda0923e25b3fa8dd533536ca337f58b96e06..0000000000000000000000000000000000000000
--- a/tests/expecteddata/AppxManifest_edge_devenv.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<Package
-  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
-  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
-  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
-  IgnorableNamespaces="uap3">
-
-  <Identity
-    Name="EyeoGmbH.AdblockPlus"
-    Publisher="CN=4F066043-8AFE-41C9-B762-6C15E77E3F88"
-    Version="1.2.3.0" />
-
-  <Properties>
-    <DisplayName>Adblock Plus</DisplayName>
-    <PublisherDisplayName>eyeo GmbH</PublisherDisplayName>
-    <Logo>Assets\logo_50.png</Logo>
-  </Properties>
-
-  <Dependencies>
-    <TargetDeviceFamily
-      Name="Windows.Desktop"
-      MinVersion="10.0.14332.0"
-      MaxVersionTested="12.0.0.0" />
-  </Dependencies>
-
-  <Resources>
-    <Resource Language="en-us"/>
-  </Resources>
-
-  <Applications>
-    <Application Id="App">
-      <uap:VisualElements
-        AppListEntry="none"
-        DisplayName="Adblock Plus"
-        Square150x150Logo="Assets\logo_150.png"
-        Square44x44Logo="Assets\logo_44.png"
-        Description="Adblock Plus is the most popular ad blocker ever, and also supports websites by not blocking unobstrusive ads by default (configurable)."
-        BackgroundColor="red">
-      </uap:VisualElements>
-      <Extensions>
-      <uap3:Extension Category="windows.appExtension">
-        <uap3:AppExtension Name="com.microsoft.edge.extension"
-          Id="1.0"
-          PublicFolder="Extension"
-          DisplayName="Adblock Plus">
-          <uap3:Properties>
-            <Capabilities>
-              <Capability Name="websiteContent"/>
-              <Capability Name="browserStorage"/>
-              <Capability Name="websiteInfo"/>
-              <Capability Name="browserWebRequest"/>
-            </Capabilities>
-          </uap3:Properties>
-        </uap3:AppExtension>
-      </uap3:Extension>
-      </Extensions>
-    </Application>
-  </Applications>
-
-</Package>
\ No newline at end of file
Index: tests/test_packagerEdge.py
diff --git a/tests/test_packagerEdge.py b/tests/test_packagerEdge.py
deleted file mode 100644
index 213a88c5f2f651aea4d5dda8906e414d7c1367bd..0000000000000000000000000000000000000000
--- a/tests/test_packagerEdge.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import xml.etree.ElementTree as ET
-
-import pytest
-
-from buildtools import packager, packagerEdge
-
-
-@pytest.fixture
-def files():
-    """Minimal Files() for testing blockmap."""
-    str500 = b''.join(chr(i % 200 + 30) for i in range(500))
-    files = packager.Files(set(), set())
-    files['Extension/foo.xml'] = str500
-    files['Extension/bar.png'] = str500 * 200
-    return files
-
-
-def blockmap2dict(xml_data):
-    """Convert AppxBlockMap.xml to a dict of dicts easier to inspect."""
-    return {
-        file.get('Name'): {
-            'size': file.get('Size'),
-            'lfhsize': file.get('LfhSize'),
-            'blocks': [b.get('Hash') for b in file],
-        }
-        for file in ET.fromstring(xml_data)
-    }
-
-
-def test_create_appx_blockmap(files):
-    blockmap = blockmap2dict(packagerEdge.create_appx_blockmap(files))
-    assert blockmap['Extension\\foo.xml'] == {
-        'size': '500',
-        'lfhsize': '47',
-        'blocks': ['Vhwfmzss1Ney+j/ssR2QVISvFyMNBQeS2P+UjeE/di0='],
-    }
-    assert blockmap['Extension\\bar.png'] == {
-        'size': '100000',
-        'lfhsize': '47',
-        'blocks': [
-            'KPW2SxeEikUEGhoKmKxruUSexKun0bGXMppOqUFrX5E=',
-            'KQHnov1SZ1z34ttdDUjX2leYtpIIGndUVoUteieS2cw=',
-        ],
-    }
-
-
-def ctm2dict(content_types_map):
-    """Convert content type map to a dict."""
-    ret = {'defaults': {}, 'overrides': {}}
-    for node in ET.fromstring(content_types_map):
-        ct = node.get('ContentType')
-        if node.tag.endswith('Default'):
-            ret['defaults'][node.get('Extension')] = ct
-        elif node.tag.endswith('Override'):
-            ret['overrides'][node.get('PartName')] = ct
-        else:
-            raise ValueError('Unrecognised tag in content map: ' + node.tag)
-    return ret
-
-
-def test_empty_content_types_map():
-    ctm_dict = ctm2dict(packagerEdge.create_content_types_map([]))
-    assert ctm_dict['defaults'] == {}
-    assert ctm_dict['overrides'] == {}
-
-
-def test_full_content_types_map():
-    filenames = ['no-extension', packagerEdge.MANIFEST, packagerEdge.BLOCKMAP]
-    filenames += ['file.' + x for x in 'json html js png css git otf'.split()]
-    ctm_dict = ctm2dict(packagerEdge.create_content_types_map(filenames))
-    assert ctm_dict['defaults'] == {
-        'css': 'text/css',
-        'html': 'text/html',
-        'js': 'application/javascript',
-        'json': 'application/json',
-        'otf': 'application/octet-stream',
-        'png': 'image/png',
-        'xml': 'application/xml',
-    }
-    assert ctm_dict['overrides'] == {
-        '/AppxBlockMap.xml': 'application/vnd.ms-appx.blockmap+xml',
-        '/AppxManifest.xml': 'application/vnd.ms-appx.manifest+xml',
-    }
Index: package.json
diff --git a/package.json b/package.json
index a4a29a7bdc8c8d3de67fff4f97e25a808d55cef5..4656e9cb04173ec9adbaeab1a1e7c6a5f10eb7ce 100644
--- a/package.json
+++ b/package.json
@@ -4,10 +4,13 @@
   "license": "MPL-2.0",
   "dependencies": {
     "jsdoc": "3.5.5",
+    "manifoldjs": "0.7.6",
     "memory-fs": "0.4.1",
     "webpack": "3.6.0"
   },
   "scripts": {
-    "jsdoc": "jsdoc"
+    "jsdoc": "jsdoc",
+    "build-edge": "manifoldjs -l error -p edgeextension -f edgeextension -d $EXT_FOLDER -m $SRC_FOLDER/manifest.json",
+    "package-edge": "manifoldjs -l error -p edgeextension package $EXT_FOLDER/MSGname/edgeextension/manifest/"
   }
 }
Index: packagerEdge.py
diff --git a/packagerEdge.py b/packagerEdge.py
index a86ffc45d44c532a24319eb809530a4f956f644d..2479ac4c9261f3d06f60facab118e9ffe698e15b 100644
--- a/packagerEdge.py
+++ b/packagerEdge.py
@@ -2,26 +2,20 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-import base64
-import hashlib
-import json
-import mimetypes
 import os
-import zipfile
+import shutil
+from StringIO import StringIO
+import subprocess
+import tempfile
+from xml.etree import ElementTree
+from zipfile import ZipFile
 
 import packager
 import packagerChrome
 
-# Files and directories expected inside of the .APPX archive.
-MANIFEST = 'AppxManifest.xml'
-CONTENT_TYPES = '[Content_Types].xml'
-BLOCKMAP = 'AppxBlockMap.xml'
-EXTENSION_DIR = 'Extension'
+MANIFEST = 'appxmanifest.xml'
 ASSETS_DIR = 'Assets'
 
-# Size of uncompressed block in the APPX block map.
-BLOCKSIZE = 64 * 1024
-
 defaultLocale = packagerChrome.defaultLocale
 
 
@@ -29,122 +23,67 @@ def _get_template_for(filename):
     return packager.getTemplate('edge/{}.tmpl'.format(filename))
 
 
-def _lfh_size(filename):
-    """Compute the size of zip local file header for `filename`."""
-    try:
-        filename = filename.encode('utf-8')
-    except UnicodeDecodeError:
-        pass  # filename is already a byte string.
-    return zipfile.sizeFileHeader + len(filename)
-
-
-def _make_blockmap_entry(filename, data):
-    blocks = [data[i:i + BLOCKSIZE] for i in range(0, len(data), BLOCKSIZE)]
-    return {
-        'name': filename.replace('/', '\\'),
-        'size': len(data),
-        'lfh_size': _lfh_size(filename),
-        'blocks': [
-            {'hash': base64.b64encode(hashlib.sha256(block).digest())}
-            for block in blocks
-        ],
-    }
+def register_xml_namespaces(manifest_path):
+    """Register namespaces of the given file, in order to preserve defaults."""
+    with open(manifest_path, 'r') as fp:
+        ns = dict([node for _, node in ElementTree.iterparse(
+            fp, events=['start-ns'])])
+    for prefix, uri in ns.items():
+        ElementTree.register_namespace(prefix, uri)
 
+    # Make the default namespace available in an xpath expression
+    ns['_d'] = ns['']
 
-def create_appx_blockmap(files):
-    """Create APPX blockmap for the list of files."""
-    # We don't support AppxBlockmap.xml generation for compressed zip files at
-    # the moment. The only way to reliably calculate the compressed size of
-    # each 64k chunk in the zip file is to override the relevant parts of
-    # `zipfile` library. We have chosen to not do it so we produce an
-    # uncompressed zip file that is later repackaged by Windows Store with
-    # compression.
-    template = _get_template_for(BLOCKMAP)
-    files = [_make_blockmap_entry(n, d) for n, d in files.items()]
-    return template.render(files=files).encode('utf-8')
-
-
-def load_translation(files, locale):
-    """Load translation strings for locale from files."""
-    path = '{}/_locales/{}/messages.json'.format(EXTENSION_DIR, locale)
-    return json.loads(files[path])
-
-
-def get_appx_version(metadata, build_num):
-    """Get the version number for usage in AppxManifest.xml.
-
-    As required by the Windows Store, the returned version string has four
-    components, where the 3rd component is replaced with the build number
-    if available, and the 4th component is always zero (e.g. 1.2.1000.0).
-    """
-    components = metadata.get('general', 'version').split('.')[:3]
-    components.extend(['0'] * (4 - len(components)))
-    if build_num:
-        components[2] = build_num
-    return '.'.join(components)
-
-
-def create_appx_manifest(params, files, build_num, release_build):
-    """Create AppxManifest.xml."""
-    params = dict(params)
-    metadata = params['metadata']
-    w = params['windows_version'] = {}
-    w['min'], w['max'] = metadata.get('compat', 'windows').split('/')
-    params['version'] = get_appx_version(metadata, build_num)
-
-    metadata_suffix = 'release' if release_build else 'devbuild'
-    app_extension_id = 'extension_id_' + metadata_suffix
-    if metadata.has_option('general', app_extension_id):
-        params['app_extension_id'] = metadata.get('general', app_extension_id)
-    else:
-        params['app_extension_id'] = 'EdgeExtension'
+    return ns
 
-    params['app_id'] = packager.get_app_id(release_build, metadata)
 
-    translation = load_translation(files, defaultLocale)
-    name_key = 'name' if release_build else 'name_devbuild'
-    params['display_name'] = translation[name_key]['message']
-    params['description'] = translation['description']['message']
+def update_appx_manifest(manifest_path, base_dir, files, metadata,
+                         release_build):
+    namespaces = register_xml_namespaces(manifest_path)
 
-    for size in ['44', '50', '150']:
-        path = '{}/logo_{}.png'.format(ASSETS_DIR, size)
-        if path not in files:
-            raise KeyError(path + ' is not found in files')
-        params['logo_' + size] = path.replace('/', '\\')
+    v_min, v_max = metadata.get('compat', 'windows').split('/')
 
-    template = _get_template_for(MANIFEST)
-    return template.render(params).encode('utf-8')
+    filenames = []
 
+    for name, path in metadata.items('appx_assets'):
+        path = os.path.join(base_dir, path)
+        icon_path = '{}/{}'.format(ASSETS_DIR, name)
 
-def move_files_to_extension(files):
-    """Move all files into `Extension` folder for APPX packaging."""
-    # We sort the files to ensure that 'Extension/xyz' is moved before 'xyz'.
-    # If 'xyz' is moved first, it would overwrite 'Extension/xyz' and its
-    # original content would be lost.
-    names = sorted(files.keys(), key=len, reverse=True)
-    for filename in names:
-        files['{}/{}'.format(EXTENSION_DIR, filename)] = files.pop(filename)
+        files.read(path, icon_path)
+        filenames.append(icon_path)
 
+    assets = packagerChrome.makeIcons(files, filenames)
 
-def create_content_types_map(filenames):
-    """Create [Content_Types].xml -- a mime type map."""
-    params = {'defaults': {}, 'overrides': {}}
-    overrides = {
-        BLOCKMAP: 'application/vnd.ms-appx.blockmap+xml',
-        MANIFEST: 'application/vnd.ms-appx.manifest+xml',
-    }
-    types = mimetypes.MimeTypes()
-    types.add_type('application/octet-stream', '.otf')
-    for filename in filenames:
-        ext = os.path.splitext(filename)[1]
-        if ext:
-            content_type = types.guess_type(filename, strict=False)[0]
-            if content_type is not None:
-                params['defaults'][ext[1:]] = content_type
-        if filename in overrides:
-            params['overrides']['/' + filename] = overrides[filename]
-    content_types_template = _get_template_for(CONTENT_TYPES)
-    return content_types_template.render(params).encode('utf-8')
+    author = metadata.get('general', 'author')
+
+    overrides = [
+        ('_d:Identity', None, [
+            ('Name', packager.get_app_id(release_build, metadata)),
+            ('Publisher', metadata.get('general', 'publisher_id')),
+        ]),
+        ('_d:Properties/_d:PublisherDisplayName', author, []),
+        ('_d:Properties/_d:Logo', assets[50], []),
+        ('_d:Dependencies/_d:TargetDeviceFamily', None, [
+            ('MaxVersionTested', v_max),
+            ('MinVersion', v_min),
+        ]),
+        ('_d:Applications/_d:Application/uap:VisualElements', None, [
+            ('Square150x150Logo', assets[150]),
+            ('Square44x44Logo', assets[44]),
+        ]),
+    ]
+
+    tree = ElementTree.parse(manifest_path)
+    root = tree.getroot()
+
+    for xpath, text, attributes in overrides:
+        element = root.find(xpath, namespaces)
+        if text:
+            element.text = text
+        for attr, value in attributes:
+                element.set(attr, value)
+
+    tree.write(manifest_path, encoding='utf-8', xml_declaration=True)
 
 
 def createBuild(baseDir, type='edge', outFile=None,  # noqa: preserve API.
@@ -191,16 +130,57 @@ def createBuild(baseDir, type='edge', outFile=None,  # noqa: preserve API.
     if devenv:
         packagerChrome.add_devenv_requirements(files, metadata, params)
 
-    move_files_to_extension(files)
+    zipped = StringIO()
+    files.zip(zipped)
+
+    zipped.seek(0)
+
+    if devenv:
+        shutil.copyfileobj(zipped, outfile)
+        return
+
+    tmp_dir = tempfile.mkdtemp('adblockplus_package')
+    try:
+        src_dir = os.path.join(tmp_dir, 'src')
+        ext_dir = os.path.join(tmp_dir, 'ext')
+
+        with ZipFile(zipped, 'r') as zip_file:
+            zip_file.extractall(src_dir)
+
+        cmd_env = os.environ.copy()
+        cmd_env['SRC_FOLDER'] = src_dir
+        cmd_env['EXT_FOLDER'] = ext_dir
+
+        manifold_folder = os.path.join(ext_dir, 'MSGname', 'edgeextension')
+        manifest_folder = os.path.join(manifold_folder, 'manifest')
+        asset_folder = os.path.join(manifest_folder, ASSETS_DIR)
+
+        # prepare the extension with manifoldjs
+        cmd = ['npm', 'run', '--silent', 'build-edge']
+        subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__))
+
+        # update incomplete appxmanifest
+        intermediate_manifest = os.path.join(manifest_folder, MANIFEST)
+        update_appx_manifest(intermediate_manifest, baseDir, files, metadata,
+                             releaseBuild)
+
+        # cleanup placeholders, copy actual images
+        shutil.rmtree(asset_folder)
+        os.mkdir(asset_folder)
+        if metadata.has_section('appx_assets'):
+            for name, path in metadata.items('appx_assets'):
+                path = os.path.join(baseDir, path)
+                target = os.path.join(asset_folder, name)
+                shutil.copyfile(path, target)
+
+        # package app with manifoldjs
+        cmd = ['npm', 'run', '--silent', 'package-edge']
 
-    if metadata.has_section('appx_assets'):
-        for name, path in metadata.items('appx_assets'):
-            path = os.path.join(baseDir, path)
-            files.read(path, '{}/{}'.format(ASSETS_DIR, name))
+        subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__))
 
-    files[MANIFEST] = create_appx_manifest(params, files,
-                                           buildNum, releaseBuild)
-    files[BLOCKMAP] = create_appx_blockmap(files)
-    files[CONTENT_TYPES] = create_content_types_map(files.keys() + [BLOCKMAP])
+        package = os.path.join(manifold_folder, 'package',
+                               'edgeExtension.appx')
 
-    files.zip(outfile, compression=zipfile.ZIP_STORED)
+        shutil.copyfile(package, outfile)
+    finally:
+        shutil.rmtree(tmp_dir, ignore_errors=True)
Index: tests/abp-150.png
diff --git a/tests/abp-150.png b/tests/abp-150.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1ed0b26a3504fb2d097ffd785c4a175476e9922
Binary files /dev/null and b/tests/abp-150.png differ
Index: tests/abp-44.png
diff --git a/tests/abp-44.png b/tests/abp-44.png
new file mode 100644
index 0000000000000000000000000000000000000000..311d8c613877795e322d63ddd64a324eb29577d6
Binary files /dev/null and b/tests/abp-44.png differ
Index: tests/abp-50.png
diff --git a/tests/abp-50.png b/tests/abp-50.png
new file mode 100644
index 0000000000000000000000000000000000000000..b53724ec9a42b6772faec254d9a44d439f20112a
Binary files /dev/null and b/tests/abp-50.png differ
Index: tests/expecteddata/AppxManifest_edge_development_build.xml
diff --git a/tests/expecteddata/AppxManifest_edge_development_build.xml b/tests/expecteddata/AppxManifest_edge_development_build.xml
index eb299d6fbb32f34676ed9c475c25dab1570c3bf7..f6abdd95437acc929f74c8f11778364d2991356b 100644
--- a/tests/expecteddata/AppxManifest_edge_development_build.xml
+++ b/tests/expecteddata/AppxManifest_edge_development_build.xml
@@ -1,61 +1,40 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version='1.0' encoding='utf-8'?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap3">
+	<Identity Name="EyeoGmbH.AdblockPlusdevelopmentbuild" Publisher="CN=4F066043-8AFE-41C9-B762-6C15E77E3F88" Version="1.2.3.1337" /> 
 
-<Package
-  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
-  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
-  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
-  IgnorableNamespaces="uap3">
+	<Properties> 
+		<DisplayName>ms-resource:DisplayName</DisplayName> 
+		<PublisherDisplayName>eyeo GmbH</PublisherDisplayName> 
+		<Logo>Assets/logo_50.png</Logo> 
+	</Properties> 
 
-  <Identity
-    Name="EyeoGmbH.AdblockPlusdevelopmentbuild"
-    Publisher="CN=4F066043-8AFE-41C9-B762-6C15E77E3F88"
-    Version="1.2.1337.0" />
+	<Dependencies> 
+		<TargetDeviceFamily MaxVersionTested="12.0.0.0" MinVersion="10.0.14332.0" Name="Windows.Desktop" />
+	</Dependencies> 
 
-  <Properties>
-    <DisplayName>devbuild-marker</DisplayName>
-    <PublisherDisplayName>eyeo GmbH</PublisherDisplayName>
-    <Logo>Assets\logo_50.png</Logo>
-  </Properties>
+	<Resources>
+		<Resource Language="en-us" />
+		<Resource Language="de" />
+		<Resource Language="it" />
+		<Resource uap:Scale="200" />
+	</Resources> 
 
-  <Dependencies>
-    <TargetDeviceFamily
-      Name="Windows.Desktop"
-      MinVersion="10.0.14332.0"
-      MaxVersionTested="12.0.0.0" />
-  </Dependencies>
-
-  <Resources>
-    <Resource Language="en-us"/>
-  </Resources>
-
-  <Applications>
-    <Application Id="App">
-      <uap:VisualElements
-        AppListEntry="none"
-        DisplayName="devbuild-marker"
-        Square150x150Logo="Assets\logo_150.png"
-        Square44x44Logo="Assets\logo_44.png"
-        Description="Adblock Plus is the most popular ad blocker ever, and also supports websites by not blocking unobstrusive ads by default (configurable)."
-        BackgroundColor="red">
-      </uap:VisualElements>
-      <Extensions>
-      <uap3:Extension Category="windows.appExtension">
-        <uap3:AppExtension Name="com.microsoft.edge.extension"
-          Id="EdgeExtension"
-          PublicFolder="Extension"
-          DisplayName="devbuild-marker">
-          <uap3:Properties>
-            <Capabilities>
-              <Capability Name="websiteContent"/>
-              <Capability Name="browserStorage"/>
-              <Capability Name="websiteInfo"/>
-              <Capability Name="browserWebRequest"/>
-            </Capabilities>
-          </uap3:Properties>
-        </uap3:AppExtension>
-      </uap3:Extension>
-      </Extensions>
-    </Application>
-  </Applications>
-
-</Package>
\ No newline at end of file
+	<Applications> 
+		<Application Id="App">
+			<uap:VisualElements AppListEntry="none" BackgroundColor="transparent" Description="ms-resource:Description" DisplayName="ms-resource:DisplayName" Square150x150Logo="Assets/logo_150.png" Square44x44Logo="Assets/logo_44.png">
+			</uap:VisualElements>
+			<Extensions>
+				<uap3:Extension Category="windows.appExtension">
+					<uap3:AppExtension DisplayName="ms-resource:DisplayName" Id="EdgeExtension" Name="com.microsoft.edge.extension" PublicFolder="Extension">
+						<uap3:Properties>
+							<Capabilities>
+								<Capability Name="websiteInfo" />
+								<Capability Name="websiteContent" />
+							</Capabilities>
+						</uap3:Properties>
+					</uap3:AppExtension>
+				</uap3:Extension>
+			</Extensions>
+		</Application> 
+	</Applications>
+</Package>
Index: tests/expecteddata/AppxManifest_edge_release_build.xml
diff --git a/tests/expecteddata/AppxManifest_edge_release_build.xml b/tests/expecteddata/AppxManifest_edge_release_build.xml
index 621dda0923e25b3fa8dd533536ca337f58b96e06..31140ca33c1e107a4d44f6b217c20517b8224b03 100644
--- a/tests/expecteddata/AppxManifest_edge_release_build.xml
+++ b/tests/expecteddata/AppxManifest_edge_release_build.xml
@@ -1,61 +1,40 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version='1.0' encoding='utf-8'?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap3">
+	<Identity Name="EyeoGmbH.AdblockPlus" Publisher="CN=4F066043-8AFE-41C9-B762-6C15E77E3F88" Version="0.1.2.3" /> 
 
-<Package
-  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
-  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
-  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
-  IgnorableNamespaces="uap3">
+	<Properties> 
+		<DisplayName>ms-resource:DisplayName</DisplayName> 
+		<PublisherDisplayName>eyeo GmbH</PublisherDisplayName> 
+		<Logo>Assets/logo_50.png</Logo> 
+	</Properties> 
 
-  <Identity
-    Name="EyeoGmbH.AdblockPlus"
-    Publisher="CN=4F066043-8AFE-41C9-B762-6C15E77E3F88"
-    Version="1.2.3.0" />
+	<Dependencies> 
+		<TargetDeviceFamily MaxVersionTested="12.0.0.0" MinVersion="10.0.14332.0" Name="Windows.Desktop" />
+	</Dependencies> 
 
-  <Properties>
-    <DisplayName>Adblock Plus</DisplayName>
-    <PublisherDisplayName>eyeo GmbH</PublisherDisplayName>
-    <Logo>Assets\logo_50.png</Logo>
-  </Properties>
+	<Resources>
+		<Resource Language="en-us" />
+		<Resource Language="de" />
+		<Resource Language="it" />
+		<Resource uap:Scale="200" />
+	</Resources> 
 
-  <Dependencies>
-    <TargetDeviceFamily
-      Name="Windows.Desktop"
-      MinVersion="10.0.14332.0"
-      MaxVersionTested="12.0.0.0" />
-  </Dependencies>
-
-  <Resources>
-    <Resource Language="en-us"/>
-  </Resources>
-
-  <Applications>
-    <Application Id="App">
-      <uap:VisualElements
-        AppListEntry="none"
-        DisplayName="Adblock Plus"
-        Square150x150Logo="Assets\logo_150.png"
-        Square44x44Logo="Assets\logo_44.png"
-        Description="Adblock Plus is the most popular ad blocker ever, and also supports websites by not blocking unobstrusive ads by default (configurable)."
-        BackgroundColor="red">
-      </uap:VisualElements>
-      <Extensions>
-      <uap3:Extension Category="windows.appExtension">
-        <uap3:AppExtension Name="com.microsoft.edge.extension"
-          Id="1.0"
-          PublicFolder="Extension"
-          DisplayName="Adblock Plus">
-          <uap3:Properties>
-            <Capabilities>
-              <Capability Name="websiteContent"/>
-              <Capability Name="browserStorage"/>
-              <Capability Name="websiteInfo"/>
-              <Capability Name="browserWebRequest"/>
-            </Capabilities>
-          </uap3:Properties>
-        </uap3:AppExtension>
-      </uap3:Extension>
-      </Extensions>
-    </Application>
-  </Applications>
-
-</Package>
\ No newline at end of file
+	<Applications> 
+		<Application Id="App">
+			<uap:VisualElements AppListEntry="none" BackgroundColor="transparent" Description="ms-resource:Description" DisplayName="ms-resource:DisplayName" Square150x150Logo="Assets/logo_150.png" Square44x44Logo="Assets/logo_44.png">
+			</uap:VisualElements>
+			<Extensions>
+				<uap3:Extension Category="windows.appExtension">
+					<uap3:AppExtension DisplayName="ms-resource:DisplayName" Id="EdgeExtension" Name="com.microsoft.edge.extension" PublicFolder="Extension">
+						<uap3:Properties>
+							<Capabilities>
+								<Capability Name="websiteInfo" />
+								<Capability Name="websiteContent" />
+							</Capabilities>
+						</uap3:Properties>
+					</uap3:AppExtension>
+				</uap3:Extension>
+			</Extensions>
+		</Application> 
+	</Applications>
+</Package>
Index: tests/metadata.edge
diff --git a/tests/metadata.edge b/tests/metadata.edge
index 9aa3c3f3fab88f5d77d07456f3e71f16a073473d..25cf3906dac4894394081dec07c951d09ca1af5b 100644
--- a/tests/metadata.edge
+++ b/tests/metadata.edge
@@ -17,9 +17,9 @@ permissions =
   contextMenus
 
 [appx_assets]
-logo_44.png = chrome/icons/abp-44.png
-logo_50.png = chrome/icons/abp-50.png
-logo_150.png = chrome/icons/abp-150.png
+logo_44.png = icons/abp-44.png
+logo_50.png = icons/abp-50.png
+logo_150.png = icons/abp-150.png
 
 [mapping]
 icons = chrome/icons
Index: tests/test_packagerWebExt.py
diff --git a/tests/test_packagerWebExt.py b/tests/test_packagerWebExt.py
index f2fd855fd16a57abb39883f289e5cce14885bfd0..81cc9633e4899ea82fcbd88ce8e1876a3be80831 100644
--- a/tests/test_packagerWebExt.py
+++ b/tests/test_packagerWebExt.py
@@ -187,10 +187,10 @@ def locale_modules(tmpdir):
 @pytest.fixture
 def icons(srcdir):
     icons_dir = srcdir.mkdir('icons')
-    for filename in ['abp-16.png', 'abp-19.png', 'abp-53.png']:
+    for name in ['abp-{}.png'.format(x) for x in [16, 19, 44, 50, 53, 150]]:
         shutil.copy(
-            os.path.join(os.path.dirname(__file__), filename),
-            os.path.join(str(icons_dir), filename),
+            os.path.join(os.path.dirname(__file__), name),
+            os.path.join(str(icons_dir), name),
         )
 
 
@@ -293,7 +293,7 @@ def assert_manifest_content(manifest, expected_path):
     assert len(diff) == 0, '\n'.join(diff)
 
 
-def assert_webpack_bundle(package, prefix, is_devbuild, excluded=False):
+def assert_webpack_bundle(package, prefix, is_devbuild, platform):
     libfoo = package.read(os.path.join(prefix, 'lib/foo.js'))
     libfoomap = package.read(os.path.join(prefix, 'lib/foo.js.map'))
 
@@ -308,15 +308,15 @@ def assert_webpack_bundle(package, prefix, is_devbuild, excluded=False):
     assert 'var this_is_c;' in libfoo
     assert 'webpack:///./ext/c.js' in libfoomap
 
-    if prefix:  # webpack 'resolve.alias' exposure
+    if platform is 'edge':  # webpack 'resolve.alias' exposure
         assert 'var this_is_edge;' in libfoo
         assert 'webpack:///./lib/edge.js' in libfoomap
     else:
         assert 'var this_is_mogo;' in libfoo
         assert 'webpack:///./lib/mogo.js' in libfoomap
 
-    assert ('var foo;' in libfoo) != excluded
-    assert ('webpack:///./lib/b.js' in libfoomap) != excluded
+    assert ('var foo;' in libfoo) != (platform is 'gecko')
+    assert ('webpack:///./lib/b.js' in libfoomap) != (platform is 'gecko')
 
 
 def assert_devenv_scripts(package, prefix, devenv):
@@ -345,16 +345,16 @@ def assert_devenv_scripts(package, prefix, devenv):
         assert set(manifest['background']['scripts']) == set(scripts)
 
 
-def assert_base_files(package, platform, prefix):
+def assert_base_files(package, platform, prefix, devenv):
     filenames = set(package.namelist())
 
     if platform == 'edge':
-        assert 'AppxManifest.xml' in filenames
-        assert 'AppxBlockMap.xml' in filenames
-        assert '[Content_Types].xml' in filenames
+        assert ('AppxManifest.xml' in filenames) is not devenv
+        assert ('AppxBlockMap.xml' in filenames) is not devenv
+        assert ('[Content_Types].xml' in filenames) is not devenv
 
-        assert package.read('Assets/logo_44.png') == '44'
-        assert package.read('Extension/icons/abp-44.png') == '44'
+        if not devenv:
+            assert package.read('Extension/icons/abp-44.png') == '44'
 
     assert os.path.join(prefix, 'bar.json') in filenames
     assert os.path.join(prefix, 'manifest.json') in filenames
@@ -429,10 +429,16 @@ def test_build_webext(platform, command, keyfile, tmpdir, srcdir, capsys):
     manifests = {
         'gecko': [('', 'manifest', 'json')],
         'chrome': [('', 'manifest', 'json')],
-        'edge': [('', 'AppxManifest', 'xml'),
-                 ('Extension', 'manifest', 'json')],
     }
 
+    if not devenv:
+        manifests['edge'] = [
+            ('', 'AppxManifest', 'xml'),
+            ('Extension', 'manifest', 'json'),
+        ]
+    else:
+        manifests['edge'] = [('', 'manifest', 'json')]
+
     filenames = {
         'gecko': 'adblockplusfirefox-1.2.3{}.xpi',
         'chrome': 'adblockpluschrome-1.2.3{{}}.{}'.format(
@@ -441,7 +447,7 @@ def test_build_webext(platform, command, keyfile, tmpdir, srcdir, capsys):
         'edge': 'adblockplusedge-1.2.3{}.appx',
     }
 
-    if platform == 'edge':
+    if platform == 'edge' and not devenv:
         prefix = 'Extension'
     else:
         prefix = ''
@@ -474,10 +480,10 @@ def test_build_webext(platform, command, keyfile, tmpdir, srcdir, capsys):
         assert_chrome_signature(out_file_path, keyfile)
 
     with content_class(out_file_path) as package:
-        assert_base_files(package, platform, prefix)
+        assert_base_files(package, platform, prefix, devenv)
         assert_all_locales_present(package, prefix)
         assert_webpack_bundle(package, prefix, not release and not devenv,
-                              platform == 'gecko')
+                              platform)
 
         if platform == 'chrome':
             assert_locale_upfix(package)
Index: tox.ini
diff --git a/tox.ini b/tox.ini
index ba597ce44d3a4fce6b5a4ef1a105d79ce8a4d3ff..2b2c33da398eaf6cfe1e8fbf4781ba853d8bebcc 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,6 +3,11 @@ envlist = py27
 skipsdist = true
 
 [flake8]
+
+exclude =
+    node_modules,
+    .tox,
+    *.pyc,
 ignore = D1,C815
 per-file-ignores =
     /chainedconfigparser.py : A107,E501,D205,D208,D400
