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.2.0.1
+version:             0.3.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            Code that helps you create a valid Atlassian Connect Descriptor.
@@ -46,6 +46,10 @@
 -- Constraint on the version of Cabal needed to build this package.
 cabal-version:       >=1.10
 
+source-repository head
+  type:     git
+  location: git@bitbucket.org:robertmassaioli/atlassian-connect-descriptor.git
+
 flag network-uri
    description: Get Network.URI from the network-uri package
    default: True
@@ -119,6 +123,7 @@
     , time-units
     , cases
     , unordered-containers
+    , bytestring
 
   if flag(network-uri)
      build-depends: network-uri >= 2.6, network >= 2.6
diff --git a/src/Data/Connect/AesonHelpers.hs b/src/Data/Connect/AesonHelpers.hs
--- a/src/Data/Connect/AesonHelpers.hs
+++ b/src/Data/Connect/AesonHelpers.hs
@@ -2,6 +2,7 @@
    ( baseOptions
    , stripFieldNamePrefix
    , dropSuffixAndSnakeCase
+   , lowerAll
    ) where
 
 import qualified Cases            as CS
@@ -25,6 +26,9 @@
 lowerFirst :: String -> String
 lowerFirst (x : xs) = C.toLower x : xs
 lowerFirst [] = []
+
+lowerAll :: String -> String
+lowerAll = fmap C.toLower
 
 dropSuffix :: String -> String -> String
 dropSuffix suffix = reverse . try (L.stripPrefix . reverse $ suffix) . reverse
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
@@ -2,7 +2,22 @@
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE OverloadedStrings          #-}
-module Data.Connect.BaseTypes where
+module Data.Connect.BaseTypes
+   ( Key(..)
+   , PluginKey(..)
+   , Timeout(..)
+   , Vendor(..)
+   , Authentication(..)
+   , AuthType(..)
+   , IconDetails(..)
+   , Name(..)
+   , I18nText(..)
+   , simpleText
+   , URLBean(..)
+   , toUrl
+   , Length(..)
+   )
+   where
 
 import           Data.Aeson
 import           Data.Aeson.Types
@@ -19,6 +34,8 @@
 -- | This data type represents an Atlassian Connect Add-on key.
 data PluginKey = PluginKey Text deriving (Show, Eq, Generic)
 
+instance ToJSON PluginKey
+
 -- | Represents a timeout in seconds.
 newtype Timeout = Timeout DTU.Second deriving (Show, Eq, Enum, Num, Ord, Real, Integral)
 
@@ -47,12 +64,41 @@
    , iconHeight :: Maybe Integer -- ^ The height of the icon.
    } deriving (Show, Generic)
 
-instance ToJSON PluginKey
-
 -- | Atlassian Connect descriptors contain many names: module names, add-on names, vendor names etc. We want to make sure
 -- that these names don't get put in places that they do not belong. Or, if they do get moved around, they get moved around
 -- specifically. We are just adding type saefty to names.
 data Name a = Name Text deriving (Show, Eq, Generic)
