websites-factory
v0.5.0
Published
Welcome to the **Websites Factory library**.
Downloads
1,335
Maintainers
Readme
Websites Factory library (Beta)
Welcome to the Websites Factory library.
This library aims to generate pages in Next.js from your modules or modules created by the community.
Table of Contents
Getting Started
Requirements
Website Factory is designed to be used with Next.js (App Router) and Tailwind.
Installation
npx websites-factory
This command creates a websites-factory
directory, which will be used to store the modules, themes and the websites-factory-config.json
file. It will also install the Websites Factory library in node_modules
.
Tailwind
Add the path for all modules in tailwind.config.js
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
// Add the path for all websites-factory
"./websites-factory/**/*.{js,ts,jsx,tsx,mdx}",
],
page.js / page.tsx
Replace the code in the page.js or page.tsx file created by Next.js:
import { notFound } from "next/navigation";
import { getPage, PageRenderer } from "websites-factory";
const page = async ({ params }) => {
const pageResult = await getPage(params);
if (!pageResult) {
notFound();
}
return (
<PageRenderer pageResult={pageResult} />
);
};
export default page;
(Beta) Note: The websites-factory-config file in this form is temporary. The idea is to eventually retrieve the configuration from a database. In that case, this will likely be used as the default configuration.
Overview
The modules provide pages and sections to the template of the websites-factory-config.json
file. This allows for the construction of the various pages of the site.
Configuration
The Websites-factory-config
file consists of the list of modules, the template, and the entities.
Modules config
"modules": [
{
"name": "welcome",
"enabled": true
}
]
- Config Coming soon Mapping entities and more?
Template
The template contains all the pages to be generated by Websites Factory in the form of an object, with the page path as the key.
To generate a page
, you must at least specify which page from which module you want to display
"template": {
"/": {
"module": "welcome",
"page": "home",
}
}
- Layout
The page can use a layout
provided by one of the installed modules.
"layout": {
"module": "welcome",
"name": "main"
}
- Sections
The page will display thesections
provided by the various modules.
"sections": [
{
"module": "welcome",
"name": "introduction"
}
]
- Entities
Defines the entities
that will be available on the page.
"entities": [
"websitesFactory"
]
- Metadatada
Creation of metadata. The different texts accept variables in the format {{variable}}. The variables are filled in from the entities available on the page.
"metadata": {
"title": "{{websitesFactory.name}} | Welcome!",
"description": "This is the example homepage of {{websitesFactory.name}}"
}
- SubPage
The
subPage
key allows nesting a subpage within a page. A subpage functions like a top-level page, with its key being the path of the subpage. You can nest as manysubPage
as you like
Note: the entry point "/" corresponds to the site's index page. It does not accept any subPages. The subpages of the index page are the other keys of type entrypoints.
"template": {
"/": {
"module": "welcome",
"page": "home",
},
"hello-world": {
"module": "helloWorld",
"page": "hello",
"subPage": {
"subPage-exemple": {
"module": "welcome",
"page": "home",
}
}
}
}
- Full template exemple
"template": {
"/": {
"module": "welcome",
"page": "home",
"sections": [
{
"module": "welcome",
"name": "introduction"
}
],
"layout": {
"module": "welcome",
"name": "main"
},
"entities": [
"websitesFactory"
],
"metadata": {
"title": "{{websitesFactory.name}} | Welcome!",
"description": "This is the example homepage of {{websitesFactory.name}}"
}
},
"hello-world": {
"module": "helloWorld",
"page": "hello",
"layout": {
"module": "welcome",
"name": "main"
},
"subPage": {
"subPage-exemple": {
"module": "welcome",
"page": "home",
"sections": [
{
"module": "welcome",
"name": "introduction"
}
]
}
}
}
}
Entities
Lists the entities available for the App and their path.
"entities": {
"websitesFactory": "websitesFactory"
}
(Beta) Note: For now, the entities are provided by the entities.json file. Later, they will be fetched via an API. The path will then be the one provided by the API.
Pages
Routing
Website Factory uses the Next.js App Router.
Slug-Page
For dynamic routes, you need to create a [...slug]
folder with a page template.
Page Rendering
Base Page Rendering
import { notFound } from "next/navigation";
import { getPage, PageRenderer } from "websites-factory";
const page = async ({ params }) => {
const pageResult = await getPage(params);
if (!pageResult) {
notFound();
}
return (
<PageRenderer pageResult={pageResult} />
);
};
export default page;
getPage
getPage
returns the elements of a page using the websites-factory-config
. The function takes the params
object from Next.js as a parameter.
Note: For the sake of clarity, it was decided to use the same template for the root page and for all other pages. In reality, for the root page,
params
are not necessary to build it. ⚠️ In the absence ofparams
, the "/" template will always be generated.
If you want to customize the rendering of your page, you can use the elements returned by getPage :
PageComponent
, pageSectionsComponents
, PageLayoutComponent
const { PageComponent, pageSectionsComponents, PageLayoutComponent } = pageResult
return (
<PageLayoutComponent>
<PageComponent>
{
pageSectionsComponents.map((Section, i) => {
if (Section)
return < Section key={i} />
})
}
</PageComponent>
</PageLayoutComponent>
);
PageRenderer
PageRenderer
returns the complete JSX template required by Websites Factory. It requires the result of getPage
as props.
return (
<PageRenderer pageResult={pageResult} />
);
Metadada Rendering
Websites Factory uses the generateMetadata
function and the params
object from Next.js.
import { populateMetadata } from 'websites-factory';
export async function generateMetadata({ params }){
const pageResult = await getPage(params)
if (!pageResult) {
notFound();
}
const populatedMetadata = populateMetadata(pageResult)
return populatedMetadata
}
You can also retrieve the page metadata directly from the result of getPage
:
const { pageMetadata } = pageResult
- populateMetadata
populateMetadata
returns the metadata object populated using websites-factory-config
. It takes as a parameter the result of the getPage
function.
pageEntities
The getPage function also returns entities as instances.
(Beta) Note: This feature is still in development. Currently, an entity instance is composed of the entity name and the findOne function. The idea is that modules will use the mapping in their configuration to match their attributes with those of the page's entities. FindOne retrieves the corresponding entity from
entities.json
const { pageEntities } = pageResult
Modules
Modules should be placed in the websites-factory
folder.
The pages provided by the module should be placed in a pages
folder and a folder named after the page.
The sections provided by the module should be placed in a sections
folder and a folder named after the section.
└──modules
├── welcome
│ ├── pages
│ │ ├── home
│ │ │ └── index.tsx
│ ├── sections
│ │ ├── introduction
│ │ │ └── index.tsx
│ ├── layout
│ │ ├── main
│ │ │ └── index.tsx
Themes
Providers
To use theme management, you need to add the context provider to the pages and provide it with the theme from the configuration.
import { notFound } from "next/navigation";
import { getPage, PageRenderer } from "websites-factory";
import { Providers } from "@/websites-factory/Providers"
const page = async ({ params }) => {
const pageResult = await getPage(params);
if (!pageResult) {
notFound();
}
const { theme } = pageResult
return (
<Providers themeTemplate={theme}>
<PageRenderer pageResult={pageResult} />
</Providers>
);
};
export default page;
UI
Modules can import components from the @/websites-factory/ui
folder.
Example:
import { Button } from "@/websites-factory/ui/button";
UI components can be imported from both server-side and client-side components.
(Beta) Note: ⚠️ Currently, all UI components (even when imported into a server-side component) are imported on the client side. This is due to the use of context in the theme components import. I plan to change this so that components are only loaded on the client side when necessary.
New Theme
To create a theme, you need to copy the default theme from websites-factory/themes
. Only the components provided by the UI are available.