When working with eXo, it is important not to modify the source code. This will ensure compatibility with future upgrades, and support will be simplified.
To customize your portal, you need to create an extension project by providing your own artifacts as a set of wars/jars/ears.


h1. Create your extension project {anchor:id=DEV.CreateYourOwnPortal.CreateExtensionProject}

A custom extension contains two mandatory items:

1. *extension webapp* contains resources and kernel configurations.

2. *extension activator jar* identifies your webapp as a dependency of the portal container.

To see the sample extension package, go to [here|https://github.com/exoportal/exogtn/tree/master/examples/extension].

Once you have modified the sample extension to build your own portal, use "mvn clean install" to create the archive files.

To deploy your extension in Tomcat, do as follows:

*Step 1:* Add the file sample-ext.war from the {{sample/extension/war/target/}} to the directory {{tomcat/webapps}}.

*Step 2:* Add the folder {{starter}} from {{starter/war/target/}} to the directory {{tomcat/webapps}}.

*Step 3:* Rename the directory (unzipped folder) {{starter}} to {{starter.war}}.

{note}
This will only work if the starter.war is the last .war file to be loaded, so you may need to rename it if your war files are loaded in the alphabetical order.
{note}

*Step 4:* Add the .jar file {{exo.portal.sample.extension.config-X.Y.Z.jar}} from {{sample/extension/config/target/}} to the {{tomcat/lib}} directory.

*Step 5:* Add the .jar file {{exo.portal.sample.extension.jar-X.Y.Z.jar}} from {{sample/extension/jar/target/}} to the {{tomcat/lib}} directory.


For JBoss deployment and more details, refer to Reference Guide on [here|http://docs.exoplatform.org/PLF30/refguide/html/index.html].


h1. Structure of portal, pages and menus {anchor:id=DEV.CreateYourOwnPortal.StructureOfPortalPages&Menus}

You can create multiple pages within a single portal. Permissions can be defined to make them visible only to specific groups and/or users. This chapter describes how to define this structure.

h2. Page layout {anchor:id=DEV.CreateYourOwnPortal.PageLayout}

The configuration of "classic" portal can be found in the {{/src/main/webapp/WEB-INF/conf/sample-ext/portal/portal/classic}} directory of your extension webapp.

*Portal:*

The {{portal.xml}} file describes the layout and portlets common to all pages of the portal.

{code}<?xml version="1.0" encoding="ISO-8859-1"?>
<portal-config
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_objects_1_0 http://www.gatein.org/xml/ns/gatein_objects_1_0"
    xmlns="http://www.gatein.org/xml/ns/gatein_objects_1_0">
  <portal-name>classic</portal-name>
  <locale>en</locale>
  <access-permissions>Everyone</access-permissions>
  <edit-permission>*:/platform/administrators</edit-permission>
  <properties>
    <entry key="sessionAlive">onDemand</entry>
  </properties>
    
     <portal-layout>
      <portlet-application>
      <portlet>
        <application-ref>web</application-ref>
        <portlet-ref>BannerPortlet</portlet-ref>
        <preferences>
          <preference>
            <name>template</name>
            <value>par:/groovy/groovy/webui/component/UIBannerPortlet.gtmpl</value>
            <read-only>false</read-only>
          </preference>
        </preferences>
      </portlet>
      <access-permissions>Everyone</access-permissions>
        <show-info-bar>false</show-info-bar>
      </portlet-application>

      <portlet-application>
      <portlet>
       ...
      </portlet>
      </portlet-application>
        
      <portlet-application>
      <portlet>
        ...
      </portlet>
      </portlet-application>
      
      <page-body> </page-body>
      
     <portlet-application>
       <portlet>
         ...
       </portlet>
     </portlet-application>
  </portal-layout>
</portal-config>
{code}


As you can see, each portlet can be configured with a set of preferences, which will be further detailed in Chapter 6. The tag <page-body> </page-body> is a placeholder for the different pages of your portal. When the user opens a new portal page, all portlets of the portal layout (portal.xml) are remained, whereas the content of <page-body> switches to the page opened by the user.

*Pages:*

The {{pages.xml}} file is used to describe the content of pages of your portal. In other words, pages of your portal will be inside the <page-body> tag of the {{portal.xml}} file above.

This is the example of pages.xml of the classic portal.

{code}
<page>
    <name>homepage</name>
    <title>Home Page</title>
    <access-permissions>Everyone</access-permissions>
    <edit-permission>*:/platform/administrators</edit-permission>
    <container id="ClassicBody" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">
      <access-permissions>Everyone</access-permissions>
      <container id="ClassicLeft" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
        <access-permissions>Everyone</access-permissions>
        <portlet-application>
          <portlet>
            <application-ref>presentation</application-ref>
            <portlet-ref>SingleContentViewer</portlet-ref>
            <preferences>
              <preference>
                <name>repository</name>
                <value>repository</value>
                <read-only>false</read-only>
              </preference>
              ...
              <preference>
                <name>ShowTitle</name>
                <value>false</value>
                <read-only>false</read-only>
              </preference>
            </preferences>
          </portlet>
          <title>Introduce</title>
          <access-permissions>Everyone</access-permissions>
          <show-info-bar>false</show-info-bar>
          <show-application-state>false</show-application-state>
          <show-application-mode>false</show-application-mode>
        </portlet-application>
      </container>
    </container>
  </page>
{code}

{note}
See Chapter 6 to learn more about the portlet configuration within the pages.xml file.
{note}

*Navigation:*

The *navigation.xml* is used to associate the links in your navigation with your portal pages. The navigation is a tree structure of "navigation nodes". Each navigation node points to one page (called the page node). The tree structure corresponds to a hierarchy of menus and sub-menus of a site.

If the pattern #{} is used, the link label will be loaded from the portal resource bundle. To learn more, refer to [Internationalization Configuration|http://docs.exoplatform.org/PLF30/refguide/html/bk02ch03.html#sect-Reference_Guide-Internationalization_Configuration].

{code:xml}
<?xml version="1.0" encoding="UTF-8"?>
<node-navigation>
<owner-type>portal</owner-type>
<owner-id>classic</owner-id>
<priority>1</priority>
<page-nodes>
<node>
<uri>home</uri>
<name>home</name>
<label>#{portal.classic.home}</label>
<page-reference>portal::classic::homepage</page-reference>
</node>
<node>
<uri>webexplorer</uri>
<name>webexplorer</name>
<label>#{portal.classic.webexplorer}</label>
<page-reference>portal::classic::webexplorer</page-reference>
</node>
</page-nodes>
</node-navigation>
{code}


This navigation tree is shown and reused in different portlets, such as sitemap, navigation or breadcrumbs. The breadcrumbs portlet renders the position of the current navigation node.

{note}
For the top nodes, the URI and the navigation node name must have the same value. For other nodes, the URI is composed like <uri>contentmanagement/fileexplorer</uri> where 'contentmanagement' is the name of the parent node and 'fileexplorer' is the name of node (<name>fileexplorer</name>).
{note}

h2. Visibility of pages {anchor:id=DEV.CreateYourOwnPortal.VisibilityPages}

You can easily restrict the visibility of selected pages and navigation nodes to certain groups and users. You just need to create {{pages.xml}} and {{navigation.xml}} files in folders named after the group and user to which you want to give permission:

*sample-ext/portal/group/group-name/your files*

*sample-ext/portal/user/username/your files*



h1. Add/remove languages {anchor:id=DEV.CreateYourOwnPortal.AddOrRemoveLanguages}

All languages are put in the _myextension.war/WEB-INF/conf/common/locales-config.xml_ directory. Each language consists of information related to key, output-encoding, input-encoding, description and orientation. Different languages will be defined in corresponding _resource bundle_ files with keys specified in the _locale-config.xml_ file.

All languages defined in the _locale-config.xml_ file are listed in *Interface Language Settings*. 

h2. Add a new language {anchor:id=DEV.CreateYourOwnPortal.AddNewLanguages}

To add a new language, you need to add the corresponding language node in the _locale-config.xml_ file. Next, you must create a new _resource bundle_ file containing the suffix name as key of the added node.

For example, to add Italian, do as follows:

*Step 1:* Add the following node to the _locale-config.xml_ file. 

{code:xml}
<locale-config>
    <locale>it</locale>
    <output-encoding>UTF-8</output-encoding>
    <input-encoding>UTF-8</input-encoding>
    <description>Default configuration for Italian locale</description>
</locale-config>
{code}

*Step 2:* Create a new _resource bundle_ as *_{{{webui_it.properties}}}_* in the _myextension.war/WEB-INF/classes/locale/portal_ folder. 

{note}
This step is necessary because the Resource Bundle Service of the portal will find keys and values in the _resource bundle_ of each corresponding language. 
{note}

*Step 3:* Restart the server.

To check if the added language takes effect, simply click the *Change Language* button on the top right corner of the portal. In the *Interface Language Setting* window, you will see Italian as shown:

!example_addItalian.png!




*Illustration 1: Italian display on Interface Language Setting*

h2. Remove languages {anchor:id=DEV.CreateYourOwnPortal.RemoveLanguages}

To remove an existing language, you need to delete the relevant language node in the _locale-config.xml_ file and all files containing the suffix name as the key of language.

For example, to remove French, do as follows:

*Step 1:* Find and remove the following node from the _locale-config.xml_ file.

{code:xml}
<locale-config>
    <locale>fr</locale>
    <output-encoding>UTF-8</output-encoding>
    <input-encoding>UTF-8</input-encoding>
    <description>Default configuration for france locale</description>
</locale-config>
{code}

*Step 2:* Continue removing all _resource bundle_ files containing the suffix name as *fr* in all folders.

{note}
It is recommended to do this step to delete unnecessary data in the application.
{note}
 
*Step 3:* Restart the server.

To check if the French removal takes effect, simply click the *Change Language* button on the top right corner of the portal. In the Interface Language Setting window, French which is shown in the *Illustration 1* has not existed on the *Interface Language Setting* window. 

!example_removeFrench.png!



*Illustration 2: Interface Language Setting without French*

h1. Create custom look and feel {anchor:id=DEV.CreateYourOwnPortal.CreateCustomLookAndFeel}
{include:document="customize/How_to_create_custom_look_and_feel.wiki"}

h1. Add JavaScript to your portal {anchor:id=DEV.CreateYourOwnPortal.AddJavaScriptToYourPortal}

This can be done entirely within your extension by customizing the *gatein-resources.xml* configuration.

To add a JavaScript library, for example jQuery, do as follows:

*Step 1*: Create _war:/WEB-INF/gatein-resources.xml_ file.

*Step 2*: Add the following line to the _gatein-resources.xml_ file.
{code}
 <javascript>
  <param>
   <js-module>jQuery</js-module>
   <js-path>/javascript/jQuery.js</js-path>
   <js-priority>0</js-priority>
  </param>
 </javascript>
 {code}
Details:

_<js-module>_ is the namespace of your JavaScript.

_<js-path>_ is the path to your JavaScript file.

<js-priority> is an optional tag. This tag is used to indicate the loading order of JavaScript files across all the platform. Its value is integer type. If its value is not negative (>=0), the loading priority is sorted by the descending order. If its value is negative (<0), the loading priority of the JavaScript file depends on the loading order of the web app (the .war file) containing that JavaScript file.
