-
Notifications
You must be signed in to change notification settings - Fork 3
Developer Guide
nexus_theme/
├── api.py # whitelisted theme and sound API
├── hooks.py # includes, apps-screen tile, doc events, boot session
├── install.py / uninstall.py # Theme User role, menu items, desktop icon, assets
├── website.py # login page and website theming
├── permission_inspector/api.py # Permission Inspector API (System Manager only)
├── nexus_theme/doctype/… # Theme Definition, preferences, Theme Settings
├── nexus_theme/page/ # theme_studio, sound_studio, nexus_permission_inspector
├── nexus_theme/workspace/ # the Nexus Theme workspace
├── public/js, public/css # theme_manager, theme_switcher, theme_editor,
│ # sound_manager, sound_studio, brand_kit, …
├── public/sounds # 36 synthesised presets
├── utils/ # contrast, css_safety, palettes, palette_generator, web_css
├── fixtures/theme_definition.json
├── tests/ # pure unit tests (no site needed)
└── tests_site/ # site-backed tests
tools/generate_sounds.py # regenerates every preset sound
tools/generate_logo.py # regenerates the logo set in logos/
All methods live in nexus_theme.api and are whitelisted, so they work from frappe.call, REST (/api/method/nexus_theme.api.<name>) and server scripts. They act for the logged-in user and need the Theme User role.
# Themes
get_available_themes() # defaults, owned, public
get_active_theme() # theme, mode, dark theme, overrides, dark_overrides, density, sidebar_collapsed, source
set_active_theme(theme_name, overrides=None) # apply a theme (+ optional colour overrides)
set_theme_mode("Automatic", dark_theme="dracula")
clear_active_theme() # back to Frappe's own look
save_custom_theme(payload, share_public=0) # payload = the 11 colours + style fields
delete_custom_theme(theme_name)
export_theme(theme_name) # portable JSON
import_theme(payload, share_public=0)
get_recommended_palettes() # the 8 curated palettes
generate_palette(seed="#8c6f3f", is_dark=0) # 3 accessible variants from one colour
# Mini rail
get_sidebar_collapsed() # {collapsed: 0|1}
set_sidebar_collapsed(1)
# Home page
get_home_data() # greeting name, tiles with to-do counts, settings
# Density
get_density() # {density: "compact", source: "user"|"site_default"|"default"}
set_density("compact") # key or label; empty means "follow the site default"
# What's new (nexus_theme.whats_new)
get_notes() # the notes for the running release series
mark_seen() # remember that this person has seen them
# Sounds
get_user_sounds() # enabled flag + event -> {url, volume}
set_user_sound("save", file_url="/files/pop.wav", volume=0.6)
clear_user_sound("save")
toggle_user_sounds(enabled=0)
clear_all_user_sounds()Permission Inspector methods live in nexus_theme.permission_inspector.api and require System Manager:
get_options()
get_matrix(target_type="user", target="abbas@example.com", include_child=0)
get_matrix(target_type="role", target="Accounts User")
get_doctype_detail("user", "abbas@example.com", "Sales Invoice") # rules, live check, user permissions
get_user_permissions("abbas@example.com")
save_changes([{"doctype": "Sales Invoice", "role": "Accounts User", "ptype": "write", "value": 0}])
refresh_cache(target_type="user", target="abbas@example.com")save_changes validates every rule, cascades dependencies the way Frappe requires, saves the batch under a savepoint, clears the permission cache and returns the fresh matrix rows for the affected record types.
curl -s "https://yoursite.com/api/method/nexus_theme.api.get_available_themes" \
-H "Authorization: token <api_key>:<api_secret>"window.openThemeSwitcher(); // open Theme Studio
window.openSoundStudio(); // open Sound Studio
ThemeManager.applyTheme("theme_key", { bg_primary: "#ffffff" }); // apply now
ThemeManager.handOffToFrappe(); // back to Frappe's look
SoundManager.applyMapping({ save: { url: "/files/pop.wav", volume: 0.7 } });
SoundManager.setEnabled(false);
NexusDensity.modes(); // [{ key, label, description }, …]
NexusDensity.get(); // "comfortable"
NexusDensity.set("compact"); // applies and saves; returns a Promise
window.openCommandPalette(); // open the palette
NexusCommandPalette.register({ // add a command of your own; returns an unregister function
label: "Close the month",
hint: "Accounts",
keywords: ["period", "closing"],
run: () => frappe.set_route("period-closing-voucher", "new"),
});
window.openNexusWhatsNew(); // show the "What's new" card again
NexusRail.isCollapsed();
NexusRail.set(true); // fold the sidebar (saved); returns a Promise
NexusRail.toggle();
window.openNexusHome();Registered commands appear under Actions in the palette. Density changes raise a nexus-density-change event on document with { detail: { density } }, and the page carries html[data-density] for your own stylesheets.
To open the Permission Inspector on a given person or role from your own code:
frappe.route_options = { role: "Accounts User" }; // or { user: "someone@example.com" }
frappe.set_route("nexus-permission-inspector");# Pure unit tests, no site needed
python -m unittest discover -s apps/nexus_theme/nexus_theme/tests
# Site-backed tests (set allow_tests on the site first)
bench --site yoursite.com set-config allow_tests true
bench --site yoursite.com run-tests --app nexus_theme
bench --site yoursite.com run-tests --app nexus_theme --module nexus_theme.tests_site.test_permission_inspector
bench --site yoursite.com set-config allow_tests falseThe site tests create their own roles, users and a throw-away DocType, and check the Permission Inspector against Frappe's own has_permission from the affected user's session. One test guards every page route against a collision with a DocType name, which is what the Desk router resolves first.
python3 tools/generate_sounds.py # rewrites public/sounds from the recipes in the script
python3 tools/generate_logo.py # rewrites logos/ (needs Pillow and fontTools)
bench build --app nexus_theme # rebuild the JS/CSS bundles after editing public/The repository ships a pre-commit configuration with ruff (Python) and an ESLint configuration for the scripts. CI installs the app on a fresh site and runs the full test suite on every push to either branch: version-16 builds a Frappe 16 bench, version-15 a Frappe 15 one, and each asserts the framework version it got before running the tests.
pre-commit install
pre-commit run --all-filesNexus Theme · MIT licence · by Abbas Raza
Start
Guides
- Theme Studio
- Command Palette
- Density
- Sidebar Skins
- Mini Rail
- Home Page
- Sound Studio
- Permission Inspector
- Theme Settings
- Login Page
- Record Types
- Recipes
Help
Reference
Legal