If possible, they should be able to see ONLY the left menu.
users that shouldn´t have access to a lot of stuff are able to see everything if they click on Primary Data!!!
Access rules should work reliably on Raw Data (as well as on API endpoints any any other way to access data). In fact, Raw Data is a good place to test that access rules restrict data permissions in the way you intend.
But they are working elsewhere.
Like, if I log with a different user, I can´t see ANY record on the PDCA table. But I can click on Raw Data and see everything
here… PDCA Table being viewed by Editor type of user… no record visible
Denied Access to Code
but then… Raw Data, same PDCA table.
Really, the tools menu shouldn´t even be available for non admin users…
I didn´t find in the help if there is a way to create a 4th type of role, that would fit between Viewer and Editor. I want user to view or make changes to the document data, but NOT to structure or formulas.
I noticed the user here (help page for Access Rules) doesn´t even have access to Raw Data option.
Access rules should work reliably on Raw Data (as well as on API endpoints any any other way to access data). In fact, Raw Data is a good place to test that access rules restrict data permissions in the way you intend.
I see the problem. Is that sometimes you make INDIRECT access rules.
In my table, users are linked to companies.
The PDCA records are also linked to companies.
I have access rules to companies. Users can only see the companies they are linked to.
And therefore, since widgets are linked, users can only see the data linked to the companies they can see.
But the when accessing RAW DATA, they are able to well, access DIRECTLY the raw data instead of a widgets linked to a table with acess rules.
I think that makes it even more important to be able to hide the Raw Data from common users. Because MANY times, users might want to hide data based on other means, not on direct rules based on that table.
Glad you found the issue. So you are right, with access rules, you need to restrict access to each table separately.
It may help to deny access by default, then add access explicitly to each table, to make sure nothing is slipping through undetected.
We could try to automatically create (or suggest) additional rules to apply to linked tables. That could be tricky, since there are many different ways to link data.
Regarding the 4th role, you can achieve something similar by giving users “Editor” permission (which allows data AND structure changes), then removing the “Structure” permission in the Access Rules page:
Hiding the raw data page would make it harder for a user to discover any data they shouldn’t see, but a savvy user could still use the API to get at anything permitted by the rules. Today, raw data pages are helpful to the creator using “View As” to explore the effect of rules, though you are right, for users you are trying to limit, offering “Raw Data” page feels wrong.
So you make a good point about the tools menu generally. It could perhaps be hidden entirely in some cases, or owner could have an option to hide it from all non-owners or certain roles (similar to the option to limit structure changes).
THIS!!!
I think more of the tools could with time be hidden. For many end users, having all those extra icons on the screen, as well as the rightside edit menu, is quite confusing EVEN if they ultimately can´t do nothing with it, being able to access those, mess with them, just to be blocked when trying to save the change, is very confusing and frustrating.
Believe me, I HAVE seen users explore the extra icons. Human curiosity. And they get really lost with the extra icons.
For the internal Grist version we are using in my company (something completely different than the case above, which is a personal project), I am using much more than recommended the iframes because the iframes can hide the menus. Users have a much easier time using Grist in iframes without the menus than with the original interface with tools, edit menu that can be viewed, etc.
Related feature request here: Add possibility to mask lateral columns to simplify uses for beginners · Issue #1266 · gristlabs/grist-core · GitHub
We faced a common challenge with our self-hosted Grist instance: how to hide specific administrative tools from users with “Editor” roles while leaving them visible for “Owners.” The goal was to make this happen automatically and reliably, without any user intervention or modifications to Grist’s core files.
Our solution is centered on a reverse proxy that acts as a smart middleman between the user and the Grist application. Instead of providing instructions, here’s a breakdown of the key working parts that make this system function.
The Working Parts
1. Nginx as the Reverse Proxy
The entire system is anchored by nginx running as a reverse proxy. All incoming web traffic is routed to nginx first. Its job is to forward requests to the Grist container and, crucially, to manipulate the content of the responses before they are sent back to the user’s browser.
2. The Content Injection Engine
The core of the logic is handled by nginx’s sub_filter module. When Grist sends back an HTML page, nginx scans the content for a specific tag—</head>—and replaces it with our custom code followed by the original </head> tag. This is how we inject our logic seamlessly into every page Grist serves.
nginx.conf snippet:
sub_filter '</head>' '<style>...</style><script>...</script></head>';
sub_filter_once on;
3. Role Detection with JavaScript
The injected code starts with a small JavaScript block. Its sole purpose is to determine the user’s access level. It makes an asynchronous API call to Grist’s /api/orgs/current endpoint, which returns the user’s role without requiring a page reload.
JavaScript snippet:
(async () => {
try {
const response = await fetch("/api/orgs/current");
const data = await response.json();
// If the user isn't an owner, we apply our class
if (data.access !== "owners" && data.access !== "owner") {
document.body.classList.add("role-editors");
}
} catch (error) {
console.error("Failed to detect user role:", error);
}
})();
4. The Visual Hiding Mechanism (CSS)
Rather than having the JavaScript directly hide elements, which can be messy and slow, the script’s only job is to add a class (role-editors) to the <body> tag. Our injected CSS rules then use this class to hide the tools. This separates the logic (role detection) from the presentation (hiding elements), making the system cleaner and more efficient.
CSS snippet:
body.role-editors [data-test-id="tools-raw"],
body.role-editors [data-test-id="access-rules"] {
display: none !important;
}
By combining these four working parts, we created a robust and maintainable solution. The system is external to Grist, so it survives updates, and all the logic is centrally managed in a single nginx configuration file, providing a clean and reliable way to handle UI access control.
I absolutely share the sentiment in this thread re: suppressing operational/internal tooling to certain user types. There is so much I like about Grist, the UI/flows are very well designed and ordered. It comes very close to a perfect solve for my use case – except – for the access to raw data and the behind-the-scenes stuff that non-owner users seem to have access to by default.
My core need is to have a nice way to share collaborative spreadsheet data with clients. Right now I send Google sheets and add tabs for new content, but I want to move to more of an “app” environment so it feels more like a standalone product.
Is there a functional user-friendly solve to the challenges raised in this post/thread? The response from Joe is interesting and great it that got it done, but sounds very technical, far from the simplicity of what Grist has the potential to provide.
There is always the possibility of displaying everything to users through Custom Widgets.
Thanks Rogerio, I will need research how that addresses those issues. So you managed to create a solution where your clients/users on see data, not all the Grist app options/tools and raw data?
Yes.
You see, Grist has an option to ONLY show the current screen as an iframe. When you use it, you can´t even see the leftside menu, meaning user can´t change pages.
That’s a problem. UNLESS moving between Grist pages is done outside Grist.
There are two ways to do that.
1 - you create the pages in Grist directly, but you will make an iframe without tools and menus, for EACH page. And each iframe link will be like a different tab accessed through a program outside Grist.
I did this solution to show Grist pages in our XWiki.
Each tab you see there shows a different Grist page
2 - the second solution is similar. Accessing Grist through an iframe in the no menus mode. But instead of several different tabs for each page, you create an app for navigating your tabs and data.
This will make Grist more customized BUT it will require much more effort if you want users to input data. Because you won´t be able to use Grist native widgets like Table, Cards, etc.
Basically, you will have to create your own table and card widgets.
check the example
<iframe src="https://templates.getgrist.com/6D8E2h2DQNwS/Task-Management/p/6?embed=true" height="250px" width="100%" frameborder="0">
</iframe>
Main part here is the embed=true
This disables menus. ALL of them. Including navigation. But as I have shown, you can create your own navigation, OUTSIDE Grist, by creating your menu where each link or tab takes you to a different Grist page shown as iframe with embed=true
Thank you very much for your time and explanation Rogerio. I follow your concept, I think it could serve my needs (create pages for each view, then build navigation around it outside of Grist.
One suggestion I have is that if possible, only show a single “link” until user is logged on. Otherwise, there may be a dissociation between link/tab and what user sees as soon as he logs in.
example: in the XWiki example above, there is the tab for Risk Management. If user is not logged in, Grist will ask him to log in. When he does so, Grist will take him to the inital page INSTEAD of the Risks page, despite the fact he is in the Risks Management tab. He will have to change tab and go back to the Risk tab to see the Risk Management page.
It’s not difficult, but users that don´t realize logins ALWAYS take you to home pages might get confused.
Understood, thanks for the heads up ![]()







