Customize the dashboard / welcome page

On v4.21.0 the redirect seems to be working for /admin but not /admin/.

1 Like

There’s an (at the moment Chrome-only) API that can be used for redirecting from /admin:

  bootstrap(app: any) {
    const url = "/admin/content-manager";

    if ("navigation" in window) {
      // Redirect soft /admin navigations to `url`
      // Chrome-only
      window.navigation.addEventListener("navigate", (e) => {
        const { pathname } = new URL(e.destination.url);

        if (new RegExp("^/admin/?$").test(pathname)) {
          window.navigation.navigate(url);
        }
      });
    }

    // Redirect hard /admin navigations to `url`
    if (new RegExp("^/admin/?$").test(location.pathname)) {
      location.href = url;
    }
  },

Also, in case you’re using TypeScript:

npm install -D @types/dom-navigation

Thanks for the idea of using bootstrap @Apostata.

2 Likes

Thanks for pointing this out @theSdev! I updated the repo, Gist, and post on my site.

If I could figure out how to edit previous posts in this forum, I’d do the same there, but:

module.exports = (config, { strapi }) => {
  const redirects = ["/", "/index.html", "/admin", "/admin/"].map((path) => ({
    method: "GET",
    path,
    handler: (ctx) => ctx.redirect("/admin/plugins/[YOUR-PLUGIN-NAME]"),
    config: { auth: false },
  }));

  strapi.server.routes(redirects);
};

Not sure about 4.20.0 but I’m using 4.21.1 and even /admin/ is not redirecting unless I perform a hard refresh after login.

not able to logout by using this code :joy:

But when you click on the top left logo or name, you still get redirected to /admin/

I found that while in develop mode, or clicking the “my-logo” link in the top left of admin panel, a refresh is needed for the route to kick in.

I also found this affecting production builds since time of writing. Until there’s a way to customize admin components again, this does not seem possible.

Hopefully strapi@5 will provide a way to achieve global route overrides.

For now i have used js inside app.js to remove the default admin panel and add custom componnent based on pathname

There is no way around?

I added the redirector middleware and used to have a patch to the strapi admin in the node modules to have another redirect

diff --git a/node_modules/@strapi/admin/admin/src/pages/HomePage/index.js b/node_modules/@strapi/admin/admin/src/pages/HomePage/index.js
index 21ab701..b706461 100644
--- a/node_modules/@strapi/admin/admin/src/pages/HomePage/index.js
+++ b/node_modules/@strapi/admin/admin/src/pages/HomePage/index.js
@@ -4,7 +4,7 @@
  */
 
 import React, { useMemo } from 'react';
-
+import { Redirect } from 'react-router-dom';
 import { Box, Grid, GridItem, Layout, Main } from '@strapi/design-system';
 import { LoadingIndicatorPage, useGuidedTour } from '@strapi/helper-plugin';
 import { Helmet } from 'react-helmet';
@@ -104,7 +104,7 @@ function HomePageSwitch() {
     return null;
   }
 
-  return <HomePage />;
+  return <Redirect to={'/plugins/dashboard-settings'} />;
 }
 
 export default HomePageSwitch;

used to have this patch to be applied inside the mode modules to fix the logo click case.

but now on 4.25.1 it’s not working.

so is there a new way to have it.

my redirector middleware is

module.exports = (config, { strapi }) => {
  return async (ctx, next) => {
    strapi.log.info("Redirector middleware");
    if (ctx.path === "/") {
      ctx.redirect(strapi.config.get("server.admin.url", "/admin"));
      return next();
    }
    if (ctx.path === "/admin") {
      ctx.redirect(strapi.config.get("server.admin.url", "/admin/plugins/dashboard-settings"));
      return next();
    }
    if (ctx.path === "/admin/") {
      ctx.redirect(strapi.config.get("server.admin.url", "/admin/plugins/dashboard-settings"));
      return next();
    }
    await next();
  };
};

I found one solution that work without redirects for strapi 4.25.1. It also base on swapping files. Code that renders HomePage is located in node_modules/@strapi/admin/dist/_chunks. This directory contains few files named in convention: HomePage-SPECYFIC_HASH. One that is used to render HomePage has mjs extension and contains the below code at the beginning:

import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";

HomePage content is located around below block of code:

/* @__PURE__ */ jsx(Typography, { as: "h1", variant: "alpha", children: hasAlreadyCreatedContentTypes ? formatMessage({
            id: "app.components.HomePage.welcome.again",
            defaultMessage: "Welcome 👋"
          }) : formatMessage({
            id: "app.components.HomePage.welcome",
            defaultMessage: "Welcome on board!"
          }) }),

Until components are placed inside jsx function everything seems to work well. I created code that finds proper file and then swaps with one that I modified. You can just paste below code to src/extensions/patch-admin.js. Prepared file should be placed in location: src/extensions/admin/HomePage.mjs

const fs = require("fs");
const path = require("path");

const home_page_dir = "./node_modules/@strapi/admin/dist/_chunks";

const requiredLines = [
  'import { jsx, jsxs } from "react/jsx-runtime";',
  'import * as React from "react";',
];

function checkFileContentSync(filePath) {
  const content = fs.readFileSync(filePath, "utf8");
  const lines = content.split("\n").slice(0, 2);
  return lines[0] === requiredLines[0] && lines[1] === requiredLines[1];
}

function findHomePageFilesSync(dir) {
  try {
    const files = fs.readdirSync(dir);

    const matchedFiles = files.filter((file) => {
      if (file.includes("HomePage") && file.endsWith(".mjs")) {
        const filePath = path.join(dir, file);
        return checkFileContentSync(filePath);
      }
      return false;
    });

    return matchedFiles;
  } catch (err) {
    console.log("Unable to scan directory: " + err);
  }
}

const filtered_files = findHomePageFilesSync(home_page_dir);

if (filtered_files == null || filtered_files.length != 1) {
  return console.log(
    `Unable to swap admin pages. Found ${filtered_files} filtes matching rules NOT 1!`
  );
}

// ---------------------------------------------

fs.cp(
  `src/extensions/admin/HomePage.mjs`,
  `${home_page_dir}/${filtered_files[0]}`,
  (err) => {
    if (err) {
      console.error(err);
    }
  }
);

To run it, I just use node src/extensions/patch-admin.js that I execute as package.json script.

Hope that It helps someone

1 Like