Skip to content

ENG-9892: feat(plugins): add register_route hook and get_plugin lookup#6728

Open
FarhanAliRaza wants to merge 3 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/eng-9892-auth-remove-global-state-circular-import-workarounds-in
Open

ENG-9892: feat(plugins): add register_route hook and get_plugin lookup#6728
FarhanAliRaza wants to merge 3 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/eng-9892-auth-remove-global-state-circular-import-workarounds-in

Conversation

@FarhanAliRaza

Copy link
Copy Markdown
Contributor

Plugins that contribute pages (e.g. auth) previously needed global state and circular-import workarounds to find their configured instance and inject routes. Instead:

  • Plugin.register_route(app) runs once per app at the start of compile_app, letting plugins add pages before routes are resolved.
  • get_plugin(cls) resolves the configured plugin instance from the rxconfig plugins list, raising ConfigError on ambiguous matches.
  • add_page invalidates the cached router so late-added routes resolve.

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally prior to submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

Plugins that contribute pages (e.g. auth) previously needed global
state and circular-import workarounds to find their configured
instance and inject routes. Instead:

- Plugin.register_route(app) runs once per app at the start of
  compile_app, letting plugins add pages before routes are resolved.
- get_plugin(cls) resolves the configured plugin instance from the
  rxconfig plugins list, raising ConfigError on ambiguous matches.
- add_page invalidates the cached router so late-added routes resolve.
@FarhanAliRaza FarhanAliRaza requested a review from a team as a code owner July 9, 2026 20:21
@FarhanAliRaza FarhanAliRaza added the reflex-enterprise For issues related to `reflex-enterprise` label Jul 9, 2026
@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds plugin-owned route registration and lookup support. The main changes are:

  • A staged Plugin.register_route hook for contributing pages before compile.
  • A get_plugin() helper for resolving configured plugin instances.
  • Router-cache invalidation when pages are committed through the new page path.
  • Tests and docs for plugin page registration behavior.

Confidence Score: 4/5

This is close, but the router cache issue should be fixed before merging.

  • Page commits now clear the cached router.
  • The compile path still replaces _pages directly without clearing the cached router.
  • A long-lived app can keep resolving routes from an older compile after _pages is rebuilt.

reflex/compiler/compiler.py

Important Files Changed

Filename Overview
reflex/app.py Adds staged page preparation, plugin route collection, and router invalidation on page commit.
reflex/compiler/compiler.py Registers plugin routes before page evaluation, but the compile-time page reset can still leave the cached router stale.
packages/reflex-base/src/reflex_base/plugins/base.py Adds the route-registration hook context and configured plugin lookup helper.
reflex/state.py Adds dynamic route argument type introspection for staged plugin route validation.

Reviews (3): Last reviewed commit: "feat(plugins): stage register_route hook..." | Re-trigger Greptile

Comment thread reflex/compiler/compiler.py Outdated
Comment thread reflex/compiler/compiler.py
@codspeed-hq

codspeed-hq Bot commented Jul 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing FarhanAliRaza:farhan/eng-9892-auth-remove-global-state-circular-import-workarounds-in (b9ced03) with main (948c619)2

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (3b97060) during the generation of this report, so 948c619 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

tests/units/reflex_base/plugins/test_base.py collided with
tests/units/vars/test_base.py during pytest collection without an
__init__.py, and towncrier required feature fragments for PR reflex-dev#6728 in
both the root package and reflex-base.
Comment thread reflex/compiler/compiler.py
@FarhanAliRaza FarhanAliRaza marked this pull request as draft July 9, 2026 20:34
Rework the register_route hook so plugins contribute pages through a
staged add_page capability instead of mutating the app directly. All
plugin contributions are validated and collected first, then committed
together, so a failing hook cannot leave partial pages or dynamic route
variables behind.

Split App.add_page into a pure _prepare_page (validation/normalization,
the extension point for App subclasses) and a fixed non-fallible
_commit_page, and give the hook context add_page, has_app_page, and
app_type instead of the mutable App. Detect app/plugin route conflicts,
structural dynamic-segment mismatches, and inconsistent dynamic argument
types up front, and invalidate the cached router when a page is added
after it was first built.
app._apply_decorated_pages()
config = get_config()
_register_plugin_routes(app, config.plugins)
app._pages = {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Router cache persists

This reset still bypasses the router-cache invalidation added to _commit_page(). When a long-lived app has already served a request, app.router can be cached from the old route set. A later compile replaces _pages here and rebuilds it below, but the cached router keeps matching the old route list because this direct assignment never clears app.__dict__["router"]. Requests after that compile can continue resolving against stale routes until another page commit happens to invalidate the cache.

@FarhanAliRaza

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: b9ced03cae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@FarhanAliRaza FarhanAliRaza marked this pull request as ready for review July 10, 2026 14:42
@FarhanAliRaza FarhanAliRaza requested a review from Alek99 as a code owner July 10, 2026 14:42
@masenf masenf changed the title feat(plugins): add register_route hook and get_plugin lookup ENG-9892: feat(plugins): add register_route hook and get_plugin lookup Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reflex-enterprise For issues related to `reflex-enterprise`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant