AEM Edge Delivery Services

Holland America Line — Getting Started

A developer & author guide for the Holland America Line website built on Adobe Experience Manager Edge Delivery Services. Learn what the project is, where the code and content live, and how to get running locally.

The initiative

This project delivers the Holland America Line web experience on Adobe Experience Manager Edge Delivery Services (EDS). It is built from the AEM boilerplate and follows Adobe's standards for fast, easy-to-author, and maintainable web experiences.

Content is authored in Document Authoring (DA) and served through the EDS pipeline. The codebase carries the Holland America brand system — navy, orange, and the Quasimoda / Minion display typefaces — applied through global styles and a library of reusable blocks. Adobe Edge Functions have been set up as a baseline for request-time customization at the CDN edge.

GOALFast by default

Vanilla JS, modern CSS, no build step. Three-phase (eager / lazy / delayed) page loading targets a 100 Lighthouse score.

CONTENTAuthor in DA

Authors edit pages in Document Authoring; blocks decorate the content authors produce — no code deploy required to publish.

BRANDHolland America look

Brand tokens (navy #022658, orange #e46c24, Quasimoda + Minion) drive global styles, the header, hero, and cards.

AttributeValue
GitHub orgAdobeDevXSC
Repositoryhal
Primary branchmain
Content systemDocument Authoring (DA) via da.live
Content mountcontent.da.live/AdobeDevXSC/hal/
Base boilerplateadobe/aem-boilerplate
ExtrasAdobe Edge Functions baseline

Key URLs

Every place you need to reach the code, the content, and the rendered site.

The URL pattern for any branch is {branch}--hal--AdobeDevXSC.aem.page (preview) or .aem.live (published). Swap main for your feature branch to preview it.

Find the GitHub repository

All of the site's code lives in one repository under the AdobeDevXSC GitHub organization.

Go straight to the repo

Open github.com/AdobeDevXSC/hal. If you have access it opens directly; otherwise request access to the AdobeDevXSC org.

Or discover it from the org

Visit github.com/AdobeDevXSC, open the Repositories tab, and search for hal.

Confirm it from a local clone

If you already have the code, run git remote -v (or gh repo view --json nameWithOwner) — it reports AdobeDevXSC/hal.

Clone it
git clone https://github.com/AdobeDevXSC/hal.git cd hal
The GitHub org (AdobeDevXSC) and repo name (hal) are the two values you plug into every preview and live URL.

Find the DA content folder

Page content is authored in Document Authoring (DA), not in the repo. The repo's fstab.yaml tells you exactly which DA folder feeds this site.

Read the mount point in fstab.yaml

At the repo root, fstab.yaml declares where content comes from:

mountpoints: /: url: https://content.da.live/AdobeDevXSC/hal/ type: markup

The path after content.da.live/ is the DA org and folder: AdobeDevXSC / hal.

Open it in the DA editor

Translate that mount into the DA app URL by swapping content.da.live/ for da.live/#/:

https://da.live/#/AdobeDevXSC/hal

Open da.live/#/AdobeDevXSC/hal to browse and edit pages, nav, footer, and metadata.

Verify the content is being served

Any page you preview at main--hal--AdobeDevXSC.aem.page is pulled from that DA folder. Inspect the raw content of a page with:

curl https://main--hal--AdobeDevXSC.aem.page/index.plain.html
Rule of thumb: the DA folder path always mirrors {org}/{repo}. Here that is AdobeDevXSC/hal — the same org and name as GitHub.

Architecture

Content authored in DA and code from GitHub are combined by the EDS pipeline and served through preview and live CDN environments.

DA content
AdobeDevXSC/hal
+
GitHub code
AdobeDevXSC/hal
EDS pipeline
+ Adobe Edge Functions
*.aem.page (preview)
|
*.aem.live (published)

Repository structure

# Key directories /blocks # reusable content blocks (blockname.js + blockname.css) /scripts # aem.js · scripts.js · delayed.js /styles # styles.css · lazy-styles.css · fonts.css (HAL brand tokens) /fonts # web fonts (Quasimoda, Minion display) /icons # SVG icons /config # cdn.yaml · edgeFunctions.yaml /aem-edge-functions # Adobe Edge Functions baseline fstab.yaml # DA content mount → content.da.live/AdobeDevXSC/hal/ head.html # global <head> content

Local development

The AEM CLI proxies your local code against previewed DA content. You edit code locally and see it against real content at localhost:3000.

# 1. Install dependencies npm install # 2. Install the AEM CLI (once, globally) npm install -g @adobe/aem-cli # 3. Start the local dev server at http://localhost:3000 aem up # Lint before committing npm run lint
Never modify scripts/aem.js — it is the core EDS library. Add site logic in scripts.js, block files, or global styles instead.

Blocks reference

Blocks are the reusable building blocks that add styling and behavior to authored content. Each lives in /blocks/{name}/ as a {name}.js + {name}.css pair. The project ships the standard boilerplate blocks plus a set of HAL-custom cruise blocks:

HAL cruise blocks

HALcruise-ships

Responsive fleet grid mirroring hollandamerica.com/cruise-ships — ship image, name, class, and detail link. Fetches from a configurable feed endpoint (defaults to a bundled sample).

HALfind-a-cruise

Cruise finder with destination / ship / port / duration filters, result cards, and load-more paging. Backed by a configurable endpoint (bundled sample of the Fusion search response).

HALhero-search

Home hero with a cruise-search widget; the Search button routes to the find-a-cruise page.

Standard blocks

BLOCKheader

Site navigation, rebuilt to match the Holland America Line brand.

BLOCKfooter

Global footer authored from a DA fragment.

BLOCKhero

Variant-driven: default image hero, plus a video variant where the image is the LCP poster and a muted autoplay video is layered on top (LCP-gated, reduced-motion aware).

BLOCKcards

Responsive card grid using the brand palette.

BLOCKcarousel

Rotating slides for featured content.

BLOCKcolumns

Multi-column layout for mixed content.

BLOCKaccordion

Expandable/collapsible content sections.

BLOCKtabs

Tabbed content panels.

BLOCKtable

Structured tabular content.

BLOCKquote

Pull quotes and testimonials.

BLOCKembed

Third-party embeds (video, social, etc.).

BLOCKvideo

Inline and modal video playback.

BLOCKmodal

Overlay dialogs triggered from content.

BLOCKform

Author-configurable forms, including a search variant used for the cruise search bar.

BLOCKsearch

On-site search experience.

BLOCKfragment

Reuse content authored elsewhere in DA.

Deep dive: Cruise Ships Page — How It's Built & Connected walks through how the cruise-ships block wires DA authoring, the ship feed, and the search API together on EDS.
Coding standards, block conventions, and the publishing workflow live in AGENTS.md at the repository root.

Page themes

Beyond global brand styles, individual pages can opt into a page-level theme via the page metadata theme field. The theme value becomes a class on <body>, which CSS targets.

THEMEmap

Paints an authored map image as a full-page navy wallpaper (#022658) that scrolls with the content; text, headings, and plain links lift to white for contrast. Defined in styles/lazy-styles.css as it's decorative, not LCP-critical.

Set theme to map in a page's metadata to apply body.map. Add new themes by defining a matching body.{theme} rule.

Translation & localization

Document Authoring ships with a built-in Translate app for producing localized versions of pages. Behavior is driven by a translate.json config — a multi-sheet workbook in the site's hidden .da configuration folder. DA seeds a sensible default translate.json; copy it into this site and adjust the languages and rules for HAL.

References: Set up translation (guide) and the default translate.json (config reference). Setup requires DA administrator access.

Set it up

Open the hidden config folder

Append /.da to the site path in DA to reach the configuration folder:

https://da.live/#/AdobeDevXSC/hal/.da
Add the translate.json config

Create a translate.json multi-sheet workbook seeded from the DA default. It carries five sheets: config, languages, custom-doc-rules, dnt-content-rules, and dnt-sheet-rules (documented below).

Tune the sheets for HAL

Edit the config conflict behaviors, prune the languages list to the locales HAL ships, and add any brand terms / URL patterns to the do-not-translate rules.

Publish, then create a project

Publish the config, then open the Translate app and create a new project — your settings appear in the project's confirmation options.

The default translate.json

The reference config is a :type: multi-sheet workbook. Each sheet below maps directly to the default DA ships.

config — service & conflict behavior

keydefault valueWhat it controls
sync.conflict.behavioroverwrite, mergeOld content when it is pulled into the "send for translation" folder.
translate.conflict.behavioroverwrite, mergeOld content when new content returns from translation.
rollout.conflict.behavioroverwrite, mergeOld content when new content is rolled out to the locale.
copy.conflict.behavioroverwrite, mergeWhen source content is copied into a region.
translation.service.nameGoogleThe translation service.
translation.service.all.envprodOrder of service endpoints; the first is the default.
translation.service.prod.linkcloud.google.com/translate/docs/overviewService documentation link.
translation.service.prod.originhttps://translate.da.live/googleService endpoint origin.
The *.conflict.behavior values list the choices; pick merge when localized pages carry market-specific content you don't want re-translation to clobber, and overwrite for fully automated, no-touch translation.

languages — locales & path convention

Each language maps to a URL location (the locale folder). The default ships seven; keep only what HAL needs.

namecodelocationtranslate typeactions
Englishen/enMachine TranslationSkip, Translate
Germande/deMachine TranslationSkip, Translate
Frenchfr/frMachine TranslationSkip, Translate
Spanishes/esMachine TranslationSkip, Translate
Chinesezh/zhMachine TranslationSkip, Translate
Japaneseja/jaMachine TranslationSkip, Translate
Hindihi/hiMachine TranslationSkip, Translate

rules — what not to translate

Three rule sheets keep structural and brand content intact:

sheetentryeffect
custom-doc-rulesmetadataTranslate column 2 only when column 1 is title or description.
custom-doc-rulessection-metadataDo not translate.
dnt-content-rules"do not translate me"Literal content strings left untranslated.
dnt-sheet-rulesbeginsWith(http:// || https://)Action dnt — leave URLs untouched in sheets.
Add HAL-specific do-not-translate entries — brand names (e.g. "Holland America Line", ship names like "Koningsdam"), trademarked phrases, and campaign slugs — to dnt-content-rules so machine translation leaves them intact.

AI tooling

This project is built and maintained with Claude Code using two Adobe extensions: the Document Authoring MCP for content operations, and the Edge Delivery Services skill for development. Both target this project's org/site, AdobeDevXSC/hal.

MCPDocument Authoring MCP

An MCP server that reads and writes DA content programmatically over the DA Admin API (admin.da.live) — list, get, create, update, copy, move, delete sources, plus versions, fragment/media lookup, and media upload.

Endpoint: mcp.adobeaemcloud.com/adobe/mcp/da

SKILLEdge Delivery Services skill

A Claude Code plugin of EDS skills — content-driven development, block building & content modeling, page import/migration, block testing, and docs search — grounded in the aem.live documentation.

Document Authoring MCP — capabilities

The server runs at https://mcp.adobeaemcloud.com/adobe/mcp/da. Register it with your MCP client, for example:

# Claude Code claude mcp add --transport http da https://mcp.adobeaemcloud.com/adobe/mcp/da

Once connected, the MCP surfaces the DA Admin API as tools scoped to AdobeDevXSC/hal:

ToolWhat it does
da_list_sourcesList content sources (pages, sheets, media) under a path.
da_get_sourceRead the HTML/JSON of a specific source.
da_create_source · da_update_sourceCreate or update a page or sheet.
da_copy_content · da_move_contentCopy or move content between paths.
da_delete_sourceDelete a source.
da_get_versionsInspect version history for a source.
da_lookup_fragment · da_lookup_mediaResolve fragments and referenced media.
da_upload_mediaUpload an image or asset into the DA media library.

Edge Delivery Services skill — what it covers

The skill encodes the conventions in AGENTS.md and the practices below, so generated code follows EDS standards:

  • Content-driven development — decide the block's content model before writing code.
  • Building blocks & content modeling — block JS/CSS conventions, initial structure as the author contract.
  • Page import / migration — scrape a source page and map it onto existing blocks.
  • Testing blocks — lint, local preview, and performance validation before a PR.
  • Docs search — grounded lookups against the aem.live documentation.
For guidance on working effectively with these AI tools, see aem.live — AI coding agents.