Before JSF 2.0, JSP (JavaServer Pages) technology produced page views.

In 2.0, Facelets replaces JSP as the JSF view handler:

The capabilities of Facelets are demonstrated in the Planets Example available in the menu to the left.
Facelets tag categories: To use these tags you must add the following attribute to your html tag:
       xmlns:ui="http://java.sun.com/jsf/facelets"  

The planets example shows a common page layout approach: In addition, the page title varies:
masterLayout.xhtml is an ordinary XHTML file except for the ui:insert tags:
Use ui:composition as in login.xhtml below to make use of a template: Since ui:composition uses a master layout page that already has html, head, title, and body tags, Facelets removes all tags outside the ui:composition tag, explaining why the title is IGNORED.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">

   <head><title>IGNORED</title></head>
   <body>
      <ui:composition template="/templates/masterLayout.xhtml">

         <ui:define name="windowTitle">
            #{msgs.loginTitle}
         </ui:define>

         <ui:define name="heading">

            <ui:include src="/sections/login/header.xhtml"/>
         </ui:define>

         <ui:define name="sidebarLeft">

            <ui:include src="/sections/login/sidebarLeft.xhtml"/>
         </ui:define>

         <ui:define name="content">

            <h:form>
               <h:panelGrid columns="2">
                  #{msgs.namePrompt}
                  <h:inputText id="name" value="#{user.name}"/>

                  #{msgs.passwordPrompt}
                  <h:inputSecret id="password" value="#{user.password}"/>
               </h:panelGrid>

               <p>
                  <h:commandButton value="#{msgs.loginButtonText}"
                                   action="planetarium"/>
               </p>

            </h:form>
         </ui:define>
      </ui:composition>
   </body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <head><title>IGNORED</title></head>

  <body>
    <ui:composition>
      #{msgs.loginHeading}
    </ui:composition>
  </body>

</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets">
   <head><title>IGNORED</title></head>

   <body>
      <ui:composition template="/templates/masterLayout.xhtml">
         <ui:define name="windowTitle">

            #{msgs.planetariumTitle}
         </ui:define>

         <ui:define name="content">
            #{msgs.planetariumWelcome}
         </ui:define>

      </ui:composition>
   </body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:ui="http://java.sun.com/jsf/facelets">
   <head><title>IGNORED</title></head>

   <body>
      <ui:composition template="/templates/masterLayout.xhtml">
         <ui:define name="windowTitle">

            #{msgs.saturn}
         </ui:define>

         <ui:define name="content">
            Saturn has rings made of ice and dust.
         </ui:define>

      </ui:composition>
   </body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"

      xmlns:corejsf="http://corejsf.com/facelets">
  <head><title>IGNORED</title></head>  
  <body>        
    <ui:composition>    
      <h:form>

        <corejsf:planet name="mercury" 
                        image="#{resource['images:Mercury.gif']}"
                        label="#{msgs.mercury}"/>

        <corejsf:planet name="venus"
                        image="#{resource['images:Venus.gif']}"
                        label="#{msgs.venus}"/>

        <corejsf:planet name="earth"
                        image="#{resource['images:Earth.gif']}"
                        label="#{msgs.earth}"/>

        <corejsf:planet name="mars"
                        image="#{resource['images:Mars.gif']}"

                        label="#{msgs.mars}"/>
        <corejsf:planet name="jupiter"
                        image="#{resource['images:Jupiter.gif']}"

                        label="#{msgs.jupiter}"/>
        <corejsf:planet name="saturn" 
                        image="#{resource['images:Saturn.gif']}"

                        label="#{msgs.saturn}"/>
        <corejsf:planet name="uranus" 
                        image="#{resource['images:Uranus.gif']}"

                        label="#{msgs.uranus}"/>
        <corejsf:planet name="neptune" 
                        image="#{resource['images:Neptune.gif']}"

                        label="#{msgs.neptune}"/>
      </h:form>     
    </ui:composition>
  </body>

</html>
The Facelets composition mechanism is used to insert content specific to each planet:
tags/corejsf/planet.xhtml Planetarium.java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">

   <h:head><title>IGNORED</title></h:head>
   <h:body>
      <ui:composition>
         <div class='#{name == planetarium.selectedPlanet ? 
                     "planetImageSelected" : "planetImage"}'>

            <h:commandLink action="#{planetarium.changePlanet(name)}">
               <h:graphicImage value="#{image}"/>
            </h:commandLink>

            <div class="planet-label">
               #{label}
            </div>
         </div>
      </ui:composition>

   </h:body>
</html>
package com.corejsf;

import java.io.Serializable;
import javax.inject.Named;
   // or import javax.faces.bean.ManagedBean;
import javax.enterprise.context.RequestScoped;
   // or import javax.faces.bean.RequestScoped;

@Named // or @ManagedBean
@RequestScoped
public class Planetarium implements Serializable {
  private String selectedPlanet;

  public String getSelectedPlanet() { return selectedPlanet; }

  public String changePlanet(String newValue) {
     selectedPlanet = newValue;
     return selectedPlanet;
  }
}
To use a custom tag, it must be declared in a tag library file containing: Finally, the web.xml configuration file must know about the tag library location by including a context-param element.
corejsf.taglib.xml web.xml
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
    "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
    "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib>
  <namespace>http://corejsf.com/facelets</namespace>
  <tag>
    <tag-name>planet</tag-name>
    <source>tags/corejsf/planet.xhtml</source>

  </tag>
</facelet-taglib>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  version="2.5" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
                      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>
  
  <context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/WEB-INF/corejsf.taglib.xml</param-value>
  </context-param>
  
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>faces/login.xhtml</welcome-file>
  </welcome-file-list>
  
</web-app>
Two approaches to templating: The markup on the left displays a login form which is the child of a ui:decorate tag with a template attribute.

The template on the right surrounds the login form with a default heading and sidebarLeft, making the login form the page's content

Facelets simply considers ui:decorate and ui:composition as complementary constructs: ui:composition trims all surrounding contents, whereas ui:decorator does not.
Decorated Markup masterDecorator.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <head><title>#{msgs.loginTitle}</title></head>
  <body>
    <ui:decorate template="/templates/masterDecorator.xhtml">
      <!-- Contents to be decorated -->
      <h:form>
	<h:panelGrid columns="2">
	  #{msgs.namePrompt}
	  <h:inputText id="name" value="#{user.name}"/>
	  #{msgs.passwordPrompt}
	  <h:inputSecret id="password" value="#{user.password}"/>
	</h:panelGrid>
	<p>
	  <h:commandButton value="#{msgs.loginButtonText}"
			   action="planetarium"/>
	</p>
      </h:form>
    </ui:decorate>
  </body>
</html>
Optional XHTML header
<ui:composition>
  <h:outputStylesheet library="css" name="styles.css" target="body"/>
  <div id="heading">
    <ui:insert name="heading">Default header</ui:insert>
  </div>
  <div id="sidebarLeft">
    <ui:insert name="sidebarLeft">Default sidebar</ui:insert>
  </div>
  <div id="content">
    <ui:insert/>
  </div>
</ui:composition>
Optional XHTML footer
When you place the ui:debug tag in a Facelets page, a debug component is added to the component tree for that page.

If the user types a hotkey, which by default is CTRL+SHIFT+d, JSF opens a window and displays the state of the component tree and the application’s scoped variables: