Relatude Help

The options

Everything else is an option of the URL manager. Set the options in the database's settings, either in the admin UI or in relatude.db.json under LocalSettings.UrlOptions:

"UrlOptions": {
  "FallbackRootId": "7e1a0001-5eed-4c0d-9a11-000000000001",
  "Parents": [ { "ParentRelationName": "RTree" } ]
}

Or set them in code. A URL manager made by CreateUrlManager replaces the options in the settings file entirely:

using Relatude.DB.Web;

builder.AddRelatudeDB(o => o.CreateUrlManager = _ => new DefaultUrlManager(new DefaultUrlManagerOptions {
    FallbackRootId = HomeId,
    Parents = [new UrlParentRelation { ParentRelationName = "RTree" }],
}));

A home page at /

FallbackRootId makes a page the root of the site. The root answers /, so it is the home page. The root is chosen by id, so create the home page with a fixed one:

public static readonly Guid HomeId = new("7e1a0001-5eed-4c0d-9a11-000000000001");

new DefaultUrlManagerOptions { FallbackRootId = HomeId }
db.CreateAndInsert<IHomePage>(p => p.Name = "Home", HomeId);
/              the home page
/hello-world   the article, as before

Page trees: /products/bikes/trail-one

Parents names the relation that leads from a page to its parent. For pages that is RTree, the page tree every IPage has (chapter 3). A page's URL is then the addresses of its ancestors followed by its own, below the root:

new DefaultUrlManagerOptions {
    FallbackRootId = HomeId,
    Parents = [new UrlParentRelation { ParentRelationName = nameof(RTree) }],   // IPage's Parent and Children
}
Home (the root)            /
├─ Products                /products
│  └─ Bikes                /products/bikes
│     └─ Trail One         /products/bikes/trail-one
└─ News                    /news
   └─ Bikes                /news/bikes
  • An address only has to be unique among its siblings. Both bikes pages above are fine.
  • The path is not stored. Moving a page, or renaming a section, changes every URL below it at once.
  • The root's own address is not part of the URLs: /products, not /home/products.
  • Several relations can lead to a parent, such as pages under pages and documents under pages. List them all in Parents, in priority order.

Add the relation before you set the child's address, so the store checks the address against the right siblings:

db.AddRelation<IPage>(products.Id, p => p.Children, bikes.Id);
db.UpdateAddress(bikes.Id, "bikes");

Several sites, one per domain

Domains gives each host a root. A host serves the pages below its root, and the root answers /:

new DefaultUrlManagerOptions {
    Parents = [new UrlParentRelation { ParentRelationName = nameof(RTree) }],
    Domains = [
        new UrlDomain { Host = "www.bikes.no", RootId = bikesHome },
        new UrlDomain { Host = "www.skis.no", RootId = skisHome },
    ],
    FallbackRootId = bikesHome,   // localhost, staging and any other host
}
https://www.bikes.no/products   the products page below bikesHome
https://www.skis.no/products    the products page below skisHome
http://localhost:5000/products  the fallback root's: bikesHome

Pages store nothing about their domain, so the same database runs locally unchanged. With domains, db.GetUrl(page, absolute: true) gives https://www.skis.no/products. Without them there is no host to add, and the URL stays relative.

A base path and trailing slashes

new DefaultUrlManagerOptions { PrimaryBaseAddress = "/site", IncludeTrailingSlash = true }
/site/products/bikes/    page URLs start with /site and end with a slash
/site/assets/…           file URLs start with /site too

BaseAddressPages and BaseAddressAssets add a prefix to page URLs only or file URLs only, after the primary base. A base with a scheme and host, such as https://cdn.example.com for files, makes those URLs absolute. Incoming URLs match either way.

URLs that survive a rename

UrlFormat can put the page's id in its URL. With EncodedGuidAndAddress the id finds the page, and the address is only there for people to read:

OnlyAddress (the default)    /products/bikes/trail-one
EncodedGuidAndAddress        /PSobnF9OcWCCk6S1xtfo-Q/products/bikes/trail-one

The second URL keeps working when the page is renamed or moved, and addresses never need a -2. The Relatude.DB manual lists all ten formats.

File URLs

Stored files have URLs of their own, made by db.GetUrl(file) and db.GetUrl(file, adjustment):

/assets/{token}/trail-one.jpg     the file as it was uploaded
/assets/{token}/trail-one.webp    a variant, such as a resized image

The token names the file and the variant; the file name at the end is only for downloads. The options below can move file URLs, for example to a CDN, make them readable, or sign them so that an edited URL stops working. See Asset URLs in the Relatude.DB manual, and chapter 7 for how files are served.

All the options

Option Default What it does
FallbackRootId the first domain's root the root for unknown hosts, answering /
Parents none: flat URLs the relations from a page to its parent, for tree URLs
Domains none a root for each host
OwnHosts none more hosts the site is served at, separated by commas, for links in rich text
UrlFormat OnlyAddress the address, the id, or both
PrimaryBaseAddress none a prefix for every URL
BaseAddressPages, BaseAddressAssets none a prefix for page URLs only, or file URLs only
IncludeTrailingSlash off /products/ rather than /products
Scheme https the scheme of absolute URLs
AssetUrlRoot, AssetUrlStyle, AssetUrlParamName /assets/, AssetRoot, asset where file URLs live
PropertyPathFormat, AssetUrlFormat Encrypted opaque or readable file URLs
AssetUrlSignatureKey none signs file URLs

URLs and the URL manager in the Relatude.DB manual covers each option, and how to write a URL manager of your own.