# Beyond the Website: Apps, Kiosks, Email and In-App

> Source: https://agilitycms.com/docs/developers/beyond-the-website

Agility content isn't tied to a website. Everything you store is available as JSON through Agility's APIs, so the same content can feed a mobile app, a kiosk or digital sign, an email, or messages inside a product. This page covers how to read content for each kind of channel, and how to model content so it works in all of them.

## How non-web channels read content

A website built with Agility usually uses pages, the sitemap and Components. Other channels usually skip those and read **content lists and items** directly. You have three ways to read them:

| | Content Fetch API (REST) | GraphQL API | Content Sync |
| --- | --- | --- | --- |
| What you get | One item, list, page or sitemap per request | Exactly the fields you select, several queries per request | Every item and page that changed since your last sync, copied into your own store |
| Where the channel reads from | Agility, on each request | Agility, on each request | Your own store (files, database, cache) |
| Good for | Apps and services that fetch on demand | Screens that need fields from several lists in one round trip | Offline devices, high read volume, feeding other systems |

All three read either **published** content (with a fetch key) or the **latest saved** content (with a preview key), so you can build a preview version of any channel. The details, and when to choose Sync, are in [Content Sync Explained](/docs/developers/content-sync-explained).

To react to changes instead of polling, use [Webhooks](/docs/developers/webhooks): Agility calls your endpoint when content is published or saved, and your service refreshes its cache, re-syncs, or rebuilds what it needs.

For a complete architecture that combines these patterns across a website, app, email and kiosks, see [Reference Architecture: Multi-Channel Delivery](/docs/developers/reference-architecture-multi-channel).

## Channel by channel

### Mobile and desktop apps

- **Read with the Fetch API or GraphQL** from your app or, more often, from your own backend, which can cache responses and keep API keys out of the app itself.
- **Use Content Sync for offline support.** Sync gives you a full local copy of the content and then only what changed. The [Content Sync API](/docs/developers/content-sync-api) lists offline mode and local caching among its use cases.
- **Request image sizes for the device.** Image fields return a CDN URL, and you can add query string parameters to resize or convert the image. See [Transforming Images Using Query Strings](/docs/editors/transforming-images-using-query-strings).

### Kiosks and digital signs

- **Sync to the device or to a local server**, so the screen keeps working when the network doesn't. Store the sync token, and resume from it next time instead of starting over.
- **Trigger updates with webhooks,** and run a scheduled sync as a safety net in case a delivery is missed.
- **Use release and pull dates** to schedule what appears and when it comes down. Because of caching, there can be a delay of up to 15 minutes before a scheduled item is released or pulled, so don't rely on it for to-the-minute timing. See [Schedule Content Changes](/docs/editors/schedule-content-changes).

### Email

- **Fetch content when you build or send the email,** for example a newsletter assembled from the latest articles.
- **Use plain fields where you can.** Email clients are strict about HTML. A Summary field in plain text, an image field and a URL field are easier to place in an email template than a rich text field written for the web.
- **Use absolute image URLs.** Image fields return full CDN URLs, which work in email as they are.

### In-app messages and product content

- **Model short, purposeful fields:** a message title, a body with a length limit, a call-to-action label and link, and an audience or placement choice.
- **Let structure or a selector decide where content appears.** Either keep each surface's content in its own list, or add a field editors use to choose destinations, and filter on it. [Publishing to Multiple Destinations](/docs/overview/publishing-to-multiple-destinations) compares these approaches.
- **Filter on the server.** Request only the items a surface needs (with `filter` and `take`), rather than downloading a whole list.

## Model content for every channel

Content that works everywhere follows a few rules:

1. **Separate content from layout.** Name models and fields for what the content is. Layout belongs to each channel's code. See [Structured Content Explained](/docs/developers/structured-content-explained).
2. **Prefer specific fields to rich text.** An HTML field comes back as one string of HTML that every channel has to render. Separate fields for headings, summaries, dates and links can be used anywhere.
3. **Write short versions on purpose.** If a channel needs a 60-character title, add a `ShortTitle` field with a maximum length, rather than truncating the web title in code.
4. **Keep image alt text in the asset label.** Image fields return the label with the URL, so every channel can use it as alt text.
5. **Use choice values your code can switch on.** A Drop-down List returns the selected choice's value, not its label, so channels can map it to their own presentation.
6. **Plan locales once.** Each channel requests a locale explicitly, and every channel can use the same locales. See [Choosing a Localization Strategy](/docs/developers/choosing-a-localization-strategy).

## A checklist for a new channel

- Which content lists does this channel need, and which fields from each?
- Does it need content when it's offline? If so, use Content Sync.
- How fast must changes appear? Choose webhooks, a cache lifetime, or both.
- Does it need preview? Point a preview build at the preview key.
- Where will the API key live?
- Does every list request pass `take`? The Fetch API returns 10 items by default and GraphQL lists 50; the maximum is 250.

## Related

- [Content Sync Explained](/docs/developers/content-sync-explained)
- [Content Fetch API](/docs/developers/content-fetch-api)
- [GraphQL API](/docs/developers/graphql-api)
- [Webhooks](/docs/developers/webhooks)
- [Publishing to Multiple Destinations](/docs/overview/publishing-to-multiple-destinations)
- [Building a Content Hub](/docs/overview/building-a-content-hub)
