Next.js Discord

Discord Forum

Detect if is mobile based on url (starting with "m." like facebook) that works with SSG

Answered
Transvaal lion posted this in #help-forum
Open in Discord
Avatar
Transvaal lionOP
import { useMediaQuery } from '@mantine/hooks';
import {
    useMantineTheme,
} from '@mantine/core';

export function useIsMobile() {
    const theme = useMantineTheme();

    const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.sm})`, url.startsWith("m."));

    return isMobile;
}


Is there anyway to do that on nextJs that works both on client and server (SSG?)

useMediaQuery returns the second parameter (default) if on server.
Answered by necm1
guess it would be less pain to use SSR, simple nginx proxy + cloudflare infront of the nginx proxy
View full answer

34 Replies

Avatar
what does url returns?
if you want to have it on client side, you should better use: window.location.hostname which would like smth like this https://m.facebook.com => console.log(window.location.hostname) // m.facebook.com
Avatar
Transvaal lionOP
What if i want to static generate a mobile version of website? (when it starts with m.)
Avatar
like loading different components (mobile components) on server level if the subdomain contains m?
Avatar
Transvaal lionOP
yes
but using SSG instead of SSR
Avatar
so
just making things clear; next build provides SSG
isn't it
Avatar
Transvaal lionOP
yes, i need two builds
one for xxx and one for m.xxx
maybe the best way is using environment variables?
Avatar
but at the end; both are runned through next start
isn't it
you could deploy a version with the environment variables
but you could maybe use headers from next/headers
my bad headers is accessible in SSR
Avatar
Transvaal lionOP
But i don`t want ssr and instead SSG
Avatar
so my approach at this point

layout.tsx
return <html><body> <DomainProvider>{children}</DomainProvider> </body></html>


// DomainProvider using Context
const [isMobile, setIsMobile] = useState<boolean>(false);

useEffect(() => {
  const hostname = window.location.hostname;

  if (hostname.startsWith('m.')) {
    setIsMobile(true);
  }
}, []);
Avatar
Transvaal lionOP
but won`t it render the desktop version on server (event if starting with m.) then rerender the mobile version on client?
Avatar
so you could go into your header.tsx component and use smth like this

const domainContext = useContext(DomainContext); // exported from your DomainProvider

domainContext.isMobile //has to be defined in your context
I mean you could extend this logic with smth like
useEffect(() => {
  const hostname = window.location.hostname;

  if (!hostname.startsWith('m.')) {
     return;
  }

  const body = document.body.classList;

  if (body.contains('mobile')) {
    return;
  }

  body.add('mobile');

  return () => {
    body.remove('mobile');
  };
}, []);
is there a specific reason to use SSG over SSR?
Avatar
Transvaal lionOP
I`m using cloudflare pages to host (it supports only SSG, but even if has minimal support for SSG it costs money per click unlike ssg)
Avatar
there is no way to get SSG detect mobile except for the client
due to the build bundle which SSG uses
only way could be only using the window.location.hostname
or create 2 projects / builds
Avatar
Transvaal lionOP
Yes, but the thing is. I`m deploying two websites, it is building two times. Probably the only way is using environment variables
Avatar
then I guess go for the environment variables, so you can directly change them in cloudflare for you special needs
at the end; the result would be somehow the same (except for the useEffect approach which would load desktop and switch to mobile)
Avatar
guess it would be less pain to use SSR, simple nginx proxy + cloudflare infront of the nginx proxy
Answer
Avatar
@Transvaal lion could be awesome when you mark any answers from me as described here: