Skip to main content

Putting the pages together

The Fat-Free Framework pulls together template files to create the pages:

  • layout.html – primary template that pulls in the other templates:
    • head.html – the HTML head section – same template for all pages
    • notifications.html – conditional text for unsupported browser (i.e. Internet Explorer) & the EU cookie notice – same template for all pages
    • navigation.html – logo and navbar – same template for all pages
    • content.html – page content and layout is supplied in these files (each page has a unique content file with a unique file name)
    • footer.html – same template for all pages
    • scripts.html – same template for all pages
  • sitemap.xml

The head, notifications, navigation, and script sections are all generic and receive their information from the Fat-Free hive via the controllers (data is stored before calling layout.html). The footer content is supplied from the dict files (it’s the same content, just translated). The content sections are specific to each page.

layout template

The layout template sets up the html page and calls the other templates:

<!DOCTYPE html>
<html lang="{{ @langCode }}" id="top" class="h-100" prefix="og: http://ogp.me/ns#"
itemscope itemtype="http://schema.org/WebPage">

<include href="head.html" />
<body id="page-top" class="d-flex flex-column h-100"
    {{ @isHomePage ? ' data-bs-spy="scroll" data-bs-target="#main-nav"
        data-bs-root-margin="0px 0px -53.28%" data-bs-threshold="0,0.5,1"' : '' }}
    {{ @isHomePage ? 'data-sc-page-type="home"' :
        (@isContactPage ? 'data-sc-page-type="contact"' :
        (@isTermsPage ? 'data-sc-page-type="terms"' :
        (@isErrorPage ? 'data-sc-page-type="error"' :
        'data-sc-page-type="detail"'))) }}>
<include href="notifications.html" />
<include href="navigation.html" />

<include href="{{ @pageContent }}" />
    
<include href="footer.html" />
<include href="script.html" />
</body>
</html>

Layout includes the setup for Bootstrap 5’s Scrollspy for the home page, and adds a data attribute to identify the page type (home, contact, terms, error, or detail). The page type is used for page-specific JavaScript functions.

notifications template

The notifications template has a notice for Internet Explorer, the EU cookie/privacy notice, and the skip-link:

  • IE: Displays a notice that the site does not support Internet Explorer although the content is visible.
  • EU cookie/privacy: Notice to comply with the European requirement to let users know that the site uses cookies. The notice includes a way to opt-out of Google Analytics and a link to the Terms of Use/Privacy page.
  • Skip-link: Link for users that are navigating with the tab key to skip over the navigation links and go directly to the content (for accessibility).

content templates

For most sites, data is in a database. For a website with five pages in three languages that won’t change much, a database seems like overkill. Using files is a simpler solution, with the primary place for information being a unique content template for each page.

script template

The script template loads any additional JavaScript files that are not used on every page, such as the code highlighter.

sitemap template

The sitemap is based on the route aliases. To not include pages in the sitemap (e.g. the contact pages), I add an x to the end of the route name (e.g. en_contactx) and filter out those routes from Fat-Free’s ALIASES variable before passing the route names and paths to the sitemap template.

The sitemap template loops through each route name, using an anonymous function connected to a framework variable to get the date the content template for that route was last modified.

The anonymous function to get the file date:

$f3->set('fdate',
    function($fileName) {
        if (file_exists('app/ui/'.$fileName.'.html')) {
            return date ('Y-m-d', filemtime('app/ui/'.$fileName.'.html'));
            } else {
                return 'Error';
            }
    }
);

Calling the function from the sitemap template:

<lastmod>{{ @fdate(@route_name) }}</lastmod>

For each route, the template loops through the array of languages from config.ini and generates a list of all of the alternate languages for that route (including the route itself per Google’s information on sitemaps).

The sitemap control function is in the UtilitiesController rather than the CommonPageController as the sitemap function calls its own instance for the Fat-Free Framework render function.

Note: Google (and other search engines) will be able to locate the pages I’m leaving off of the sitemap as there will be links to those pages in the navigation menu and the footer, but as those pages all have the tag <meta name="robots" content="noindex,nofollow">, Google will not index those pages. (Google is polite about complying with the robots meta tag, but not all search engines may be as nice.)