The shell component

Personalize the "shell" surrounding your page contents. Used to set properties for the entire page.

Top-level parameters

name required type description
css

URL

The URL of a CSS file to load and apply to the page.
description

TEXT

A description of the page. It can be displayed by search engines when your page appears in their results.
favicon

URL

fixed_top_menu

BOOLEAN

Fixes the top bar with menu at the top (the top bar remains visible when scrolling long pages).
font

TEXT

Specifies the font to be used for displaying text, which can be a valid font name from fonts.google.com or the path to a local WOFF2 font file starting with a slash (e.g., "/fonts/MyLocalFont.woff2").
font_size

INTEGER

Font size on the page, in pixels. Set to 18 by default.
footer

TEXT

Muted text to display in the footer of the page. This can be used to display a link to the terms and conditions of your application, for instance. By default, shows "Built with SQLPage". Supports links with markdown.
icon

ICON

Name of an icon (from tabler-icons.io) to display next to the title in the navigation bar.
image

URL

The URL of an image to display next to the page title.
javascript

URL

The URL of a Javascript file to load and execute on the page.
javascript_module

URL

The URL of a javascript module in the ESM format (see javascript.info/modules)
language

TEXT

The language of the page. This can be used by search engines and screen readers to determine in which language the page is written.
layout

TEXT

The general page layout. Can be "boxed" (the default), "horizontal" (for a full-width menu), "vertical"(vertical menu), "fluid" (removes side margins).
link

URL

The target of the link in the top navigation bar.
manifest

URL

menu_item

TEXT

Adds a menu item in the navigation bar at the top of the page. The menu item will have the specified name, and will link to as .sql file of the same name. A dropdown can be generated by passing a json object with a `title` and `submenu` properties.
navbar_title

TEXT

The title to display in the top navigation bar. Used to display a different title in the top menu than the one that appears in the tab of the browser.
norobot

BOOLEAN

Forbids robots to save this page in their database and follow the links on this page. This will prevent this page to appear in Google search results for any query, for instance.
preview_image

URL

The URL of an image to display as a link preview when the page is shared on social media
refresh

INTEGER

Number of seconds after which the page should refresh. This can be useful to display dynamic content that updates automatically.
rss

URL

The URL of an RSS feed to display in the top navigation bar. You can use the rss component to generate the field.
search_target

TEXT

When this is set, a search field will appear in the top navigation bar, and load the specified sql file with an URL parameter named "search" when the user searches something.
search_value

TEXT

This value will be placed in the search field when "search_target" is set. Using the "$search" query parameter value will mirror the value that the user has searched for.
sidebar

BOOLEAN

Whether the menu defined by menu_item should be displayed on the left side of the page instead of the top. Introduced in v0.27.
sidebar_theme

BOOLEAN

Used with sidebar property, It can be set to "dark" to exclusively set the sidebar into dark theme.
social_image

URL

The URL of the preview image that will appear in the Open Graph metadata when the page is shared on social media.
target

TEXT

"_blank" to open the link in a new tab, "_self" to open it in the same tab, "_parent" to open it in the parent frame, or "_top" to open it in the full body of the window
theme

TEXT

Set to "dark" to use a dark theme.
title

TEXT

The title of your page. Will be shown in a top bar above the page contents. Also usually displayed by web browsers as the name of the web page's tab.
No data

Example 1

This example contains the values used for the shell of the page you are currently viewing.

The menu_item property is used both in its simple string form, to generate a link named "functions" that points to "functions.sql", and in its object form, to generate a dropdown menu named "Community" with links to the blog, the github repository, and the issues page.

The object form can be used directly only on database engines that have a native JSON type. On other engines (such as SQLite), you can use the dynamic component to generate the same result.

You see the page layouts demo for a live example of the different layouts.

select 
    'shell'                     as component,
    'SQLPage: SQL to web pages' as title,
    'database'                  as icon,
    '/'                         as link,
    JSON('{"title":"About","submenu":[{"link":"/safety.sql","title":"Security","icon":"lock"},{"link":"/performance.sql","title":"Performance","icon":"bolt"},{"link":"//github.com/sqlpage/SQLPage/blob/main/LICENSE.txt","title":"License","icon":"file-text"},{"link":"/blog.sql","title":"Articles","icon":"book"}]}') as menu_item,
    JSON('{"title":"Examples","submenu":[{"link":"/examples/tabs/","title":"Tabs","icon":"layout-navbar"},{"link":"/examples/layouts.sql","title":"Layouts","icon":"layout"},{"link":"/examples/multistep-form","title":"Forms","icon":"edit"},{"link":"/examples/handle_picture_upload.sql","title":"File uploads","icon":"upload"},{"link":"/examples/authentication/","title":"Password protection","icon":"password-user"},{"link":"//github.com/sqlpage/SQLPage/blob/main/examples/","title":"All examples & demos","icon":"code"}]}') as menu_item,
    JSON('{"title":"Community","submenu":[{"link":"/blog.sql","title":"Blog","icon":"book"},{"link":"//github.com/sqlpage/SQLPage/issues","title":"Report a bug","icon":"bug"},{"link":"//github.com/sqlpage/SQLPage/discussions","title":"Discussions","icon":"message"},{"link":"//github.com/sqlpage/SQLPage","title":"Github","icon":"brand-github"}]}') as menu_item,
    JSON('{"title":"Documentation","submenu":[{"link":"/your-first-sql-website","title":"Getting started","icon":"book"},{"link":"/components.sql","title":"All Components","icon":"list-details"},{"link":"/functions.sql","title":"SQLPage Functions","icon":"math-function"},{"link":"/custom_components.sql","title":"Custom Components","icon":"puzzle"},{"link":"//github.com/sqlpage/SQLPage/blob/main/configuration.md#configuring-sqlpage","title":"Configuration","icon":"settings"}]}') as menu_item,
    'boxed'                     as layout,
    'en-US'                     as language,
    'Go from SQL queries to web applications in an instant.' as description,
    'https://sql-page.com/sqlpage_social_preview.webp' as preview_image,
    'Poppins'                   as font,
    'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js' as javascript,
    'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/languages/sql.min.js' as javascript,
    'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/languages/handlebars.min.js' as javascript,
    'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/languages/json.min.js' as javascript,
    '/highlightjs-launch.js'    as javascript,
    '/highlightjs-tabler-theme.css' as css,
    'Official [SQLPage](https://sql-page.com) documentation' as footer;

