Adding Pages

How to add pages to your Jaspr content site.


This guide explains how to add pages to your Jaspr content site. You'll learn how to use the content directory structure that maps to URL routes and work with different file formats or remote content sources. We'll also cover advanced features like private files, in-memory pages and raw content output options.

Content Folder

A page is a single file that contains the content for a specific route in your site. By default, ContentApp loads pages from the content/ directory in your project. For example, you might have the following directory structure:

text
content/
 โ”œโ”€โ”€ index.md
 โ”œโ”€โ”€ about.md
 โ””โ”€โ”€ posts/
    โ”œโ”€โ”€ index.md
    โ”œโ”€โ”€ post1.md
    โ””โ”€โ”€ post2.md
lib/
 โ”œโ”€โ”€ ...
 โ””โ”€โ”€ main.server.dart

This would create the following routes:

  • / for content/index.md
  • /about for content/about.md
  • /posts for content/posts/index.md
  • /posts/post1 for content/posts/post1.md
  • /posts/post2 for content/posts/post2.md

Private Files

Files and folders starting with _ or . are considered private and will be ignored. This is useful for files that are not meant to be publicly accessible, such as configuration files or template partials.

Many templating languages, including mustache and liquid, support partial files that can be included in other files. These files are usually stored in a _partials directory. For example, you might have the following directory structure:

text
content/
 โ”œโ”€โ”€ index.md
 โ””โ”€โ”€ _partials/
    โ”œโ”€โ”€ header.md
    โ””โ”€โ”€ footer.md

This would allow you to include the header.md and footer.md files in your other markdown files using the templating syntax of your choice. For example, in mustache you would use:

markdown
{{> _partials/header }}

# My Page Title
This is the normal content of the page.

{{> _partials/footer }}

Read more about how to configure templating like this in the Templating guide.

File Formats

jaspr_content is not limited to only markdown files. Which formats are supported depends on the PageParsers you configured.

Add additional parsers to the ContentApp like this:

dart
ContentApp(
  parsers: [
    MarkdownParser(),
    HtmlParser(),
  ],
);

With this configuration, you can then mix markdown and HTML files in your content directory. For example:

text
content/
 โ”œโ”€โ”€ index.html
 โ”œโ”€โ”€ about.md
 โ””โ”€โ”€ posts/
    โ”œโ”€โ”€ index.md
    โ”œโ”€โ”€ post1.html
    โ””โ”€โ”€ post2.md

Remote Files

You can also load content from remote sources like GitHub or a CMS, instead of the filesystem. jaspr_content already comes with a GitHubLoader that can be used to load content from a GitHub repository. Or you can implement your own RouteLoader to load content from any source you want.

For example, to load content from a GitHub repository, you can do this:

dart
ContentApp.custom(
  loaders: [
    GitHubLoader(
      '<username>/<repo>',
      path: 'docs/',
      accessToken: '...'
    ),
  ],
  // ...
);

In-Memory Pages

You can also create pages in memory without loading them from anywhere. This is useful for testing or for creating pages by code:

dart
ContentApp.custom(
  loaders: [
    MemoryLoader(pages: [
      MemoryPage(
        path: 'special.md',
        content: '''
          This is a **special page** that is created in memory.
          It is not loaded from anywhere.
          It still follows the same rules as normal pages and is parsed and rendered like any other page.
        ''',
      ),
    ]),
  ],
  // ...
)

This will create a page at the /special route with the content provided in the MemoryPage. The content is parsed and rendered like any other page, so you can use all the features of jaspr_content like frontmatter, templating, and components.

Raw Content

Sometimes you might want to output content as is without rendering it to HTML. For example, you might want to add a robots.txt file or a llms.txt file to your site.

You can of course do this by adding it as static assets to the web/ directory. However, if you want to leverage the content pipeline for this, you can do so like this:

dart
ContentApp.custom(
  loaders: [
    FilesystemLoader(
      directory: 'content',
      keepSuffixPattern: RegExp(r'.*\.txt$'),
    ),
  ],
  configResolver: PageConfig.all(
    // ...
    rawOutputPattern: RegExp(r'.*\.txt$'),
  ),
);
  • The keepSuffixPattern will keep the .txt file suffix for matching pages. This is important since the file suffix is normally removed when creating the url for a page.
  • The rawOutputPattern will skip the HTML rendering for matching pages and output the raw content as is. The frontmatter parsing and templating will still be applied though.

Continue with the Writing Content guide to learn about writing rich and engaging content for your pages. You will explore markdown syntax, frontmatter, templating, and how to use custom components to enhance your content.