diff --git a/atlassian-connect-descriptor.cabal b/atlassian-connect-descriptor.cabal
--- a/atlassian-connect-descriptor.cabal
+++ b/atlassian-connect-descriptor.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.1.0.1
+version:             0.2.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            Code that helps you create a valid Atlassian Connect Descriptor.
diff --git a/dist/build/test-descriptorStub/test-descriptorStub-tmp/test-descriptorStub.hs b/dist/build/test-descriptorStub/test-descriptorStub-tmp/test-descriptorStub.hs
deleted file mode 100644
--- a/dist/build/test-descriptorStub/test-descriptorStub-tmp/test-descriptorStub.hs
+++ /dev/null
@@ -1,5 +0,0 @@
-module Main ( main ) where
-import Distribution.Simple.Test.LibV09 ( stubMain )
-import Test ( tests )
-main :: IO ()
-main = stubMain tests
diff --git a/src/Data/Connect/BaseTypes.hs b/src/Data/Connect/BaseTypes.hs
--- a/src/Data/Connect/BaseTypes.hs
+++ b/src/Data/Connect/BaseTypes.hs
@@ -75,3 +75,13 @@
 instance ToJSON AuthType where
    toJSON Jwt  = "jwt"
    toJSON None  = "none"
+
+-- | A basic length type for HTML elements. Useful for 'WebPanel's and other modules that may require length specifications.
+data Length
+   = Pixels Integer -- ^ Specify a length in pixels
+   | Percentage Integer -- ^ Specify a length as a percentage in the range [0-100].
+   deriving (Show, Generic)
+
+instance ToJSON Length where
+   toJSON (Pixels x) = String . pack $ (show x ++ "px")
+   toJSON (Percentage x) = String . pack $ (show x ++ "%")
diff --git a/src/Data/Connect/Conditions.hs b/src/Data/Connect/Conditions.hs
--- a/src/Data/Connect/Conditions.hs
+++ b/src/Data/Connect/Conditions.hs
@@ -114,7 +114,7 @@
    | CanManageAttachmentsJiraCondition
    | FeatureFlagJiraCondition
    | HasIssuePermissionJiraCondition
-   | HasProjectPermissionJiraCondition
+   | HasProjectPermissionJiraCondition -- ^ Returns true if there is a selected project and the user has project admin to it.
    | HasSelectedProjectPermissionJiraCondition
    | HasSubTasksAvaliableJiraCondition
    | HasVotedForIssueJiraCondition
diff --git a/src/Data/Connect/Descriptor.hs b/src/Data/Connect/Descriptor.hs
--- a/src/Data/Connect/Descriptor.hs
+++ b/src/Data/Connect/Descriptor.hs
@@ -89,6 +89,7 @@
    , PluginKey(..)
    , Timeout(..)
    , IconDetails(..)
+   , Length(..)
    -- * Authentication
    , Authentication(..)
    , AuthType(..)
@@ -105,7 +106,9 @@
    , ConfluenceModules(..)
    , emptyConfluenceModules
    , WebPanel(..)
+   , WebPanelLayout(..)
    , GeneralPage(..)
+   , JIRAProjectAdminTabPanel(..)
    -- ** Webhooks
    , Webhook(..)
    , WebhookEvent(..)
diff --git a/src/Data/Connect/Modules.hs b/src/Data/Connect/Modules.hs
--- a/src/Data/Connect/Modules.hs
+++ b/src/Data/Connect/Modules.hs
@@ -7,7 +7,9 @@
    , ConfluenceModules(..)
    , emptyConfluenceModules
    , WebPanel(..)
+   , WebPanelLayout(..)
    , GeneralPage(..)
+   , JIRAProjectAdminTabPanel(..)
    ) where
 
 import           Data.Aeson
@@ -49,13 +51,16 @@
 -- | A collection of all of the JIRA Modules that you can define. For more documentation on which Modules are supported
 -- the Atlassian Connect framework please see 'Modules'. You can also find more documentation on each of the modules.
 data JIRAModules = JIRAModules
-   { jiraWebPanels    :: [WebPanel]
-   , jiraGeneralPages :: [GeneralPage]
-   , jiraWebhooks     :: [Webhook]
+   { jiraWebPanels                 :: [WebPanel]
+   , jiraGeneralPages              :: [GeneralPage]
+   , jiraWebhooks                  :: [Webhook]
+   , jiraJiraProjectAdminTabPanels :: [JIRAProjectAdminTabPanel]
    } deriving (Show, Generic)
 
 instance ToJSON JIRAModules where
    toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jira"
+      }
 
 -- | A collection of all of the Confluence Modules that you can define. For more documentation on which Modules are supported
 -- the Atlassian Connect framework please see 'Modules'. You can also find more documentation on each of the modules.
@@ -65,10 +70,12 @@
 
 instance ToJSON ConfluenceModules where
    toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "confluence"
+      }
 
 -- | Empty JIRA Modules; useful when you only want to define a few modules via Haskell record syntax.
 emptyJIRAModules :: JIRAModules
-emptyJIRAModules = JIRAModules [] [] []
+emptyJIRAModules = JIRAModules [] [] [] []
 
 -- | Empty Confluence Modules; useful when you only want to define a few modules via Haskell record syntax.
 emptyConfluenceModules :: ConfluenceModules
