In this article, we will review the Docmost client file structure. This project’s frontend is built using React + Vite and has a monorepo architecture setup using NX.
We will be focusing on the client:
client
client folder contains the frontend code for the Docmost. It uses Mantine components.
Let’s pick a route and study how the files are organized in order to render that page in react.
We will focus on:
Components structure
API Layer
Page.tsx
I picked page route, this is the page that renders the editor as shown in the below image. I logged in Docmost cloud version and was on free trial at the time of writing this article.
How to locate this page in the client? I would start at the URL — https://myworkspace-665.docmost.com/s/general/p/home-page-t7i4wXav8l and check the routes configured in the client.
I found this in App.tsx L54 — L68.
<Route path={"/p/:pageSlug"} element={<PageRedirect />} />
<Route element={<Layout />}>
<Route path={"/home"} element={<Home />} />
<Route path={"/s/:spaceSlug"} element={<SpaceHome />} />
<Route
path={"/s/:spaceSlug/p/:pageSlug"}
element={
<ErrorBoundary
fallback={<>{t("Failed to load page. An error occurred.")}</>}
>
<Page />
</ErrorBoundary>
}
/>
The route — /s/general/p/home-page-t7i4wXav8l this translates to s/:spaceSlug/p/:pageSlug.
I am suprised there is no lazy loading in App.tsx, I did create an issue suggesting this — Issue #1037
Page is imported from page/page.tsx.
Components structure
<div>
<Helmet>
<title>{`${page?.icon || ""} ${page?.title || t("untitled")}`}</title>
</Helmet>
<PageHeader
readOnly={spaceAbility.cannot(
SpaceCaslAction.Manage,
SpaceCaslSubject.Page,
)}
/>
<FullEditor
key={page.id}
pageId={page.id}
title={page.title}
content={page.content}
slugId={page.slugId}
spaceSlug={page?.space?.slug}
editable={spaceAbility.can(
SpaceCaslAction.Manage,
SpaceCaslSubject.Page,
)}
/>
<HistoryModal pageId={page.id} />
</div>
These are the components rendered in the page.tsx
Helmet
Helmet is imported as shown below:
import { Helmet } from "react-helmet-async"
PageHeader
PageHeader is imported as shown below:
import PageHeader from "@/features/page/components/header/page-header.tsx";
FullEditor
FullEditor is imported as shown below:
import { FullEditor } from "@/features/editor/full-editor";
HistoryModal
HistoryModal is imported as shown below:
import HistoryModal from "@/features/page-history/components/history-modal";
API Layer
In this page.tsx, the following code snippet is found at L17–28
const { t } = useTranslation();
const { pageSlug } = useParams();
const {
data: page,
isLoading,
isError,
error,
} = usePageQuery({ pageId: extractPageSlugId(pageSlug) });
const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug);
const spaceRules = space?.membership?.permissions;
const spaceAbility = useSpaceAbility(spaceRules);
usePageQuery
usePageQuery
is imported as shown below:
import { usePageQuery } from "@/features/page/queries/page-query";
useGetSpaceBySlugQuery
useGetSpaceBySlugQuery
is imported as shown below:
import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts";
About me:
Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.
I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com
My Github — https://github.com/ramu-narasinga
My website — https://ramunarasinga.com
My Youtube channel — https://www.youtube.com/@ramu-narasinga
Learning platform — https://thinkthroo.com
Codebase Architecture — https://app.thinkthroo.com/architecture
Best practices — https://app.thinkthroo.com/best-practices
Production-grade projects — https://app.thinkthroo.com/production-grade-projects
Top comments (0)