diff --git a/src/app/(landing)/page.tsx b/src/app/(landing)/page.tsx new file mode 100644 index 0000000..3e7ca56 --- /dev/null +++ b/src/app/(landing)/page.tsx @@ -0,0 +1,15 @@ +import Landing from "@models/landing"; + +import { readLandingJson } from "@utils/landing"; + +const getLanding = async (): Promise => { + return await readLandingJson(); +}; + +export default async function Page() { + const landing = await getLanding(); + + return
{/* */}
; +} + +export const revalidate = 3600; diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..dd187fb --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,30 @@ +"use client"; + +import { Link, Spacer } from "@nextui-org/react"; + +// Error components must be Client Components +import { useEffect } from "react"; + +export default function Error({ + error, + reset +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + console.error(error); + }, [error]); + + return ( +
+

Something went loading the page!

+

{error.toString()}

+
+ reset()}> + Try again + +
+
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index 9a2cb7d..0000000 --- a/src/app/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -"use client"; - -import { Button } from "@nextui-org/react"; - -export default function Page() { - return ( -
- -
- ); -} diff --git a/src/models/landing.ts b/src/models/landing.ts new file mode 100644 index 0000000..26a5af7 --- /dev/null +++ b/src/models/landing.ts @@ -0,0 +1,11 @@ +import z from "zod"; + +import { OwnerModel } from "./owner"; + +export const LandingModel = z.object({ + owner: OwnerModel +}); + +export type Landing = z.infer; + +export default Landing; diff --git a/src/models/owner.ts b/src/models/owner.ts new file mode 100644 index 0000000..16e3ba3 --- /dev/null +++ b/src/models/owner.ts @@ -0,0 +1,17 @@ +import z from "zod"; + +export const OwnerModel = z.object({ + fullName: z.string(), + name: z.string(), + description: z.string(), + avatar: z.string().optional(), + contact: z.object({ + email: z.string().email(), + linkedin: z.string().url(), + git: z.string().url() + }) +}); + +export type Owner = z.infer; + +export default Owner; diff --git a/src/styles/global.scss b/src/styles/global.scss index bd6213e..70614c1 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -1,3 +1,25 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; + +.container { + display: flex; + min-width: 100%; + flex-direction: column; + justify-content: center; + + @media screen and (width >=600px) { + padding-right: 1rem; + padding-left: 1rem; + } + + @media screen and (width >=800px) { + padding-right: 4rem; + padding-left: 4rem; + } + + @media screen and (width >=1200px) { + padding-right: 16rem; + padding-left: 16rem; + } +} \ No newline at end of file diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..02edaa3 --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,2 @@ +export const landingJsonLocation = + process.env.LANDING_JSON_LOCATION ?? "/app/landing.json"; diff --git a/src/utils/fileExists.ts b/src/utils/fileExists.ts new file mode 100644 index 0000000..72446db --- /dev/null +++ b/src/utils/fileExists.ts @@ -0,0 +1,9 @@ +import { stat } from "fs-extra"; + +const fileExists = async (fileName: string): Promise => { + return await stat(fileName) + .then(() => true) + .catch(() => false); +}; + +export default fileExists; diff --git a/src/utils/landing.ts b/src/utils/landing.ts new file mode 100644 index 0000000..510a5f5 --- /dev/null +++ b/src/utils/landing.ts @@ -0,0 +1,25 @@ +import { readJson } from "fs-extra"; + +import Landing, { LandingModel } from "@models/landing"; + +import { landingJsonLocation } from "@utils/constants"; +import exists from "@utils/fileExists"; + +export const readLandingJson = async (): Promise => { + const location = landingJsonLocation; + + const fileExists = await exists(location); + + if (!fileExists) { + throw new Error(`Could not find landing json file at: ${location}`); + } + + const rawJson: unknown = await readJson(location); + + const landingResult = LandingModel.safeParse(rawJson); + + if (!landingResult.success) + throw new Error(`Failed to parse landing json: ${landingResult.error}`); + + return landingResult.data; +};