Example 2

A page without a shell

SQLPage provides the shell-empty component to create a page without a shell. In this case, the html and body tags are not generated, and the components are rendered directly in the page without any styling, navigation bar, footer, or dynamic content. This is useful when you want to generate a snippet of HTML that can be dynamically included in a larger page.

Any component whose name starts with shell will be considered as a shell component, so you can also create your own shell component.

If you generate your own HTML from a SQL query, you can also use the shell-empty component to include it in a page. Make sure you know what you are doing, and be careful to escape the HTML properly, as you are stepping out of the safe SQLPage framework and into the wild world of HTML.

select 
    'shell-empty' as component,
    '<!DOCTYPE html>
<html>
<head>
  <title>My page</title>
</head>
<body>
  <h1>My page</h1>
</body>
</html>' as html;

Examples

Sharing the shell between multiple pages

It is common to want to share the same shell between multiple pages.

Static menu

If your menu is completely static (it does not depend on the database content), you can use the dynamic component together with the sqlpage.read_file_as_text function to load the shell from a json file.

SELECT 'dynamic' AS component, sqlpage.read_file_as_text('shell.json') AS properties;

and in shell.json:

{
    "component": "shell",
    "title": "SQL + JSON = <3",
    "link": "/",
    "menu_item": [
        {"link": "index.sql", "title": "Home"},
        {"title": "Community", "submenu": [
            {"link": "/blog.sql", "title": "Blog"},
            {"link": "//github.com/sqlpage/SQLPage", "title": "Github"}
        ]}
    ]
}

Dynamic menu

If your menu depends on the database content, or on special sqlpage functions, you can use the dynamic component, but this time with the sqlpage.run_sql function to generate the menu from the database.

SELECT 'dynamic' AS component, sqlpage.run_sql('shell.sql') AS properties;

and in shell.sql:

SELECT 'shell' AS component, 'run_sql is cool' as title,
    json_group_array(json_object(
        'link', link,
        'title', title
    )) as menu_item
FROM my_menu_items

(check your database documentation for the exact syntax of the json_group_array function).

Another case when dynamic menus are useful is when you want to show some menu items only in certain conditions.

For instance, you could show an "Admin panel" menu item only to users with the "admin" role, a "Profile" menu item only to authenticated users, and a "Login" menu item only to unauthenticated users:

set role = (
    SELECT role FROM users
    INNER JOIN sessions ON users.id = sessions.user_id
    WHERE sessions.session_id = sqlpage.cookie('session_id')
); -- Read more about how to handle user sessions in the "authentication" component documentation

SELECT 
    'shell' AS component,
    'My authenticated website' AS title,

    -- Add an admin panel link if the user is an admin
    CASE WHEN $role = 'admin' THEN '{"link": "admin.sql", "title": "Admin panel"}' END AS menu_item,

    -- Add a profile page if the user is authenticated
    CASE WHEN $role IS NOT NULL THEN '{"link": "profile.sql", "title": "My profile"}' END AS menu_item,

    -- Add a login link if the user is not authenticated
    CASE WHEN $role IS NULL THEN 'login' END AS menu_item
;

More about how to handle user sessions in the authentication component documentation.

Menu with icons

The "icon" attribute may be specified for items in the top menu and submenus to display an icon before the title (or instead). Similarly, the "image" attribute defines a file-based icon. For image-based icons, the "size" attribute may be specified at the top level of menu_item only to reduce the size of image-based icons. The following snippet provides an example, which is also available here.

SELECT 
    'shell'             AS component,
    'SQLPage'           AS title,
    'database'          AS icon,
    '/'                 AS link,
    TRUE                AS fixed_top_menu,
    '{"title":"About","icon": "settings","submenu":[{"link":"/safety.sql","title":"Security","icon": "logout"},{"link":"/performance.sql","title":"Performance"}]}' AS menu_item,
    '{"title":"Examples","image": "https://upload.wikimedia.org/wikipedia/en/6/6b/Terrestrial_globe.svg","submenu":[{"link":"/examples/tabs/","title":"Tabs","image": "https://upload.wikimedia.org/wikipedia/en/6/6b/Terrestrial_globe.svg"},{"link":"/examples/layouts.sql","title":"Layouts"}]}' AS menu_item,
    '{"title":"Examples","size":"sm","image": "https://upload.wikimedia.org/wikipedia/en/6/6b/Terrestrial_globe.svg","submenu":[{"link":"/examples/tabs/","title":"Tabs","image": "https://upload.wikimedia.org/wikipedia/en/6/6b/Terrestrial_globe.svg"},{"link":"/examples/layouts.sql","title":"Layouts"}]}' AS menu_item,
    'Official [SQLPage](https://sql-page.com) documentation' as footer;

See also: other components