+
+-- | Represents a standard text type in the descriptor than may be Internationalised in the future. However, currently
+-- there is no I18n support: <http://goo.gl/9vJEsW>
+data I18nText = I18nText
+   { dValue :: Text -- ^ The raw text value that will show.
+   , dI18n  :: Maybe Text -- ^ The potential i18n key that will be used when we eventually have I18n support: <http://goo.gl/9vJEsW>
+   } deriving (Show, Generic)
+
+instance ToJSON I18nText where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "d"
+      }
+
+-- | Since there is currently no I18n support (<http://goo.gl/9vJEsW>) we have this helper method to quickly create an 'I18nText' from a standard
+-- 'Text' object.
+simpleText :: Text -> I18nText
+simpleText t = I18nText { dValue = t, dI18n = Nothing }
+
+-- | This represents a URL wrapped as an object instead of as a plain text element.
+data URLBean = URLBean
+   { ubUrl :: Text -- ^ The raw URL.
+   } deriving (Show, Generic)
+
+instance ToJSON URLBean where
+   toJSON = genericToJSON baseOptions
+         { fieldLabelModifier = stripFieldNamePrefix "ub"
+         }
+
+-- | Wrap a regular 'Text' based URL inside a URLBean.
+toUrl :: Text -> URLBean
+toUrl = URLBean
 
 instance ToJSON (Name PluginKey)
 instance ToJSON (Name Vendor)
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
@@ -31,7 +31,7 @@
 >     , lifecycle = Just defaultLifecycle
 >     , modules = Just exampleModules
 >     , enableLicensing = Just False
->     , links = fromList
+>     , links = HM.fromList
 >         [ ("documentation", toURI "http://awesome-devs.com/docs")
 >         , ("source", toURI "http://bitbucket.org/awesome-devs/connect-addon")
 >         ]
@@ -43,31 +43,36 @@
 >
 > exampleJIRAModules :: JIRAModules
 > exampleJIRAModules = emptyJIRAModules
->     { jiraWebPanels =
+>     { jmWebPanels =
 >         [ WebPanel
 >             { wpKey = "test-web-panel"
->             , wpName = Name "Test Web Panel"
+>             , wpName = simpleText "Test Web Panel"
+>             , wpTooltip = Just $ simpleText "This is a test web panel..."
 >             , wpLocation = "some-location-in-jira"
 >             , wpUrl = "/panel/location/for"
 >             , wpConditions = [staticJiraCondition UserIsAdminJiraCondition]
+>             , wpWeight = Nothing
+>             , wpLayout = Nothing
+>             , wpParams = noParams
 >             }
 >         ]
->     , jiraGeneralPages =
->         [ GeneralPage
->             { generalPageKey = "test-general-page"
->             , generalPageName = Name "Test General Page"
->             , generalPageLocation = Just "some-other-location-in-jira"
->             , generalPageWeight = Just 1234
->             , generalPageUrl = "/panel/general-page"
->             , generalPageIcon = Just IconDetails
+>     , jmGeneralPages =
+>         [ JIRAPage
+>             { jiraPageKey = "test-general-page"
+>             , jiraPageName = simpleText "Test General Page"
+>             , jiraPageLocation = Just "some-other-location-in-jira"
+>             , jiraPageWeight = Just 1234
+>             , jiraPageUrl = "/panel/general-page"
+>             , jiraPageIcon = Just IconDetails
 >                 { iconUrl = "/static/path/to/icon.png"
 >                 , iconWidth = Just 20
 >                 , iconHeight = Just 40
 >                 }
->             , generalPageConditions = [staticJiraCondition UserHasIssueHistoryJiraCondition]
+>             , jiraPageConditions = [staticJiraCondition UserHasIssueHistoryJiraCondition]
+>             , jiraPageParams = noParams
 >             }
 >         ]
->     , jiraWebhooks =
+>     , jmWebhooks =
 >         [ Webhook
 >             { webhookEvent = JiraIssueDeleted
 >             , webhookUrl = "/webhook/handle-deletion"
@@ -84,17 +89,22 @@
      Plugin(..)
    , pluginDescriptor
    -- * Basic Types
-   , Name(..)
    , Key(..)
    , PluginKey(..)
    , Timeout(..)
-   , IconDetails(..)
-   , Length(..)
-   -- * Authentication
+   , Vendor(..)
    , Authentication(..)
    , AuthType(..)
-   -- * Vendor Details
-   , Vendor(..)
+   , IconDetails(..)
+   , Name(..)
+   , I18nText(..)
+   , simpleText
+   , URLBean(..)
+   , toUrl
+   , Length(..)
+   , Weight
+   , ModuleParams
+   , noParams
    -- * Lifecycle
    , Lifecycle(..)
    , emptyLifecycle
@@ -105,10 +115,28 @@
    , emptyJIRAModules
    , ConfluenceModules(..)
    , emptyConfluenceModules
+   -- ** Web Sections, Items and Panels
+   , JIRAWebSection(..)
+   , WebItem(..)
    , WebPanel(..)
    , WebPanelLayout(..)
-   , GeneralPage(..)
+   -- ** JIRA Pages
+   , JIRAPage(..)
+   -- ** JIRA Tab Panels
+   , JIRAGenericTabPanel(..)
    , JIRAProjectAdminTabPanel(..)
+   -- ** JIRA Specific Modules
+   , JIRASearchRequestView(..)
+   , JIRAReport(..)
+   , Target(..)
+   , JIRAWorkflowPostFunction(..)
+   , DialogOptions(..)
+   , InlineDialogOptions(..)
+   , JIRAEntityProperties(..)
+   , EntityType(..)
+   , KeyConfiguration(..)
+   , Extraction(..)
+   , ExtractionType(..)
    -- ** 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
@@ -6,12 +6,59 @@
    , emptyJIRAModules
    , ConfluenceModules(..)
    , emptyConfluenceModules
+   , JIRAWebSection(..)
+   , WebItem(..)
    , WebPanel(..)
    , WebPanelLayout(..)
-   , GeneralPage(..)
+   , JIRAPage(..)
+   , JIRAGenericTabPanel(..)
    , JIRAProjectAdminTabPanel(..)
+   , JIRASearchRequestView(..)
+   , JIRAReport(..)
+   , Target(..)
+   , JIRAWorkflowPostFunction(..)
+   , DialogOptions(..)
+   , InlineDialogOptions(..)
+   , JIRAEntityProperties(..)
+   , EntityType(..)
+   , KeyConfiguration(..)
+   , Extraction(..)
+   , ExtractionType(..)
+   , ModuleParams
+   , noParams
+   , Weight
    ) where
 
+{-
+Supported JIRA Modules
+
+webSections
+webItems
+webPanels
+
+generalPages
+adminPages
+configurePage
+
+jiraProfileTabPanels
+jiraVersionTabPanels
+jiraProjectTabPanels
+jiraProjectAdminTabPanels
+jiraIssueTabPanels
+jiraComponentTabPanels
+
+jiraSearchRequestViews
+
+jiraReports
+
+webhooks
+
+jiraWorkflowPostFunctions
+
+jiraEntityProperties
+
+-}
+
 import           Data.Aeson
 import           Data.Aeson.Types
 import           Data.Connect.AesonHelpers
@@ -51,15 +98,28 @@
 -- | 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]
-   , jiraJiraProjectAdminTabPanels :: [JIRAProjectAdminTabPanel]
+   { jmWebSections               :: [JIRAWebSection]
+   , jmWebItems                  :: [WebItem]
+   , jmWebPanels                 :: [WebPanel]
+   , jmGeneralPages              :: [JIRAPage]
+   , jmAdminPages                :: [JIRAPage]
+   , jmConfigurePage             :: Maybe JIRAPage
+   , jmJiraSearchRequestViews    :: [JIRASearchRequestView]
+   , jmJiraProfileTabPanels      :: [JIRAGenericTabPanel]
+   , jmJiraVersionTabPanels      :: [JIRAGenericTabPanel]
+   , jmJiraProjectTabPanels      :: [JIRAGenericTabPanel]
+   , jmJiraProjectAdminTabPanels :: [JIRAProjectAdminTabPanel]
+   , jmJiraIssueTabPanels        :: [JIRAGenericTabPanel]
+   , jmJiraComponentTabPanels    :: [JIRAGenericTabPanel]
+   , jmJiraReports               :: [JIRAReport]
+   , jmWebhooks                  :: [Webhook]
+   , jmJiraWorkflowPostFunctions :: [JIRAWorkflowPostFunction]
+   , jmJiraEntityProperties      :: [JIRAEntityProperties]
    } deriving (Show, Generic)
 
 instance ToJSON JIRAModules where
    toJSON = genericToJSON baseOptions
-      { fieldLabelModifier = stripFieldNamePrefix "jira"
+      { fieldLabelModifier = stripFieldNamePrefix "jm"
       }
 
 -- | A collection of all of the Confluence Modules that you can define. For more documentation on which Modules are supported
@@ -75,12 +135,42 @@
 
 -- | Empty JIRA Modules; useful when you only want to define a few modules via Haskell record syntax.
 emptyJIRAModules :: JIRAModules
-emptyJIRAModules = JIRAModules [] [] [] []
+emptyJIRAModules = JIRAModules [] [] [] [] [] Nothing [] [] [] [] [] [] [] [] [] [] []
 
 -- | Empty Confluence Modules; useful when you only want to define a few modules via Haskell record syntax.
 emptyConfluenceModules :: ConfluenceModules
 emptyConfluenceModules = ConfluenceModules []
 
+-- | Represents the weight of an element in a menu.
+type Weight = Integer
+
+-- | The standard representation for module parameters.
+type ModuleParams = HM.HashMap T.Text T.Text
+
+-- | No parameters. A useful helper when you don't want to pass any parameters to a module.
+noParams :: ModuleParams
+noParams = HM.empty
+
+-- | A 'JIRAWebSection' represents a location in the host application that you can add 'WebItem's to. In this way you
+-- can give your add-on sections to inject content into.
+--
+-- For more information read the Atlassian Connect documentation:
+-- <https://developer.atlassian.com/static/connect/docs/modules/jira/web-section.html>
+data JIRAWebSection = JIRAWebSection
+   { jwsKey        :: T.Text -- ^ The add-on unique key for this module.
+   , jwsName       :: I18nText -- ^ The name of this section, likely to appear in the User Interface.
+   , jwsLocation   :: T.Text -- ^ The location in the application interface where the web section should appear.
+   , jwsTooltip    :: Maybe I18nText -- ^ The internationalised text to be used in the link's tooltip.
+   , jwsConditions :: [Condition] -- ^ The conditions under which to show this web section.
+   , jwsWeight     :: Maybe Weight -- ^ The higher the weight the lower down the menu it will appear.
+   , jwsParams     :: ModuleParams -- ^ Optional parameters to pass to the web section.
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAWebSection where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "tt"
+      }
+
 -- | A 'WebPanel' is an injectable segment of the host application that you can place content inside. Currently the
 -- WebPanel has the same structure for both JIRA and Confluence but, potentially, that could change in the future.
 -- You can read their Atlassian Connect documentation here:
@@ -103,12 +193,14 @@
 -- WebPanels are a great way to inject your add-on's content into the host application.
 data WebPanel = WebPanel
    { wpKey        :: T.Text -- ^ The add-on unique key for this module.
-   , wpName       :: Name WebPanel -- ^ The name of this panel, likely to appear in the User Interface.
+   , wpName       :: I18nText -- ^ The name of this panel, likely to appear in the User Interface.
    , 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
+   , wpTooltip    :: Maybe I18nText -- ^ A tooltip that explains what this is for.
+   , wpWeight     :: Maybe Weight -- ^ Web panels can be ordered and a higher weight makes you appear lower down the page.
+   , wpLayout     :: Maybe WebPanelLayout -- ^ You can specify the dimensions of this panel. This will only be considered in certain locations.
+   , wpParams     :: ModuleParams -- ^ You can pass parameters to the web panel.
    } deriving (Show, Generic)
 
 instance ToJSON WebPanel where
@@ -127,40 +219,130 @@
       { fieldLabelModifier = stripFieldNamePrefix "wpl"
       }
 
-{-
+-- | A 'WebItem' is a like that can be placed in one of an Atlassian Products many menus. Currently the WebItem has the
+-- same structure for both JIRA and Confluence. You can read their documentation here:
+--
+-- * JIRA Web Items: <https://developer.atlassian.com/static/connect/docs/modules/jira/web-item.html>
+-- * Confluence Web Items: <https://developer.atlassian.com/static/connect/docs/modules/confluence/web-item.html>
+--
+-- Web items are very useful for providing links to your Atlassian Connect pages. See 'GeneralPage' or 'AdminPage' for
+-- more information.
 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]
+   { wiKey          :: T.Text -- ^ The add-on unique key for this module.
+   , wiName         :: I18nText -- ^ The name of this web item. It will appear as the text of the link.
+   , wiLocation     :: T.Text -- ^ Where in the product UI this web item will appear.
+   , wiUrl          :: T.Text -- ^ The URL to direct the user to. May be relative to the host Product or the Addon depending on the context.
+   , wiTooltip      :: Maybe I18nText -- ^ An optional tooltip for the link.
+   , wiIcon         :: Maybe IconDetails -- ^ An optional icon to display with the link text or as the link
+   , wiWeight       :: Maybe Weight -- ^ The higher the weight the lower down in the location menu this web item will appear.
+   , wiTarget       :: Maybe Target -- ^ Determines the way the link is opened. In the page, in a dialog or in an inline dialog.
+   , wiStyleClasses :: [T.Text] -- ^ Specifies custom styles for the web item target page
+   , wiContext      :: Maybe WebItemContext -- ^ Determines if the url is relative to the page, product or connect addon.
+   , wiConditions   :: [Condition] -- ^ Determines the conditions under which to show this link.
+   , wiParams       :: ModuleParams -- ^ Optional parameters that you can pass to the web item.
    } deriving (Show, Generic)
 
+instance ToJSON WebItem where
+   toJSON = genericToJSON baseOptions
+         { fieldLabelModifier = lowerAll . stripFieldNamePrefix "wi"
+         }
+
+-- | A 'Target' represents the location that a link will be opened into.
+data Target
+   = TargetPage -- ^ Open the link into the current page.
+   | TargetDialog (Maybe DialogOptions) -- ^ Open the link into a dialog on the page with the given options.
+   | TargetInlineDialog (Maybe InlineDialogOptions) -- ^ Open the link into an inline dialog with the given options.
+   deriving (Show)
+
+tp :: String -> T.Text
+tp = T.pack
+
+instance ToJSON Target where
+   toJSON (TargetPage) = object [tp "type" .= tp "page"]
+   toJSON (TargetDialog potentialOptions) = object $ tp "type" .= tp "dialog" :
+      case potentialOptions of
+         Just options -> [tp "options" .= toJSON options]
+         Nothing -> []
+   toJSON (TargetInlineDialog potentialOptions) = object $ tp "type" .= tp "inlinedialog" :
+      case potentialOptions of
+               Just options -> [tp "options" .= toJSON options]
+               Nothing -> []
+
+-- | Options for a dialog that a link may be opened into.
+data DialogOptions = DialogOptions
+   { doHeight :: Maybe Integer -- ^ The height of the dialog on the page.
+   , doWidth  :: Maybe Integer -- ^ The width of the dialog on the page.
+   , doChrome :: Maybe Bool -- ^ Whether the dialog should contain the AUI header and buttons. Default is true
+   } deriving (Show, Generic)
+
+instance ToJSON DialogOptions where
+   toJSON = genericToJSON baseOptions
+         { fieldLabelModifier = lowerAll . stripFieldNamePrefix "do"
+         }
+
+-- | Options for an inline dialog that a link may be opened into.
+data InlineDialogOptions = InlineDialogOptions
+   { idoWidth             :: Maybe T.Text -- ^ Sets how wide the inline-dialog is in pixels
+   , idoOnTop             :: Maybe Bool -- ^ Determines if the dialog should be shown above the trigger or not
+   , idoIsRelativeToMouse :: Maybe Bool -- ^ Determines if the dialog should be shown relative to where the mouse is at the time of the event trigger
+   , idoShowDelay         :: Maybe Integer -- ^ Determines how long in milliseconds after a show trigger is fired until the dialog is shown
+   , idoOnHover           :: Maybe Bool -- ^ Determines whether the inline-Dialog will show on a mouseOver or mouseClick of the trigger
+   , idoOffsetX           :: Maybe T.Text -- ^ Sets an offset distance of the inline-dialog from the trigger element along the x-axis in pixels
+   , idoOffsetY           :: Maybe T.Text -- ^ Sets an offset distance of the inline-dialog from the trigger element along the y-axis in pixels
+   , idoPersistent        :: Maybe Bool -- ^ This option, ignores the 'closeOthers' option
+   , idoCloseOthers       :: Maybe Bool -- ^ Cetermines if all other dialogs on the screen are closed when this one is opened
+   } deriving (Show, Generic)
+
+instance ToJSON InlineDialogOptions where
+   toJSON = genericToJSON baseOptions
+         { fieldLabelModifier = lowerAll . stripFieldNamePrefix "ido"
+         }
+
+-- TODO this cannot have a generic implimentation
+
+-- | Wether to open the url relative to the current page, the current addon or the current product. This lets you control
+-- where Atlassian Connect web items point to.
 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"
--}
+   toJSON PageContext = stj "page"
+   toJSON AddonContext = stj "addon"
+   toJSON ProductContext = stj "product"
 
+stj :: String -> Value
+stj = String . T.pack
+
+-- | JIRA has the concept of a TabPanel which is a panel where you can inject content along with a 'WebItem' that is
+-- automatically created for you so that you can navigate to the tab panel in question. Tab panels often have a common format
+-- and this 'JIRAGenericTabPanel' encapsulates that common format and allows you to apply it to many different scenarios.
+data JIRAGenericTabPanel = JIRAGenericTabPanel
+   { jtpKey        :: T.Text -- ^ The add-on unique key for this module.
+   , jtpName       :: I18nText -- ^ The user facing name of this panel. Likely to appear as the name of the link to the tab panel.
+   , jtpUrl        :: T.Text -- ^ The URL to your addon where you will provide the content for the panel.
+   , jtpConditions :: [Condition] -- ^ The conditions under which this tapb panel should be displayed.
+   , jtpWeight     :: Maybe Weight -- ^ The higher the weight the lower down in the list of tabs the link to this tab panel will be displayed.
+   , jtpParams     :: ModuleParams -- ^ Optional parameters for the tab panel.
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAGenericTabPanel where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jtp"
+      }
+
 -- 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
+   { jpatpKey        :: T.Text -- ^ The add-on unique key for this module.
+   , jpatpName       :: I18nText -- ^ The user facing name of this panel. Likely to appear as the name of the link to the tab panel.
+   , jpatpUrl        :: T.Text -- ^ The URL to your addon where you will provide the content for the panel.
+   , jpatpLocation   :: T.Text -- ^ The location in JIRA Admin that you wish the link to this panel to appear.
+   , jpatpConditions :: [Condition] -- ^ The conditions under which this panel should be displayed. UserIsAdminCondition is redundant.
+   , jpatpWeight     :: Maybe Weight -- ^ The higher the weight the lower down in the list of tabs the link to this tab panel will be displayed.
+   , jpatpParams     :: ModuleParams -- ^ Optional parameters for the tab panel.
    } deriving (Show, Generic)
 
 instance ToJSON JIRAProjectAdminTabPanel where
@@ -168,41 +350,185 @@
       { 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
--- Statistics pages where you really want the user to be fully working with your add-on inside the host product.
+-- | A 'JIRAPage' is gives you a location in the host product that you addon can present content and behave just like any
+-- other host product page. The main types of pages in JIRA are:
 --
+-- * General pages: for just getting a geniric chunk of realestate to display your content.
+-- * Admin pages: for getting a page in the admin seciton of JIRA to display your content.
+-- * Configuration page: Every Atlassian Connect plugin can have a configuration page to configure the plugin when installed.
+--
+-- This is very useful for pages like Configuration screens or Statistics pages where you really want the user to be
+-- immersed in working with your add-on inside the host product.
+--
 -- General pages, like Web Panels, are common to JIRA and Confluence and share the same json format. However they have
 -- separate documentation:
 --
 -- * JIRA General Page: <https://developer.atlassian.com/static/connect/docs/modules/jira/general-page.html>
 -- * Confluence General Page: <https://developer.atlassian.com/static/connect/docs/modules/confluence/general-page.html>
 --
--- Even though, at this point in time, the documentation looks identical.
-data GeneralPage = GeneralPage
-   { generalPageKey        :: T.Text -- ^ The add-on unique key for this module.
-   , generalPageName       :: Name GeneralPage -- ^ The name of this General Page. Likely to be used in the page title.
-   , generalPageUrl        :: T.Text -- ^ The relative URI that the host product will hit to get the HTML content for the page.
-   , generalPageLocation   :: Maybe T.Text -- ^ The location for this General Page to display; see the docs for your options.
-   , generalPageIcon       :: Maybe IconDetails -- ^ The optional icon to use for this general page.
-   , generalPageWeight     :: Maybe Integer -- ^ Determines the order that this item appears in any menu or list.
-                                            -- Lower numbers mean that it will appear higher in the list.
-   , generalPageConditions :: [Condition] -- ^ The 'Condition's that need to be met for this module to be displayed.
+-- Even though, at this point in time, the documentation looks identical. You can find the Admin page and Configure page
+-- documentation in the official Atlassian Connect documentation too.
+data JIRAPage = JIRAPage
+   { jiraPageKey        :: T.Text -- ^ The add-on unique key for this module.
+   , jiraPageName       :: I18nText -- ^ The name of this JIRA page. Likely to be used in the page title.
+   , jiraPageUrl        :: T.Text -- ^ The relative URI that the host product will hit to get the HTML content for the page.
+   , jiraPageLocation   :: Maybe T.Text -- ^ The location for this General Page to display; see the docs for your options.
+   , jiraPageWeight     :: Maybe Weight -- ^ Determines the order that this item appears in any menu or list.
+                                        -- Lower numbers mean that it will appear higher in the list.
+   , jiraPageIcon       :: Maybe IconDetails -- ^ The optional icon to use for this JIRA page.
+   , jiraPageConditions :: [Condition] -- ^ The 'Condition's that need to be met for this page to be displayed.
+   , jiraPageParams     :: ModuleParams -- ^ Optional parameters for the page.
    } deriving (Show, Generic)
 
-instance ToJSON GeneralPage where
+instance ToJSON JIRAPage where
    toJSON = genericToJSON baseOptions
-      { fieldLabelModifier = stripFieldNamePrefix "generalPage"
+      { fieldLabelModifier = stripFieldNamePrefix "jiraPage"
       }
 
-instance ToJSON (Name WebPanel) where
-   toJSON = nameToValue
+-- |  A Search Request View allows you to render a custom representation of a search result. Rendering a custom XML
+-- format is a common example.
+--
+-- For more information read the Atlassian Connect documentation:
+-- <https://developer.atlassian.com/static/connect/docs/modules/jira/search-request-view.html>
+data JIRASearchRequestView = JIRASearchRequestView
+   { jsrvKey         :: T.Text -- ^ The add-on unique key for this module.
+   , jsrvName        :: I18nText -- ^ The name of this Search Request View. Will appear in the Export menu.
+   , jsrvUrl         :: T.Text -- ^ This URL will render the search results.
+   , jsrvDescription :: Maybe I18nText -- ^ The description of this view.
+   , jsrvWeight      :: Maybe Weight -- ^ A higher weight puts the link further down the export menu.
+   , jsrvConditions  :: [Condition] -- ^ The conditions under which this option should show.
+   , jsrvParams      :: ModuleParams -- ^ The optional parameters to this search request view.
+   } deriving (Show, Generic)
 
-instance ToJSON (Name GeneralPage) where
-   toJSON = nameToValue
+instance ToJSON JIRASearchRequestView where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jsrv"
+      }
 
-nameToValue :: Name a -> Value
-nameToValue (Name name) = object [ T.pack "value" .= name ]
+-- | A 'JIRAReport' will provide a report on the JIRA issues in the project. It allows you to write custom reporting
+-- for JIRA.
+--
+-- For more information read the Atlassian Connect documentation:
+-- <https://developer.atlassian.com/static/connect/docs/modules/jira/report.html>
+data JIRAReport = JIRAReport
+   { jrKey            :: T.Text -- ^ The add-on unique key for this module.
+   , jrName           :: I18nText -- ^ The user facing name of this report.
+   , jrUrl            :: T.Text -- ^ The URL that will render the report back to the user.
+   , jrDescription    :: I18nText -- ^ The required user facing description of this report.
+   , jrReportCategory :: Maybe JIRAReportCategory -- ^ The category that this report should be placed inside.
+   , jrWeight         :: Maybe Weight -- ^ A higher weight will push this report further down the list of reports.
+   , jrThumbnailUrl   :: Maybe T.Text -- ^ A thumbnail that gives a gist of what this report is supposed to accomplish.
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAReport where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jr"
+      }
+
+-- | The report category for a 'JIRAReport'. Useful in organising the different types of reports.
+data JIRAReportCategory
+   = AgileRC -- ^ This report is visible to agile customers.
+   | IssueAnalysisRC -- ^ This report does issue analysis.
+   | ForecastManagementRC -- ^ This report considers future of the project state.
+   | OtherRC -- ^ Any report that does not fit into the other categories goes here.
+   deriving (Show)
+
+instance ToJSON JIRAReportCategory where
+   toJSON AgileRC = stj "agile"
+   toJSON IssueAnalysisRC = stj "issue_analysis"
+   toJSON ForecastManagementRC = stj "forecast_management"
+   toJSON OtherRC = stj "other"
+
+-- | A 'JIRAWorkflowPostFunction' carries out any additional processing required after a JIRA workflow transition is executed.
+--
+-- For more information read the Atlassian Connect documentation:
+-- <https://developer.atlassian.com/static/connect/docs/modules/jira/workflow-post-function.html>
+--
+-- Or you could read the JIRA documentation on Workflow Post Functions to learn more:
+-- <https://confluence.atlassian.com/display/Cloud/Advanced+Workflow+Configuration#AdvancedWorkflowConfiguration-postfunctions>
+data JIRAWorkflowPostFunction = JIRAWorkflowPostFunction
+   { jwpfKey         :: T.Text -- ^ The add-on unique key for this module.
+   , jwpfName        :: I18nText -- ^ The user facing name of this workflow post function.
+   , jwpfTriggered   :: URLBean -- ^ The add-on URL to hit when the post function is triggered. The URL will be POST'ed
+                                -- to and you should read the Atlassian Connect docs for more details.
+   , jwpfDescription :: Maybe I18nText -- ^ The user facing description of this post function.
+   , jwpfCreate      :: Maybe URLBean -- ^ The add-on URL to the configuration page for the post function when it is created.
+   , jwpfEdit        :: Maybe URLBean -- ^ The add-on URL to the configuration edit page of the post function.
+   , jwpfView        :: Maybe URLBean -- ^ The add-on URL to the view page for the read-only view of the configuration.
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAWorkflowPostFunction where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jwpf"
+      }
+
+-- | 'JIRAEntityProperties' are used to set Key / Value pair information on JIRA Issues that can be searched via JQL and
+-- are indexed by JIRA. The can also be accessed directly via rest api so they allow you to store data in client-only
+-- Atlassian Connect plugins. Very handy!
+--
+-- The data stored as entity properties is in the JSON data format so multiple values can be stored against the one property.
+--
+-- For more information read the JIRA Documentation on the topic:
+-- <https://developer.atlassian.com/display/JIRADEV/JIRA+Entity+Properties+Overview>
+--
+-- Or read the Atlassian Connect documentation on the topic:
+-- <https://developer.atlassian.com/static/connect/docs/modules/jira/entity-property.html>
+data JIRAEntityProperties = JIRAEntityProperties
+   { jepKey               :: T.Text -- ^ The add-on unique key for this module.
+   , jepName              :: I18nText -- ^ The user facing name of this entity property.
+   , jepEntityType        :: Maybe EntityType -- ^ The entity type that you want to attach this property to. Issue by default.
+   , jepKeyConfigurations :: [KeyConfiguration] -- ^ The list of key configurations that you wish to define.
+   } deriving (Show, Generic)
+
+instance ToJSON JIRAEntityProperties where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "jep"
+      }
+
+-- | An 'EntityType' represents the type of entity that the JIRA Entity Property should be attatched to. By default
+-- entity types are attatched to issues.
+data EntityType = IssueEntityType
+   deriving (Show)
+
+instance ToJSON EntityType where
+   toJSON IssueEntityType = stj "issue"
+
+-- | A 'KeyConfiguration' is the key for this particular property and the JSON flattened paths to the elements that
+-- should be extracted from this property. For more information see the Atlassian Connect documentation:
+-- <https://developer.atlassian.com/static/connect/docs/modules/fragment/index-key-configuration.html>
+data KeyConfiguration = KeyConfiguration
+   { kcPropertyKey :: T.Text -- ^ The name of the JIRA Entity Property
+   , kcExtractions :: [Extraction] -- ^ All of the data extractions from the property that should be indexed.
+   } deriving (Show, Generic)
+
+instance ToJSON KeyConfiguration where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "kc"
+      }
+
+-- | An 'Extraction' represents a snippet of data that should be extracted from a 'KeyConfiguration' such that it is
+-- Indexed by JIRA and capable of being searched in JQL.
+data Extraction = Extraction
+   { extractionObjectName :: T.Text
+   , extractionType       :: ExtractionType
+   } deriving (Show, Generic)
+
+instance ToJSON Extraction where
+   toJSON = genericToJSON baseOptions
+      { fieldLabelModifier = stripFieldNamePrefix "extraction"
+      }
+
+-- | The style in which the data should be extracted and indexed. For example, you may want the data to be treated as a
+-- Date or as a Number.
+data ExtractionType
+   = ExtractionTypeNumber -- ^ Index the data as a numeric type.
+   | ExtractionTypeText -- ^ Index the data as a text based type, with words.
+   | ExtractionTypeString -- ^ Index the data as an exact string.
+   | ExtractionTypeDate -- ^ Index the data as a Date.
+   deriving(Show)
+
+instance ToJSON ExtractionType where
+   toJSON ExtractionTypeNumber = stj "number"
+   toJSON ExtractionTypeText = stj "text"
+   toJSON ExtractionTypeString = stj "string"
+   toJSON ExtractionTypeDate = stj "date"
diff --git a/tests/DescriptorTest.hs b/tests/DescriptorTest.hs
--- a/tests/DescriptorTest.hs
+++ b/tests/DescriptorTest.hs
@@ -5,12 +5,13 @@
 import           Control.Applicative
 import           Data.Aeson
 import           Data.Connect.Descriptor
-import           Data.HashMap.Strict
+import qualified Data.HashMap.Strict     as HM
 import           Data.Maybe              (fromJust)
 import qualified Data.Text               as T
 import           Network.URI
 import           Test.HUnit
 import           ValueExtractors
+import qualified Data.ByteString.Lazy.Char8 as BLC
 
 toURI :: String -> URI
 toURI = fromJust . parseURI
@@ -26,7 +27,7 @@
     , lifecycle = Just defaultLifecycle
     , modules = Just exampleModules1
     , enableLicensing = Just False
-    , links = fromList
+    , links = HM.fromList
         [ ("documentation", toURI "http://awesome-devs.com/docs")
         , ("source", toURI "http://bitbucket.org/awesome-devs/connect-addon")
         ]
@@ -38,31 +39,36 @@
 
 exampleJIRAModules :: JIRAModules
 exampleJIRAModules = emptyJIRAModules
-    { jiraWebPanels =
+    { jmWebPanels =
         [ WebPanel
             { wpKey = "test-web-panel"
-            , wpName = Name "Test Web Panel"
+            , wpName = simpleText "Test Web Panel"
             , wpLocation = "some-location-in-jira"
             , wpUrl = "/panel/location/for"
             , wpConditions = [staticJiraCondition UserIsAdminJiraCondition]
+            , wpParams = HM.singleton "single" "ton"
+            , wpTooltip = Just . simpleText $ "A random tooltip here."
+            , wpWeight = Just 2468
+            , wpLayout = Just $ WebPanelLayout (Pixels 963) (Percentage 40)
             }
         ]
-    , jiraGeneralPages =
-        [ GeneralPage
-            { generalPageKey = "test-general-page"
-            , generalPageName = Name "Test General Page"
-            , generalPageLocation = Just "some-other-location-in-jira"
-            , generalPageWeight = Just 1234
-            , generalPageUrl = "/panel/general-page"
-            , generalPageIcon = Just IconDetails
+    , jmGeneralPages =
+        [ JIRAPage
+            { jiraPageKey = "test-general-page"
+            , jiraPageName = simpleText "Test General Page"
+            , jiraPageLocation = Just "some-other-location-in-jira"
+            , jiraPageWeight = Just 1234
+            , jiraPageUrl = "/panel/general-page"
+            , jiraPageIcon = Just IconDetails
                 { iconUrl = "/static/path/to/icon.png"
                 , iconWidth = Just 20
                 , iconHeight = Just 40
                 }
-            , generalPageConditions = [staticJiraCondition UserHasIssueHistoryJiraCondition]
+            , jiraPageConditions = [staticJiraCondition UserHasIssueHistoryJiraCondition]
+            , jiraPageParams = HM.empty
             }
         ]
-    , jiraWebhooks =
+    , jmWebhooks =
         [ Webhook
             { webhookEvent = JiraIssueDeleted
             , webhookUrl = "/webhook/handle-deletion"
@@ -78,6 +84,7 @@
 basicDescriptorTest :: Test
 basicDescriptorTest = TestCase $ do
     let jv = toJSON exampleDescriptor1
+    BLC.putStrLn . encode $ exampleDescriptor1
     isObject jv @? "Expect the descriptor to be one big json object."
     (getString =<< get "key" jv) `isEqualTo` "my-example-connect"
     (getString =<< get "baseUrl" jv) `isEqualTo` (T.pack . show $ baseURL)
diff --git a/tests/ModulesTest.hs b/tests/ModulesTest.hs
--- a/tests/ModulesTest.hs
+++ b/tests/ModulesTest.hs
@@ -8,6 +8,7 @@
 import           Data.Connect.Conditions (JIRACondition (..),
                                           staticJiraCondition)
 import           Data.Connect.Modules
+import qualified Data.HashMap.Strict     as HM
 import           Test.HUnit
 import           ValueExtractors
 
@@ -22,10 +23,14 @@
 testWebPanelCorrectFormat = TestCase $ do
     let wp = WebPanel
               { wpKey = "web-panel-key"
-              , wpName = Name "My web panel"
+              , wpName = simpleText "My web panel"
               , wpUrl = "/panel/my-panel?issue_key={issue.key}"
               , wpLocation = "atl.jira.view.issue.right.context"
               , wpConditions = [staticJiraCondition UserIsAdminJiraCondition]
+              , wpTooltip = Just . simpleText $ "A tooltip for the web panel..."
+              , wpWeight = Just 1234
+              , wpLayout = Just $ WebPanelLayout (Pixels 321) (Percentage 80)
+              , wpParams = HM.fromList [("one", "1"), ("two", "2")]
               }
     let jv = toJSON wp
     isObject jv @? "Expected the web panel to be an object"
@@ -37,14 +42,15 @@
 
 testGeneralPageCorrectFormat :: Test
 testGeneralPageCorrectFormat = TestCase $ do
-    let gp = GeneralPage
-              { generalPageKey = "general-page-key"
-              , generalPageName = Name "General Page Name"
-              , generalPageUrl = "/panel/page-panel-name?page_id={page.id}"
-              , generalPageLocation = Just "some-confluence-location"
-              , generalPageIcon = Just $ IconDetails "/path/to/icon" (Just 10) (Just 20)
-              , generalPageWeight = Just 10000
-              , generalPageConditions = [staticJiraCondition IsIssueReportedByCurrentUserJiraCondition]
+    let gp = JIRAPage
+              { jiraPageKey = "general-page-key"
+              , jiraPageName = simpleText "General Page Name"
+              , jiraPageUrl = "/panel/page-panel-name?page_id={page.id}"
+              , jiraPageLocation = Just "some-confluence-location"
+              , jiraPageIcon = Just $ IconDetails "/path/to/icon" (Just 10) (Just 20)
+              , jiraPageWeight = Just 10000
+              , jiraPageConditions = [staticJiraCondition IsIssueReportedByCurrentUserJiraCondition]
+              , jiraPageParams = HM.fromList [("gpOne", "gp1"), ("gpTwo", "gp2")]
               }
     let jv = toJSON gp
     isObject jv @? "Expected the web panel to be an object"
