A quick introduction to the folders and files in this repo.
Source Organization: src/
To keep things modular, the resources are divided into folders namely /screens, /pages, /components, /actions.
-
/screens: Contains Next.js pages along with their necessary styles and any extra files.- While it's possible to create Next.js pages in
/src/pagesdirectly, several problems occur. Pages are able to import CSS modules like any other component, but CSS cannot be placed in the/src/pagesdirectory. - To work, CSS files must be placed in another directory away from the page, leading to messy code. Similarly, any other files or utils must be placed in a separate directory.
- To fix this, screens are placed in a separate directory from pages, and each in their own directory. This makes it very simple to keep the logic, styles, and utilities for each page in their separate space.
- Each screen behaves as a page, so
getInitialPropsand other Next.js helpers can be used. - Each screen is also passed the prop
currentUser, which is either null or an object containing the user's data from the database. - The one caveat to this is the special SSR functions like
getServerSidePropsandgetStaticPropscan not be called from thescreensdirectory, as they are framework specific topages. The workaround to this is maintaining these initial data calls in apage, and drilling the props down a level toscreens.
- While it's possible to create Next.js pages in
-
/pages: Used for creating file-system routing to screens and creating API routes.- The
/src/pagesdirectory acts as file-system routing for our screens and for API routes. - For regular pages,
importandexport defaultthe screen directly. - External API routes are placed in the src/pages/api directory.
- Every API route must return a HTTP status code and body matching the template:
for successful requests, and:
res.status(201).json({ success: true, payload: ..., })for errors. This makes processing the results much easier.res.status(500).json({ success: false, message: "...", }) - The request body can be accessed with
req.bodyand cookies withreq.cookies.
- Every API route must return a HTTP status code and body matching the template:
- To simplify API routes and promote code reuse, server-side actions are used from the
/server/actionsdirectory.
- The
-
/components: Contains reusable React components.- Each reusable component is placed in this directory with a similar structure to screens.
- Create a directory for each component, and include any necessary styles and utils for this component only in the same directory.
- Each directory must include a
index.jsxfile that imports and export defaults the component. This makes it easier to import the component from/componentDirinstead of/componentDir/component. - Any sub-components that are used by, and only by, this component, should be placed within their own sub-directory within the component's directory.
-
/actions: Contains functions for calling API routes.- Each file in this directory contains multiple functions for interacting with a group of API routes.
- Each function should return a fetch request matching the template:
fetch(urls.baseUrl + urls.api.example, { method: "get", mode: "same-origin", credentials: "include", }) .then((response) => response.json()) .then((json) => { if (json == null) { throw new Error("Could not connect to API!"); } else if (!json.success) { throw new Error(json.message); } return json.payload; }); - IMPORTANT Calling an internal API route while using SSR for initial data fetching is an antipattern. These actions should only be used on the client side.
- Instead, if access to server-side actions are required for SSR initial page load, directly import resolve asynchronous calls from the
/server/actionsdirectory into/src/pages.
- Instead, if access to server-side actions are required for SSR initial page load, directly import resolve asynchronous calls from the
Server Organization: server/
The server directory includes the backend actions used in API routes separated by their type.
-
/mongodb: Contains backend Mongoose models and actions for interacting with MongoDB.- Mongoose models should be placed within the
server/mongodb/modelsdirectory.- The export for each model should follow the template:
export default mongoose.models.User ?? mongoose.model("User", UserSchema);
- The export for each model should follow the template:
- MongoDB (using Mongoose) actions (i.e. queries and operations) should be placed within the
server/mongodb/actionsdirectory.- Each file should use the same name as the model, and include all related actions.
- Each file needs to import
import mongoDB from "../index";, and each function needs to includeawait mongoDB();(once per function) before any interactions are made with the database.
- Mongoose models should be placed within the
Utils Organization: utils/
The utils directory includes any utilities needed for the frontend and backend.
-
urls.js: Exports an object containing the urls for each page and API route.- After creating a page or API route, the path needs to be added to
urls.jsimmediately. - This makes it easy use urls in the project, because the urls object only needs to be imported, and then urls can be changed at a later date without needing to search the code to replace urls as strings.
- Plain strings should NEVER be used to reference pages/API routes, ALWAYS import the urls object.
- If a dynamic route is needed format it as
pageKey: "/somePage/[aKey]"(with the corresponding page route being/pages/somePage/[aKey].jsx), then use theNavLinkcomponent to navigate to this page:<NavLink href={pages.pageKey} hrefParts={{ aKey: 123 }}>Link</NavLink>.
- After creating a page or API route, the path needs to be added to
Public Organization: public/
The public directory hosts any included files on the website.
/public: Files placed in this directory can be accessed atbaseUrl/file. Be VERY careful to not include a file with the same name as a page!/public/static: Files placed in this directory can be accessed atbaseUrl/static/file.
Project Management: .github/
The hidden directory contains the configuration needed for CI/CD through Vercel as well as other GitHub related artifacts.
/.github/pull_request_template.md: A Markdown file that is automatically loaded into a PR./.github/ISSUE_TEMPLATES: Markdown files placed in this directory describe issue templates for the repository. When using your preferred project management system, this may expedite and formalize how issues are created./.github/workflows: GitHub Actions workflows. These are often used for CI/CD. Themain.ymlworkflow that currently exists in this repository is a Vercel actions that creates preview deployments depending on branch.- [https://stackoverflow.com/questions/60507097/is-there-an-overview-of-what-can-go-into-a-github-dot-github-directory](Link to additional items that can be configured in .github)