Root URL as site 1

Hi John and Patrick! I’m probably going to be posting a lot in the next 2 weeks in both Omeka-S and Omeka forums :slight_smile:

Real world project:

It would be ideal to have a setting to tell the Omeka-S installation to load one site ID as the root URL. It doesn’t have to be the first site created, it could just be a “primary” setting. In the case of the project above, it’s probably going to be one site forever, but there could be some sites added in the future.

I could of course implement some HTTP redirects on the Apache side (although this is on RH, so not sure what control I have) but SEO would also be better served by having one site as the root. I guess this hasn’t come up as a use case / scenario yet? I guess I could also do some HTTP masking, although that’s even more of a “trick” than I would prefer to put into production.

Even if you can just point me in the right direction as far as writing a module, modifying some configuration setting, or whatever, that’d be great.

1 Like

In the global settings for your Omeka S installation (admin/setting), there is an option for “default site” where you can select from a dropdown of all sites in the installation to set what people see when they go to the front page of the installation.

That was easy! Thanks, I skipped right over that option :slight_smile:

Oops, spoke too soon! So it appears that setting just does a URL forward?

I would like to work on a module that can allow the following:

Ignoring the initial sub-dir on the dev server, basically remove the “/s/sitename” from the URL for the default site.

So this is what I just posted in Reclaim Hosting support… wondering if anyone on the Omeka team has a comment? I’ll be posting an .htaccess rewrite rule as solution if nothing else.

Is there any way I can do some .htaccess rewrite to remove the /s/digital from the Omeka S URL? If we have full htaccess in the root public_html folder, then my only question is whether you advise it or find masking/rewriting to be troublesome. And if .htaccess is turned off or otherwise limited, then my question is what options might I have aside from modifying the Omeka-S routing in PHP?

Don’t want to change:

Want to change:*
and still allow for

I’ll just note to start the reasoning behind the “dirty” URLs…

Omeka S lets you freely assign the URLs of all pages within your sites. This works fine when all those URLs must be “underneath” the /s/your-site prefix, but if you remove that and shift the site directly to the root, you encounter some issues. There’s obvious ones like naming a page “admin” (is the admin shadowed? just the dashboard? or is the page inaccessible?), or naming a page “s.” Slashes are allowed for users who want to simulate hierarchy in their URLs so “deep” pages underneath either of those names could be “shadowed” in the same way.

Some of that could be avoided by only allowing root URLs only in a “single site mode,” or by simply disallowing some URLs, but it does present a problem for us in that adding to such a banned list could become problematic in the future (or even now), and would have the effect of banning page URLs that work perfectly fine in the current system.

In addition, part of the reasoning of reserving “/s/” for the site content was that other modules could make use of the then “free” space under the root. My understanding is that Scripto for S at least makes use of URLs of that type, or plans to.

Now, all that’s not to say that it’s impossible… just that it’s a fairly tricky thing for us to provide out of the box. A mod_rewrite solution should work fine, subject to those limitations I mentioned. Another possibility would be a module that adds parallel routes for a site at the root, or at just /s/ (in fact, “single site mode” at /s/ is probably the least problematic alternative that could be provided and not interfere with things).

Thanks for the explanation John! Understood about the potential for namespace conflict underneath the site domain.

You said that mod_rewrite should work, but when I looked at the .htaccess file (which I assume is included in the Omeka S zip/download) it appears to only allow filename downloads directly, and then everything else is routed via index.php? If so, I believe all URL rewrites beyond that point (hitting index.php) would have to be handled in PHP rather than on the Apache side?

Just a short musing on single site mode, which I think is a really great idea if Omeka Classic isn’t going to be developed much further (or not be a priority) - it’s clear that Omeka-S is intended for use at the institutional/enterprise level (many sites, central pool/lake) but given the other mature/robust options at that level (not sure where you guys see yourselves in competition with the other discovery layers/platforms) I wonder if a primary use case will be large collections with 1-5 sites. I think the biggest impact of the /s/sitename is SEO and URL readability, which may be more important for “large collections” than for institutions who are providing internal services.

# The following rewrites all other queries to index.php. The 
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to 
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size 
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L]

