How to create multiple static pages with Hugo? - hugo

I'm trying to build a basic landing page on GitHub pages using Hugo (version 0.44) and the hugo-sustain theme. But I struggle to understand how to organise content with Hugo.
This is the basic example site from the hugo-sustain theme:
exampleSite
├── config.toml
├── content
│ ├── projects.md
│ └── blog
│ ├── creating-a-new-theme.md
│ ├── go-is-for-lovers.md
│ ├── hugo-is-for-lovers.md
│ └── migrate-from-jekyll.md
├── data
│ └── projects.yml
└── static
Now I'd like a nice projects page, where I have images and/or text.
But with the hugo-sustain theme the actual text content and the project's descriptions are in the projects.yml file. But not in the projects.md as I'd have expected.
That means it will be a lot harder to encode content that will nicely compile as a static page.
I have found this workaround with getting static pages set up following this post. But is that really the best-practice approach? It feels quite messy and involved for just one simple page.

Now I'd like a nice projects page, where I have images and/or text.
Generating pages from data in Hugo is currently not possible and will (most likely) not become possible in the near future: https://github.com/gohugoio/hugo/issues/5074
That means you have to create a section projects with .md files of each project. They will have their own layouts. The alternative is to use the trick from Regis (https://www.thenewdynamic.com/) where you run Hugo twice: once to transform data into .md files and once to render the .md files.

Related

Nextjs - first level dynamic routing for many pages each of which has children

Nextjs - first level dynamic routing for many pages each of which has children
I have a NextJS 12.2/React 18 app linked to a CMS, where users can set up their custom page structure, content & theme.
In the front-end, there will be some API calls to get the app
settings and configuration including the page hierarchy.
The default six top-level page names are homepage, content, events,
user, search and blog.
We can think of these six pages as types, so we have six different
types, and users can change the names of these types but not the type
itself. And as you may expect, changing the names will change the URL
segment accordingly.
Four of those six types can have child-page(s), multi-level (nested).
Here are some examples of what the default app's URLs can look like:
mydomain.com/homepage
mydomain.com/content/
mydomain.com/events/by-location/[locationID]
mydomain.com/events/[eventID]
mydomain.com/events/by-category/[catLevelOne]
mydomain.com/user/profile
mydomain.com/blog/[postID]
mydomain.com/search?term=searchterm
mydomain.com/contact-us
Notice: there is also a static page "contact-us" which is not connected to the CMS.
To achieve this model within the NextJS methodology of routing, the app file structure should look like this (if it is allowed):
pages
├── [blog]
│ ├── [postID].js
│ └── index.js
├── [content]
│ ├── [levelOne]
│ │ ├── [levelTwo]
│ │ │ ├── [levelThree]
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ └── index.js
│ └── index.js
├── [events]
│ ├── by-category
│ │ ├── [catLevelOne]
│ │ │ ├── [catLevelTwo]
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ └── index.js
│ ├── by-location
│ │ ├── [location]
│ │ │ ├── [locationID].js
│ │ │ └── index.js
│ │ └── index.js
│ ├── index.js
│ └── [eventID].js
├── [user]
│ ├── account.js
│ ├── emailverification.js
│ ├── password.js
│ └── register.js
├── search.js
└── homepage.js
And this is not possible as we cannot have two folders with brackets on the same level!
If I hard-code file names of the top-level pages, they worked just fine, however, the problem starts when the user changes their default names (homepage, content, events, ...etc) into something else, NextJS then will have no idea what the pages' structure is yet so it through a 404 not found straight away, as getting the file structure from the API will take few seconds to fetch.
What I have tried:
middleware: it turned out that we can't fetch data inside middleware.js and if we did, there will be tens of API calls each time the route changes.
I tried the one dynamic route method, so I fetched the data server-side inside a [wildcard].js file and then based on the data that came back I rewrote the URL to route the requests in the right direction based on the pages types, which is basically the hard-coded page names. That works smoothly but for the top pages not for their children.
I know I am late to the party but in case someone still needs this, I think you were very close. Using shallow-routing with your second approach should do the job. Basically add [...wildcard].js and
based on the data that comes back, rewrote the URL to route the requests in the right direction based on the pages types
A good idea would be to do this in the getServerSideProps function since you can make requests there, it will be faster, and you don't have to worry about any glitch when the page loads.
Also in case anyone has any doubts:
Of course we can't have two folders with brackets on the same level because if you have [id1] and [id2] how will the nextJS know what mydomain.com/1234 should be? There is now way to tell if 1234 is id1 or id2.
I think the last part is probably obvious, but still... In case anyone wonders.

How to serve a file for any matching GET request with warp?

I am using React in the frontend development and doing client-side routing with react-router. While intergating with my warp backend, I have come across some obstacles.
After building the React app with npm run build, I move the build folder to my Rust project. According to create-react-app documentation. I need to serve build folder and serve the index.html file for any matching GET request. I could not achieve this in warp like the express example in the documentation.
Here is the build folder example.
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── robots.txt
└── static
├── css
│   ├── main.089e2544.css
│   └── main.089e2544.css.map
└── js
├── main.ba6a006a.js
├── main.ba6a006a.js.LICENSE.txt
└── main.ba6a006a.js.map
3 directories, 10 files
Here is index.html line where includes the script.
<script defer="defer" src="/static/js/main.ba6a006a.js"></script>
Using warp::fs::dir("build") was enough to see main page since it includes index.html file in the background. But if I to manually type URL for example 127.0.0.1:8080/login and press enter it does not process the request.
The way to implement a "fallback" is to simply use .or() which will attempt to use the next filter if the one before didn't match. So if the required behavior is to serve from the "build" directory or else serve "build/index.html", that can be done like this:
use warp::Filter;
#[tokio::main]
async fn main() {
let routes = warp::filters::fs::dir("build")
.or(warp::filters::fs::file("build/index.html"));
warp::serve(routes)
.run(([127, 0, 0, 1], 8080))
.await;
}

Disable Specific Paths for Next.JS File System Routing [duplicate]

There are SSR-related problems with several pages in Next.js project that results in errors on npm run build and prevent the project from being built:
pages/
foo/
bar/
[id].jsx
index.jsx
index.jsx
...
For example, bar:
export function getStaticProps() {
return someApiCallThatCurrentlyFails()
...
}
export default function Bar() {...}
As a quick fix, it may be convenient to just not build bar/*.* pages and make routes unavailable.
Can pages be ignored on Next.js build without physically changing or removing page component files in the project?
You can configure the pageExtensions in the next.config.js.
// next.config.js
module.exports = {
pageExtensions: ["page.js"],
}
After configuring this, the only pages with *.page.js will be considered in the below given directory structure.
pages/
├── user
│ └── setting
│ ├── index.js
├── _app.page.js
├── _document.page.js
├── list.page.js
└── theme.ts
Custom file ignores patterns that are not supported yet. You can visit the PR created here, and the solution given here. This is the most satisfactory solution so far.
#Mathilda Here from Nextjs docs: it's necessary for all pages including _app, _document, etc.
https://nextjs.org/docs/api-reference/next.config.js/custom-page-extensions
Changing these values affects all Next.js pages, including the following:
- middleware.js
- pages/_document.js
- pages/_app.js
- pages/api/
For example, if you reconfigure .ts page extensions to .page.ts, you would need to rename pages like _app.page.ts.

What is the right way to incude Sass in NextJs?

When I use Sass files in NextJs, I am getting 'conflicting order' warnigs from mini-css-extract-plugin. The conflict always messes up my stylings on build. You can see the error described in the following link:
https://medium.com/iryl/control-css-imports-order-for-next-js-webpack-based-production-applications-3b69765444fd
This is an article with a solution to this issue but it talks about ordering Sass files for only one page. I'm not sure how to do order when there are multiple pages. How can I tackle the conflicting order issue?
if you are using nextjs 9.3 or higher you can use it like css modules. At least this is how they recommend that you do it.
This is an example.
You can also check the Sass support on the Next.js docs.
-- Update
The best way of do it it's by creating a different scss module for each component. It will look something like this.
Components
├── Header
│ ├── Header.js
│ ├── Header.module.css
├── Footer
│ ├── Footer.js
│ ├── Footer.module.css
├── Nav
│ ├── Nav.js
│ ├── Nav.module.css
The main idea of using css modules it's to prevent you from use a global sheet. this way the css will be optimized on the code splitting by components and you don't have to worry about declaring the same class twice, each css module file will generate a unique class name.
I'm working on a project using css modules, the project isn't done yet but the file structure it's almost the same working with sass, you can give it a look if you want.
https://github.com/edgarlr/portfolio/tree/main/components

How to set up a chrome extension using React and TypeScript with multiple pages and entry points?

There are plenty of questions and tutorials on this topic, but none of them cover all use cases for a chrome extension, because most of them assume there's only one entry point.
Here are the requisites:
Multiple "single page applications":
1) popup.html for the extension pop up page
2) options.html for the options page
3) custom.html this is a custom .html file that the extension can refer to "locally"
Each of these files are entry points for React to manipulate the DOM, but they behave independently of each other.
Non React TypeScript files
They must not be bundled together with any other scripts, and gets compiled to its own JavaScript file, for example a background.ts that compiles to background.js (which is refered to in the manifest.json).
I assume this is doable with TypeScript, React and Webpack but I'm not sure how to approach that.
There is a custom CRA template that exactly fits your needs: complex-browserext-typescript.
Usage:
npx create-react-app my-app --template complex-browserext-typescript
By default it sets up 4 entry points associated with page-like extension components:
popup (src/index.tsx) - extension's popup page, replaces the
default index entry point.
options (src/options.tsx) - extension's options page.
background (src/background.ts) - background script.
content (src/content.ts) - content script.
However there is an option to exclude any of the above components except the popup from compilation as well as add extra HTML page(s).
Also see this article for usage example.
I found a solution but it was not using create-react-app and webpack. It looks like parcel supports multiple entry points out of the box without any configuration.
Assuming a directory structure like this:
├── chrome
│   └── background.ts
├── html
│   ├── custom.html
│   ├── options.html
│   └── popup.html
├── manifest.json
├── package.json
├── react
│   ├── custom.tsx
│   ├── options.tsx
│   └── popup.tsx
With Parcel.js you simply do:
parcel build html/*.html react/*.tsx chrome/*.ts
And it will handle the multiple entry points. I created a repository that contains a template for that approach, it contains a fully runnable example.

Resources