Java library for rendering Contentful Rich Text fields. It helps you easily render rich text stored in Contentful using Java, targeting both plain JVM applications (HTML output) and Android (Spannables or native Views).
What is Contentful?
Contentful provides content infrastructure for digital teams to power websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management and delivery APIs, and a customizable web app that enable developers and content creators to ship their products faster.
Table of contents
- Takes the rich text node tree produced by contentful.java (
CDARichDocumentand friends) and renders it into a representation that's easy to use in your own project. htmlmodule: converts rich text into an HTML string, suitable for any JVM application (web backends, CLI tools, etc).androidmodule: converts rich text into eitherCharSequence/Spannableoutput forTextView, or native AndroidViewhierarchies — your choice.- A shared
coremodule defines theProcessor/Renderer/RenderabilityCheckerpattern used by both thehtmlandandroidmodules, and is dependency-free of either. - Fully extensible: add a new
Rendererto aProcessorvia.addRenderer(…), or replace a default one via.overrideRenderer(…), without forking the library. Simplifierutilities to clean up a rich text graph before rendering — for example removing empty nodes or nodes nested beyond a given depth (RemoveToDeepNesting), useful for capping Android rendering time on deeply nested documents.- Ships as three independently versioned JitPack artifacts (
core,html,android) so you only pull in what you need.
| Requirement | Version |
|---|---|
| Java | 17 |
Android (for the android module) |
compileSdk 35, minSdk 23 |
This library depends on contentful.java for the CDARichDocument node model that it renders.
Artifacts are distributed via JitPack. Add the JitPack repository, then depend on the module(s) you need:
- Gradle
allprojects {
repositories {
// …
maven { url 'https://jitpack.io' }
}
}dependencies {
// …
// JVM / server (HTML output):
implementation 'com.contentful.java:java-sdk:10.6.1'
implementation 'com.github.contentful.rich-text-renderer-java:html:2.4.1'
}dependencies {
// Android: from 2.4.1 the android artifact brings core and java-sdk (without okhttp-jvm).
implementation 'com.github.contentful.rich-text-renderer-java:android:2.4.1'
// If you also declare java-sdk yourself, exclude okhttp-jvm. Otherwise the build fails with
// "Duplicate class okhttp3.…" against okhttp-android:
implementation('com.contentful.java:java-sdk:10.6.1') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp-jvm'
}
}2.4.1 notes for Android: the minimum SDK is 23 (it was 21 up to 2.3.x). Links in rich text are opened only for
http,https,mailto,telandsms; other schemes such asjavascript:orintent:cannot navigate. Don't use 2.4.0: it has an unprotected link path and a list-rendering crash, both fixed in 2.4.1. The default embedded-image provider returns a placeholder on the main thread. Render off the main thread for downloads (bounded by a 3-second timeout per image), or supply a customBitmapProviderthat uses cached images.
2.4.1 notes for the HTML module: attribute values are now HTML-escaped (for example
&in a link becomes&), and links with a disallowed scheme (javascript:,data:, …) are rendered as<a>without anhref. Relative links (/about,#top) are unchanged.
- Maven
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories><dependency>
<groupId>com.contentful.java</groupId>
<artifactId>java-sdk</artifactId>
<version>10.6.1</version>
</dependency>
<dependency>
<groupId>com.github.contentful.rich-text-renderer-java</groupId>
<artifactId>html</artifactId>
<version>2.4.1</version>
</dependency>Both the html and android modules start the same way: fetch an entry containing a rich text field with the base contentful.java SDK, then extract the CDARichDocument:
final CDAClient client = CDAClient.builder()
.setSpace(SPACE_ID)
.setToken(TOKEN)
.build();
final CDAEntry entry = client
.fetch(CDAEntry.class)
.one(ENTRY_ID);
final CDARichDocument node = entry.getField(FIELD_ID);If your rich text data comes from an external tool (for example, a JavaScript library) rather than directly through this SDK, build a CDARichDocument from plain JSON using GSON:
private final Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> jsonMap = gson.fromJson(json, type);
final CDARichDocument node = RichTextFactory.resolveRichNode(jsonMap);Use the html module to convert the node tree into an HTML string:
final HtmlProcessor processor = new HtmlProcessor();
final HtmlContext context = new HtmlContext();
final String html = processor.process(context, node);See the html module README for the full guide, including custom renderers.
Use the android module to convert the node tree into either CharSequence/Spannable output, or native Views:
final AndroidProcessor<CharSequence> sequenceProcessor = AndroidProcessor.creatingCharSequences();
// or
final AndroidProcessor<View> viewProcessor = AndroidProcessor.creatingNativeViews();
final AndroidContext context = new AndroidContext(activity.getContext());
final CharSequence result = sequenceProcessor.process(context, node);
// or
final View result = viewProcessor.process(context, node);See the android module README for the full guide, including rendering embedded entries/assets and hyperlinks, and performance advice for deeply nested documents.
Extend the core functionality by adding a new Renderer to a Processor. A Processor holds a list of renderers; each one knows how to render one kind of rich text node. Adding a renderer with .addRenderer(…) appends it to the end of the list (lowest priority, used as a fallback); .overrideRenderer(…) prepends it (checked first, taking priority over the built-in renderer for that node type):
processor.addRenderer(
(context, node) -> true, // Checker: does the renderer need to be invoked?
(context, node) -> node.toString() // Renderer: renders the specific node.
)Extending is especially important if you plan on rendering
embeddedorhyperlinkrich text nodes: this library cannot know your content model in advance, so it never ships a default renderer for those node types. Always provide your own renderer for embedded entries, embedded assets, and hyperlinks.
We are always looking for feedback — feel free to create an issue.
This library is a companion to contentful.java; consult its README for details on CDAClient, fetching entries, and the CDARichDocument node model this library renders. Every released change is recorded in the module-level source and JitPack release history.
- File an issue here on GitHub:
. Make sure to remove any credential from your code before sharing it.
We appreciate any help on our repositories. See CONTRIBUTING.md for the full contributor workflow.
This is a multi-module Gradle project (core, html, android, android_sample). Use the included Gradle wrapper — do not install Gradle separately:
git clone git@github.com:contentful/rich-text-renderer-java.git
cd rich-text-renderer-java
# Build all modules.
./gradlew build
# Run all tests.
./gradlew test
# Build or test a specific module.
./gradlew :core:build
./gradlew :html:test
./gradlew :android:testThis repository is published under the MIT license.
We want to provide a safe, inclusive, welcoming, and harassment-free space and experience for all participants, regardless of gender identity and expression, sexual orientation, disability, physical appearance, socioeconomic status, body size, ethnicity, nationality, level of experience, age, religion (or lack thereof), or other identity markers.
Read our full Code of Conduct.
| Document | What it covers |
|---|---|
| ARCHITECTURE.md | Internal module structure, data flow, key dependencies, extension model |
| CONTRIBUTING.md | Build setup, test commands, commit conventions, release process |
| docs/ADRs/ | Why key decisions were made (distribution, module structure, renderer pattern) |
| AGENTS.md | Agent-first context directory — sharp edges, invariants, quick reference |
Upstream (this repo consumes):
- contentful.java SDK (
com.contentful.java:java-sdk) — provides theCDARichNodetype hierarchy
Downstream (consumes this repo):
- JVM and Android applications that render Contentful Rich Text fields
- Distributed via JitPack