@@ -100,12 +107,67 @@
    , wpUrl        :: T.Text -- ^ The relative URI that the host product will hit to get HTML content.
    , wpLocation   :: T.Text -- ^ The location that this content should be injected in the host product.
    , wpConditions :: [Condition] -- ^ The 'Condition's that need to be met for this module to be displayed.
+   , wpWeight     :: Maybe Integer
+   , wpLayout     :: Maybe WebPanelLayout
    } deriving (Show, Generic)
 
 instance ToJSON WebPanel where
    toJSON = genericToJSON baseOptions
       { fieldLabelModifier = stripFieldNamePrefix "wp"
       }
+
+-- | A 'WebPanelLayout' allows you to specify the dimensions of your Web Panel if that is required.
+data WebPanelLayout = WebPanelLayout
+   { wplWidth  :: Length
+   , wplHeight :: Length
+   } deriving (Show, Generic)
+
+instance ToJSON WebPanelLayout where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "wpl"
+      }
+
+data WebItem = WebItem
+   { wiName         :: Name WebItem
+   , wiKey          :: T.Text
+   -- TODO add tooltip support
+   , wiLocation     :: T.Text
+   , wiUrl          :: T.Text
+   , wiConditions   :: [Condition]
+   , wiContext      :: Maybe WebItemContext
+   , wiIcon         :: Maybe IconDetails
+   , wiStyleClasses :: [String]
+   } deriving (Show, Generic)
+
+data WebItemContext = PageContext | AddonContext | ProductContext
+   deriving(Show, Generic)
+
+instance ToJSON WebItemContext where
+   toJSON PageContext = String . T.pack $ "page"
+   toJSON AddonContext = String . T.pack $ "addon"
+   toJSON ProductContext = String . T.pack $ "product"
+
+-- TODO update the docs for the JIRAProjectAdminTabPanel based on this question: http://goo.gl/c6QUdd
+
+-- | A 'JIRAProjectAdminTabPanel' is useful for when you want to add a page to the administration screens of a project.
+-- This module will create a web item in the sidebar of every project for you and provide a web panel in the JIRA Project
+-- Admin section.
+data JIRAProjectAdminTabPanel = JIRAProjectAdminTabPanel
+   { jpatpKey        :: T.Text
+   , jpatpName       :: Name JIRAProjectAdminTabPanel
+   , jpatpUrl        :: T.Text
+   , jpatpLocation   :: T.Text
+   , jpatpConditions :: [Condition]
+   , jpatpWeight     :: Maybe Integer
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAProjectAdminTabPanel where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jpatp"
+      }
+
+instance ToJSON (Name JIRAProjectAdminTabPanel) where
+   toJSON = nameToValue
 
 -- | A 'GeneralPage' makes your add-on take a large section of screen realestate, with the intention of displaying
 -- your own page with no other distracting content. This is very useful for pages like Configuration screens or
diff --git a/tests/ModulesTest.hs b/tests/ModulesTest.hs
--- a/tests/ModulesTest.hs
+++ b/tests/ModulesTest.hs
@@ -15,6 +15,7 @@
 moduleTests = TestList
     [ testWebPanelCorrectFormat
     , testGeneralPageCorrectFormat
+    , testEmptyModulesAreShown
     ]
 
 testWebPanelCorrectFormat :: Test
@@ -57,3 +58,10 @@
     (getNumber =<< get "height" =<< get "icon" jv) `isEqualTo` 20
     (getNumber =<< get "weight" jv) `isEqualTo` 10000
     (isArray <$> get "conditions" jv) @? "Expected the conditions to be present."
+
+testEmptyModulesAreShown :: Test
+testEmptyModulesAreShown = TestCase $ do
+    let modules = Modules emptyJIRAModules emptyConfluenceModules
+    let jv = toJSON modules
+    fieldIsPresent "webPanels" jv @? "Expected the field webPanels to be present"
+    fieldIsPresent "generalPages" jv @? "Expected the field webPanels to be present"
diff --git a/tests/ValueExtractors.hs b/tests/ValueExtractors.hs
--- a/tests/ValueExtractors.hs
+++ b/tests/ValueExtractors.hs
@@ -1,7 +1,9 @@
 module ValueExtractors where
 
+import           Control.Applicative
 import           Data.Aeson
 import qualified Data.HashMap.Strict as M
+import           Data.Maybe          (isJust)
 import qualified Data.Scientific     as S
 import qualified Data.Text           as T
 import qualified Data.Vector         as V
@@ -11,6 +13,13 @@
     where
         notFound = fail $ "Could not find a value in object with key: " ++ T.unpack key
 get key _ = fail $ "The value was not an object when looking for: " ++ T.unpack key
+
+fieldIsPresent :: T.Text -> Value -> IO Bool
+fieldIsPresent key (Object o) = return . isJust $ M.lookup key o
+fieldIsPresent key _ = fail $ "The value was not an object when looking for: " ++ T.unpack key
+
+fieldIsNotPresent :: T.Text -> Value -> IO Bool
+fieldIsNotPresent key value = not <$> fieldIsPresent key value
 
 getArray :: Value -> IO [Value]
 getArray (Array v) = return . V.toList $ v
