Skip to content

Large update for new tut and JSX availability#558

Open
BoDonkey wants to merge 1 commit into
mainfrom
update-old-jsx-tut
Open

Large update for new tut and JSX availability#558
BoDonkey wants to merge 1 commit into
mainfrom
update-old-jsx-tut

Conversation

@BoDonkey

@BoDonkey BoDonkey commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Please indicate which branch this PR should merge into:

Check one

  • main
  • latest
  • stable
  • Check if this PR will be resubmitted against another branch

Summary

Summarize the changes briefly, including which issue/ticket this resolves. If it closes an existing Github issue, include "Closes #[issue number]"
This PR is a major update of the existing client-side JSX tutorial. It places more emphasis on why you would choose to use JSX client-side and less on Vite configuration.

What are the specific steps to test this change?

For example:

  1. Run the website and log in as an admin
  2. Open a piece manager modal and select several pieces
  3. Click the "Archive" button on the top left of the manager and confirm that it should proceed
  4. Check that all pieces have been archived properly

What kind of change does this PR introduce?

(Check at least one)

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Build-related changes
  • Other

Make sure the PR fulfills these requirements:

  • It includes a) the existing issue ID being resolved, b) a convincing reason for adding this feature, or c) a clear description of the bug it resolves
  • The changelog is updated
  • Related documentation has been updated
  • Related tests have been updated

If adding a new feature without an already open issue, it's best to open a feature request issue first and wait for approval before working on it.

Other information:

@BoDonkey BoDonkey requested a review from boutell July 9, 2026 13:49

@boutell boutell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome. Just a couple notes to maximize clarity. The biggest ask is that we fix the title and slug to avoid confusing both Google and AI, which is definitely happening because this title and slug we chose long ago are hogging all the SEO on this topic.

prev: false
title: "Using JSX in Apostrophe with Vite"
detailHeading: "Tutorial"
url: "/tutorials/using-jsx-in-apostrophe.html"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This title and URL are both going to cause serious confusion for AI and SEO. They need to change.

I suggest:

"Using React for interactive components in ApostropheCMS with Vite"

/tutorials/using-react-in-apostrophecms.html

Please add a redirect rule from the old URL when this goes live to avoid an SEO fail.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, I know this URL has been here a long time! But it's super not working for us right now SEO and AEO wise.

detailHeading: "Tutorial"
url: "/tutorials/using-jsx-in-apostrophe.html"
content: "The Apostrophe Webpack build can easily be extended to include additional files. In this tutorial, we will add a weather widget powered by JSX and React to our ApostropheCMS project."
content: "Learn how to use JSX and React for an interactive browser-side component in ApostropheCMS, including how to extend the Vite build and connect React to a widget player."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would take "JSX" out of this, even, just for search clarity. It's fine that it's in the body of the document of course.


For new server-rendered pages and widgets, we encourage using JSX templates in place of Nunjucks. These `.jsx` templates run on the server and produce the HTML sent to the browser.

For focused browser-side behavior, many widgets only need ApostropheCMS's built-in widget player system. A widget player can respond to user events, fetch data, update the DOM, and reinitialize correctly during in-context editing without requiring a browser framework.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a link.

ApostropheCMS offers a robust and flexible platform for building content-rich websites, and it now comes with a powerful built-in Vite build system that caters to most development needs out of the box. This system streamlines the process of managing assets, optimizing performance, and ensuring a smooth developer experience. However, there are times when you may want to extend its capabilities by customizing the build process. One common scenario is integrating React components into your ApostropheCMS project for browser-side rendering, which involves customizing Vite to support JSX (JavaScript XML). By leveraging JSX and React, you can enhance the interactivity and maintainability of your front-end JavaScript components, providing a richer user experience while still taking advantage of the features offered by ApostropheCMS.
ApostropheCMS supports several ways to create and enhance the interface of a page.

For new server-rendered pages and widgets, we encourage using JSX templates in place of Nunjucks. These `.jsx` templates run on the server and produce the HTML sent to the browser.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a link. And emphasis. The focus is heavily on avoiding browser side hydration these days so there's a solid chance people are looking for the "other" guide.


The same weather widget could be built with a widget player alone. We are using React because it gives us a compact but complete example with multiple UI components, shared state, asynchronous data, and several parts of the interface that update in response to that state.

For a version of the same widget where the editor chooses the city and the weather is rendered entirely on the server, see the companion tutorial [Building a weather widget with server-side JSX](/tutorials/jsx-server-weather-widget.html). You can also learn more about using JSX instead of Nunjucks in the [JSX templates guide](/guide/jsx-templates.md).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! And here's the emphasis. That's great. In that case, just add more links where I noted earlier 🙏 I think you you have the emphasis covered.

As we will see when we cover the JSX code files, this default city will cause the widget to be prepopulated with data from a selected city that can then be replaced with user input.
Editors can now choose the city displayed when the widget first loads. Visitors will still be able to search for another city from the React interface.

This is one of the main differences between this browser-side version and the companion server-side JSX tutorial. In the server-rendered version, the editor controls the city being displayed. Here, the editor provides the starting value and the visitor can change it interactively.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 the parallel stories feel much more natural to me now that I see this distinction

(To be clear I love where you're going with this!)

This code extends Vite's configuration by adding the official React plugin, which provides Fast Refresh capabilities for React applications.
The `build.vite.extensions` configuration adds the official React plugin to ApostropheCMS's Vite configuration.

The module also connects React's Fast Refresh runtime to ApostropheCMS's templating system.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is necessary for hmr: 'public' to do any good? It's old, don't even bother answering me if it's not top of mind 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants