Complex routing in NextJs - reactjs

I'm trying to create descriptive routes in the NextJs app however I'm struggling with the nextJs file-based routing system.
Intended route in the web is: (/posts/id/mail);
How I do it in the project:
Posts
- index.js
- [id]
- mail.js
As you can see, I don't have index.js in my [id] folder hence whenever somebody decides to go to /posts/id without '/mail' it is gonna be 404.
So basically my question is: How do I turn mail.js into index.js and make the URL stay the same (/mail at the end).
If there is no way of doing it natively with nextjs I'd also be grateful if you let me know.

catch all
This might not be the way you like it, but you might use a catch all route to hande [id] and mail.js together in one file.
E.g. if you have a file [...post].jsx and call the routes /someid/mail or just /someid you would have params.post to be an array like [ 'someid', 'mail' ] or just [ 'someid' ].
redirect
Apart from that I also didn't find any way for a folder to be a route on its own without an index file (or any other file), especially for a route like www.example.com/ (i.e. without an /index appended to it). I solved it by using some "unneeded" path /main and then redirected that to /.
As a remark:
I found that the specific route /index caused an error in some cases, that's why I've choosen /main.
I don't remember exactly, it might be dependent on if you want both routes ('/index' and '/') to be valid and point to the same file (and stay visible in the addressbar), or if only one of them should be valid and redirect to the other. Also in that case my paths came from getStaticPaths, not from files.

Related

Href opening link in http://localhost:3000/LINK rather than opening the link seprately [duplicate]

I just have created primitive html page. Here it is: example
And here is its markup:
www.google.com
<br/>
http://www.google.com
As you can see it contains two links. The first one's href doesn't have 'http'-prefix and when I click this link browser redirects me to non-existing page https://fiddle.jshell.net/_display/www.google.com. The second one's href has this prefix and browser produces correct url http://www.google.com/. Is it possible to use hrefs such as www.something.com, without http(s) prefixes?
It's possible, and indeed you're doing it right now. It just doesn't do what you think it does.
Consider what the browser does when you link to this:
href="index.html"
What then would it do when you link to this?:
href="index.com"
Or this?:
href="www.html"
Or?:
href="www.index.com.html"
The browser doesn't know what you meant, it only knows what you told it. Without the prefix, it's going to follow the standard for the current HTTP address. The prefix is what tells it that it needs to start at a new root address entirely.
Note that you don't need the http: part, you can do this:
href="//www.google.com"
The browser will use whatever the current protocol is (http, https, etc.) but the // tells it that this is a new root address.
You can omit the protocol by using // in front of the path. Here is an example:
Google
By using //, you can tell the browser that this is actually a new (full) link, and not a relative one (relative to your current link).
I've created a little function in React project that could help you:
const getClickableLink = link => {
return link.startsWith("http://") || link.startsWith("https://") ?
link
: `http://${link}`;
};
And you can implement it like this:
const link = "google.com";
<a href={getClickableLink(link)}>{link}</a>
Omitting the the protocol by just using // in front of the path is a very bad idea in term of SEO.
Ok, most of the modern browsers will work fine. On the other hand, most of the robots will get in trouble scanning your site. Masjestic will not count the flow from those links. Audit tools, like SEMrush, will not be able to perform their jobs

Sanity/next slug- 404 not found

When I try to access my slug page, the name of the slug shows in the browser search bar (so I know its accessing the backend data), but nothing shows up on the page. In the console, error 404 keeps coming every 3 seconds.
Due to lack of timing, experience, knowledge, etc., I've had to switch from react to next very last minute (learning both for the first time at the moment). In react, I remember you could establish a path/page that went '/pageName/:slug', but I haven't seen that for next. I think this might be what is causing the issue, that I don't have an equivalent of that, but I'm not sure how to go about doing that. How do I fix this issue?
I'm happy to post any code if needed.
Got it. I hadn't given much context in the post, but I had two .js page files, gallery.js (where I can select a set), and sets.js where I wanted the slug to route into. So my link in gallery.js looked like this: <a href="./sets/[slug]">.
The fix: I renamed sets.js to [slug].js, and removed /sets/ so that it was just <a href="./[slug]">.

nextJS nested Routes for multiple slug cases

Hello everyone I have a problem regarding nextJS routing
i have the following folder structure and its works fine for a simple scenario where a project has only one folder and this folder have one domain
but my problem occurs when a project has a folder and this folder have many subfolders
for example if i have this URL projects/1/folder1/subfolder1/subsubfolder1/.../domain1
so as you can see i don't know how many slugs i will have
how can I achieve this??
Dynamic routes can be extended to catch all paths by adding three dots (...) inside the brackets.
It means you can create a file with name [...folder].js and in that file, you can write your logic to handle the route.
You can even make it optional by including the parameter in double brackets ([[...folder]]). This allows /base, /base/a, /base/a/b, and so on.
To access folder object you can simply get it from query as
{ "folder": ["a", "b"] }

Nginx fallback for file not found to different directory with same path

Short Version: Is there any easy way to automatically redirect a path like /templates/my_child_theme/main/sidebar/user_nav.html to /templates/default/main/sidebar/user_nav.html whenever a 404 is encountered?
Question: Is there an easy way to use something like try_files within nginx to change a filepath when not found to a different folder with the same file path at the end? I'm currently using a client-side framework (AngularJS) and dealing with checking for the existence of files can get fairly expensive as I am literally performing an AJAX call for each file and looking for a 404 before performing the logic to swap out the path in Javascript. I've seen similar solutions for fallback images but haven't gotten a good solution yet. Here's the gist of what I'm looking to do:
Look for file at /templates/$1/$2.
On HTTP 404 instead return /templates/default/$2.
This only really needs to happen in the /templates/ location for now.
It's possible that these files could be nested several layers deep so I need something like /templates/my_child_theme/main/sidebar/user_nav.html to redirect to /templates/default/main/sidebar/user_nav.html
Backstory:
I've been building a site in AngularJS that has a fairly complex templating setup. I am utilizing the awesome ui-router module from Angular UI for deeply nested views and have written a few custom functions to implement child themes similar to Magento's fallback system. Here's what currently happens:
AngularJS requests a template path using a getTemplate() function I wrote which first looks for the file at /templates/child_theme_name_here/filepath by performing an XMLHttpRequest, checking for a status code of 404 (file not found), and then either returning that path or (in the case of a 404) returning /templates/default/filepath instead.
This way I can overload modify specific templates without needing to copy the entire theme each time, making development easier (we have 3 major corporate clients which will each have their own branded child theme) by not making me keep up with each change across multiple themes.
If there is a better way to do this within AngularJS I am open to that as well, it just seemed to me that Nginx would be the most logical place to perform such an action due to to it's low-level integration with the filesystem.
Solved.
Had to teach myself a bit on regular expressions, but finally got it working.
Here's what worked:
location ~* ^\/templates\/([^\/\\\]+)(.*)$ {
try_files /templates/$1$2 /templates/default$2 =404;
}
Regex Explanation
~* means case-insensitive matching (not really regex, just nginx syntax)
^ means start of a string
\/ means match a backslash
templates means literally match the word templates
\/ means match a backslash again
( means start capturing the following match as a group for later use
[^\\\/] means match anything that's not a backslash or forward slash means the previous set of characters can be matched multiple times (i.e. keep matching anything that isn't a slash.
) means stop capturing characters for this group. We have now defined the string that represents the first folder after /templates/
(.*) means match any other character as many times as needed (match everything that isn't a line feed in other words)
$ means match the end of the string
try_files then tries each URL in order
/templates/$1$2 means try /templates/(everything in capture group 1 above, which holds the folder we captured)(then add everything from capture group which holds the backslash and anything after it until the end of the url)
/templates/default$2 is very similar, except instead of using the text from capture group 1 ($1, the folder name we matched) we use the text "default" and then add everything from the second capture group to the end like before
=404 means that if neither of those worked return a 404 error
I'm seeing a significant speed improvement by moving this fallback mechanism into the server versus all of the extraneous calls I was forced to do before on the client.

Dealing with Alias URLs in CakePHP

I am rewriting our company website in cakephp, and need to find a way to do the following:
A user enters our site by using one
of the promotional alias URLS that
has been pregenerated for a specific
media advert ( magazine, web
promotion etc )
The URL is checked against a
database of alias URLs, and if an
alias exists, then a specific
tracking code is written into the
session.
I have considered several options, none of which seem suitable for this purpose. They are:
Putting the lookup script in the
beforeFilter() in appcontroller, so
that its included in every
controller. (Writes a session value
so it only perfoms once.)
This option only works for existing contollers, and gives the
Cake 'missing controller' error if a
URL doesn't exist.
Specific routes for each alias in
Routes.php - Works but there are
potentially hundreds of alias urls
added/removed regularly via admin
interface.
Route all site URLs to their own
actions, and having an 'everything
else' rule, for the alias URLs that
maps to my lookup script. - Messy
and I lose the built in Cake
routing.
Custom 404. - I don't want to
return 404's for these urls, as I
feel its bad practice unless they
really don't map to anything.
I really could do with a place in the application flow where I can put this lookup/tracking script, and I'm fairly new to cake so I'm stumped.
EDIT: Also, I know that a subfolder called say 'promo' would easily do this, but I have a lot of legacy URLS from our old site, that need handling too.
Note: I'm making an assumption that your promo URLs are in the form of "domain.com/advert-259" or something like that (i.e. no "domain.com/adverts/advert-259'). That would be just too simple :)
Hopefully, you can use the routing with some regex. Add this to your /config/routes.php and let me know if a different regex will help :)
$controllers = Configure::listObjects('controller');
foreach ($controllers as &$value)
{
$value = Inflector::underscore($value);
}
Router::connect('/:promo', array('controller' => 'promos', 'action' => 'process'), array('promo' => '(?!('.implode('|', $controllers).')\W+)[a-zA-Z\-_]+/?$'));
Now you can handle all your promo codes in PromosController::process().
Basically, it checks for a promo code in url, excluding those in the $controllers array (i.e. your regular routes won't be messed up).
Later on you might want to consider caching the value of Configure::listObjects() depending on the speed of your app and your requirements.
A very interesting question. I think I would use item #3. It's not really that messy -- after all, this typically is handled by the pages controller in my stuff. That's how I'd handle it - hardcode your routes to your controllers in routes.php, then have a matchall route that will work for your promo codes. This allows you to keep legacy URLs, as well as use a lot of the standard cake stuff (you probably will just have to explicitly state each of your controllers routes, not such a chore...) Additionally, it will let you do some cool stuff with 404 errors -- you can put some logic in there to try and figure out where they were trying to go, so you can superpower your 404's.

Resources