John, when you have time, am I on the right track with looking at this code? I’m tracing from index.php

    public function run()
        $events = $this->events;
        $event  = $this->event;
        // Define callback used to determine whether or not to short-circuit
        $shortCircuit = function ($r) use ($event) {
            if ($r instanceof ResponseInterface) {
                return true;
            if ($event->getError()) {
                return true;
            return false;

        // Trigger route event
        $event->stopPropagation(false); // Clear before triggering
        $result = $events->triggerEventUntil($shortCircuit, $event);
        if ($result->stopped()) {
            $response = $result->last();
            if ($response instanceof ResponseInterface) {
                $event->stopPropagation(false); // Clear before triggering
                $this->response = $response;
                return $this;

If so, can you explain or point me to documentation about what is a Name vs. Target vs. Response vs. event?

Yeah… tracing will work but it gets a little… hairy with ZF 2/3. The routing, along with much of the system is really running through their Event Manager system, which is where the name and target stuff is coming from. Response is an HTTP response and is more specific to the MVC stuff.

In terms of routes, the actual routes we’re using are in application/config/routes.config.php, and you can, as a module add to or alter those in the same way as any other configuration item: by including it in your module’s config file under the same key(s). So a possible approach would be basically duplicating the site route tree but changing the route string from the top segment to something else. At least as a starting point.

1 Like

I am going to try this, but wondering what you think about the feasibility of it… the top route / is set to Omeka\Controller, which I assume handles all the rest of the routing… since the htaccess file directs all incoming requests (other than files) to index.php which is / (root). But, would it be possible to combine the site route with the top route in some way (for a “single site mode”) so that /s/:site-slug “responds” under the / route? (I know all the concepts, but I’m not an active developer so my words might not be totally accurate lol)

return [
    'router' => [
        'routes' => [
            'top' => [
                'type' => 'Literal',
                'options' => [
                    'route' => '/',
                    'defaults' => [
                        '__NAMESPACE__' => 'Omeka\Controller',
                        'controller' => 'Index',
                        'action' => 'index',
            'site' => [
                'type' => 'Segment',
                'options' => [
                    'route' => '/s/:site-slug',
                    'constraints' => [
                        'site-slug' => '[a-zA-Z0-9_-]+',
                    'defaults' => [
                        '__NAMESPACE__' => 'Omeka\Controller\Site',
                        '__SITE__' => true,
                        'controller' => 'Index',
                        'action' => 'index',

This is a feature that is commonly needed. See or even (attach multiple domains to an instance).

A modification of the htaccess cannot be enough (the url created inside Omeka should be changed too), so the routes should be changed inside the core or via a module (Omeka S is a lot more modular than Omeka classic, so we can change nearly everything via modules except some points that require little changes in the core). And a check against all routes should be added when a slug is created to avoid issues (the routes on the root are not many anyway).

Similar, global pages for a site (about, etc.) is a true need too, not only pages by site.

Excellent points Daniel. Thanks for the reminder to check GitHub issues queue. I have added my support for this feature there.

And I agree about global pages too. IMO any “web-based X management system” would ideally support basic website presentation, because even if it is tailored to some specific niche (document store, digital library, blog) people’s needs are varied and it is simple to support the basic needs. This has typically not been the case with highly structured systems - for instance Microsoft Sharepoint which for a while some organizations were trying to use as their public website back-end as well as internal intranet. The developers never thought of this use case, but the customers did.

After some search, there are many ways to do it.
So here is a possible solution, that implies the minimal changes to Omeka and modules:

  • keep the current routing to create urls, except for the route “site”, that should be a regex or a custom Zend route, that checks if the slug is empty or not, to build a url without s/:site-slug. It should take care of child routes too;
  • add a controller to forward requests with an empty slug (/item, /item-set…) to standard routes (the child routes of the route “site”);
  • allow one site to have an empty slug: it will be the root url;
  • add some checks when creating pages for the root site or global pages (“about”).

For memo, another issue related to this point: the login, maintenance, etc. pages are not themable.

Any changes on that topic ?
I need to create a main site on the root url with sub sites.
The github didn’t show any news.


We’ve developed an omeka s module that does this job.


Can you share the code? Or a link to the working site? :slight_smile: Very interested

Hi Ben,

You can view / download the code here.

1 Like