The Fat-Free Framework pulls together template files to create the pages:
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.
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.
The head template sets up:
defer
The dns-prefetch contacts the Domain Name System to obtain the IP address to download the Google Analytics JavaScript file, if analytics is enabled. Doing a dns-prefetch does not make contact with the Google server, so there is no violation of the user’s privacy. The Google Analytics JavaScript file is only loaded if the user has accepted cookies.
For the home page, the appropriate hero image is loaded using preload with imagesrcset, imagesizes, and media attributes.
The notifications template has a notice for Internet Explorer, the EU cookie/privacy notice, and the skip-link:
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.
The script template loads any additional JavaScript files that are not used on every page, such as the code highlighter.
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.)