From 1b71b472a7334414d593735f638847141c09cfde Mon Sep 17 00:00:00 2001 From: vaporvee Date: Thu, 24 Jul 2025 01:20:02 +0200 Subject: [PATCH] =?UTF-8?q?template=20setup=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 38 + .npmrc | 0 README.md | 159 + apps/client/.gitignore | 41 + apps/client/README.md | 36 + apps/client/components.json | 21 + apps/client/next.config.ts | 34 + apps/client/package.json | 45 + apps/client/postcss.config.mjs | 5 + apps/client/public/manifest.webmanifest | 14 + apps/client/src/app/[slug]/page.tsx | 92 + apps/client/src/app/actions.ts | 10 + .../src/app/api/draft-mode/enable/route.ts | 9 + apps/client/src/app/globals.css | 104 + apps/client/src/app/layout.tsx | 61 + apps/client/src/app/page.tsx | 26 + apps/client/src/components/ColorTest.tsx | 30 + apps/client/src/components/footer.tsx | 15 + apps/client/src/components/link-button.tsx | 87 + apps/client/src/components/sanity-block.tsx | 243 ++ apps/client/src/components/section/cta.tsx | 126 + apps/client/src/components/ui/button.tsx | 66 + apps/client/src/lib/asset-to-url.ts | 54 + apps/client/src/lib/image-url.ts | 85 + apps/client/src/lib/link-client.ts | 51 + apps/client/src/lib/link-helper.ts | 62 + apps/client/src/lib/utils.ts | 6 + apps/client/src/sanity/client.ts | 14 + apps/client/src/sanity/live.ts | 9 + apps/client/src/sanity/sanity.types.ts | 512 +++ apps/client/src/sanity/settings.ts | 18 + apps/client/tailwind.config.ts | 3 + apps/client/tsconfig.json | 20 + apps/studio/.gitignore | 29 + apps/studio/README.md | 11 + apps/studio/components/TextAlignComponent.tsx | 21 + .../components/icons/alignment-center.tsx | 11 + .../components/icons/alignment-left.tsx | 11 + .../components/icons/alignment-right.tsx | 11 + apps/studio/eslint.config.mjs | 3 + apps/studio/example.env | 1 + apps/studio/lib/colorUtils.ts | 18 + apps/studio/package.json | 45 + apps/studio/sanity-typegen.json | 4 + apps/studio/sanity.cli.ts | 15 + apps/studio/sanity.config.ts | 65 + apps/studio/schema.json | 3133 ++++++++++++++++ apps/studio/schemaTypes/blockContent.ts | 89 + apps/studio/schemaTypes/index.ts | 15 + apps/studio/schemaTypes/objects/button.ts | 33 + apps/studio/schemaTypes/objects/faq.ts | 34 + .../schemaTypes/objects/imageWithAlt.ts | 20 + apps/studio/schemaTypes/objects/index.ts | 3 + apps/studio/schemaTypes/pages/custom.ts | 36 + apps/studio/schemaTypes/pages/home.ts | 33 + apps/studio/schemaTypes/pages/index.ts | 3 + apps/studio/schemaTypes/sections/contact.ts | 71 + apps/studio/schemaTypes/sections/cta.ts | 49 + apps/studio/schemaTypes/sections/faq.ts | 45 + apps/studio/schemaTypes/sections/index.ts | 3 + apps/studio/schemaTypes/settings.ts | 44 + apps/studio/static/manifest.webmanifest | 14 + apps/studio/tsconfig.json | 17 + bun.lock | 3277 +++++++++++++++++ package.json | 26 + packages/sanity-connection/index.ts | 9 + packages/sanity-connection/package.json | 11 + packages/sanity-connection/tsconfig.json | 27 + packages/typescript-config/base.json | 22 + packages/typescript-config/nextjs.json | 14 + packages/typescript-config/package.json | 9 + packages/typescript-config/react-library.json | 7 + packages/ui/package.json | 27 + packages/ui/src/brand-colors.ts | 16 + packages/ui/src/components/logo.tsx | 7 + packages/ui/src/index.ts | 4 + packages/ui/src/primitives.ts | 57 + packages/ui/src/tailwind.config.ts | 27 + packages/ui/src/variables.ts | 14 + packages/ui/tsconfig.json | 12 + turbo.json | 37 + 81 files changed, 9586 insertions(+) create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 README.md create mode 100644 apps/client/.gitignore create mode 100644 apps/client/README.md create mode 100644 apps/client/components.json create mode 100644 apps/client/next.config.ts create mode 100644 apps/client/package.json create mode 100644 apps/client/postcss.config.mjs create mode 100644 apps/client/public/manifest.webmanifest create mode 100644 apps/client/src/app/[slug]/page.tsx create mode 100644 apps/client/src/app/actions.ts create mode 100644 apps/client/src/app/api/draft-mode/enable/route.ts create mode 100644 apps/client/src/app/globals.css create mode 100644 apps/client/src/app/layout.tsx create mode 100644 apps/client/src/app/page.tsx create mode 100644 apps/client/src/components/ColorTest.tsx create mode 100644 apps/client/src/components/footer.tsx create mode 100644 apps/client/src/components/link-button.tsx create mode 100644 apps/client/src/components/sanity-block.tsx create mode 100644 apps/client/src/components/section/cta.tsx create mode 100644 apps/client/src/components/ui/button.tsx create mode 100644 apps/client/src/lib/asset-to-url.ts create mode 100644 apps/client/src/lib/image-url.ts create mode 100644 apps/client/src/lib/link-client.ts create mode 100644 apps/client/src/lib/link-helper.ts create mode 100644 apps/client/src/lib/utils.ts create mode 100644 apps/client/src/sanity/client.ts create mode 100644 apps/client/src/sanity/live.ts create mode 100644 apps/client/src/sanity/sanity.types.ts create mode 100644 apps/client/src/sanity/settings.ts create mode 100644 apps/client/tailwind.config.ts create mode 100644 apps/client/tsconfig.json create mode 100644 apps/studio/.gitignore create mode 100644 apps/studio/README.md create mode 100644 apps/studio/components/TextAlignComponent.tsx create mode 100644 apps/studio/components/icons/alignment-center.tsx create mode 100644 apps/studio/components/icons/alignment-left.tsx create mode 100644 apps/studio/components/icons/alignment-right.tsx create mode 100644 apps/studio/eslint.config.mjs create mode 100644 apps/studio/example.env create mode 100644 apps/studio/lib/colorUtils.ts create mode 100644 apps/studio/package.json create mode 100644 apps/studio/sanity-typegen.json create mode 100644 apps/studio/sanity.cli.ts create mode 100644 apps/studio/sanity.config.ts create mode 100644 apps/studio/schema.json create mode 100644 apps/studio/schemaTypes/blockContent.ts create mode 100644 apps/studio/schemaTypes/index.ts create mode 100644 apps/studio/schemaTypes/objects/button.ts create mode 100644 apps/studio/schemaTypes/objects/faq.ts create mode 100644 apps/studio/schemaTypes/objects/imageWithAlt.ts create mode 100644 apps/studio/schemaTypes/objects/index.ts create mode 100644 apps/studio/schemaTypes/pages/custom.ts create mode 100644 apps/studio/schemaTypes/pages/home.ts create mode 100644 apps/studio/schemaTypes/pages/index.ts create mode 100644 apps/studio/schemaTypes/sections/contact.ts create mode 100644 apps/studio/schemaTypes/sections/cta.ts create mode 100644 apps/studio/schemaTypes/sections/faq.ts create mode 100644 apps/studio/schemaTypes/sections/index.ts create mode 100644 apps/studio/schemaTypes/settings.ts create mode 100644 apps/studio/static/manifest.webmanifest create mode 100644 apps/studio/tsconfig.json create mode 100644 bun.lock create mode 100644 package.json create mode 100644 packages/sanity-connection/index.ts create mode 100644 packages/sanity-connection/package.json create mode 100644 packages/sanity-connection/tsconfig.json create mode 100644 packages/typescript-config/base.json create mode 100644 packages/typescript-config/nextjs.json create mode 100644 packages/typescript-config/package.json create mode 100644 packages/typescript-config/react-library.json create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/brand-colors.ts create mode 100644 packages/ui/src/components/logo.tsx create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/primitives.ts create mode 100644 packages/ui/src/tailwind.config.ts create mode 100644 packages/ui/src/variables.ts create mode 100644 packages/ui/tsconfig.json create mode 100644 turbo.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96fab4f --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies +node_modules +.pnp +.pnp.js + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc +.DS_Store +*.pem diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..b57b02e --- /dev/null +++ b/README.md @@ -0,0 +1,159 @@ + + +# ✨ Lumify Sanity Template + +Modern web template for Next.js, Sanity Studio, and Bun, with monorepo structure and reusable UI components. 🚀 + +--- + + +## 🧩 Features + +- ⚡ **Next.js** (App Router, TypeScript, Tailwind CSS) +- 📝 **Sanity Studio** (custom schemas, live preview, type generation) +- 🏗️ **Monorepo** (TurboRepo, packages for UI and Sanity connection) +- 🎨 **Reusable UI components** + +--- + + +## 🗂️ Project Structure + +``` +apps/ + client/ # Next.js frontend app + src/ + app/ # App router pages & layouts + components/ # React UI components + lib/ # Utility functions + public/ # Static assets + studio/ # Sanity Studio (CMS) +packages/ + sanity-connection/ # Shared Sanity config/utilities + typescript-config/ # Shared tsconfig presets + ui/ # Shared UI components +``` + +--- + + +## 🏁 Getting Started + + +### 1️⃣ Sanity Project Setup + +1. Create a new project at [sanity.io](https://www.sanity.io/) +2. Copy your **Project ID** for later +3. In Sanity, set up the following CORS origins: + + | URL | Status | + |-------------------------------|-------------| + | https://example.vercel.app | Not Allowed | + | http://localhost:3000 | Not Allowed | + | https://*.api.sanity.io | Not Allowed | + | wss://*.api.sanity.io | Not Allowed | + | https://example.sanity.studio | Allowed | + | http://localhost:3333 | Allowed | + +4. Create a **token** with `Viewer` permissions (for live preview): + + | Name | Permissions | + |----------------------------------------|-------------| + | Main Token (Copy it for the next step) | Viewer | + + +### 2️⃣ Configure the Repo + +Edit `packages/sanity-connection/index.ts` and fill in: + +1. `pageTitle` – Name for your Sanity Studio +2. `publicViewerToken` – The token from above +3. `studioHost` – Lowercase, no special chars (e.g. `myproject`) +4. `studioUrl` – `https://.sanity.studio` +5. `projectId` – From Sanity project settings +6. `previewUrl` – Your website URL (`http://localhost:3000` for local dev) + +--- + + +## 💻 Local Development + + +Install dependencies (from the root): + +```sh +bun install +``` + + +Start all apps (Next.js and Sanity Studio) in parallel from the root: + +```sh +bun run dev +``` + + +✨ You do not need to `cd` into any subdirectory—TurboRepo will handle running the correct scripts in each package/app. + +--- + + +## 🛠️ Useful Scripts + +| Script | Description | +|--------------------|------------------------------------| +| bun run dev | Start dev server (client/studio) | +| bun run build | Build app/studio | +| bun run deploy | Deploy Sanity Studio | +| bun run generate | Generate Sanity types | + +--- + + +## 🚢 Deployment + +To deploy Sanity Studio: + +```sh +bun run deploy +``` + +--- + + +## 🧬 Type Generation + +To generate types from your Sanity schemas: + +```sh +bun run generate +``` + +--- + +on github + +## 🚀 Use This Template + +Easily kickstart your own project with this template on GitHub: + +1. ⭐️ **Go to the repository page on GitHub.** +2. ⤴️ Click the **"Use this template"** button (top right) and select **"Create a new repository"**. +3. 📝 Fill in your new repository details and click **"Create repository from template"**. +4. ⬇️ Clone your new repository: + + ```sh + git clone https://github.com/your-username/your-repo-name.git + cd your-repo-name + ``` + +5. 📦 Install dependencies and start development: + + ```sh + bun install + bun run dev + ``` + +6. 🛠️ Follow the [Getting Started](#getting-started) steps above to configure your Sanity project and environment. + +Happy building! 🎉 \ No newline at end of file diff --git a/apps/client/.gitignore b/apps/client/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/apps/client/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/apps/client/README.md b/apps/client/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/apps/client/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/apps/client/components.json b/apps/client/components.json new file mode 100644 index 0000000..0e8b633 --- /dev/null +++ b/apps/client/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/apps/client/next.config.ts b/apps/client/next.config.ts new file mode 100644 index 0000000..c35e632 --- /dev/null +++ b/apps/client/next.config.ts @@ -0,0 +1,34 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + eslint: { ignoreDuringBuilds: true }, + images: { + remotePatterns: [ + { + hostname: "cdn.sanity.io", + pathname: "/images/**", + protocol: "https", + }, + { + hostname: "lh3.googleusercontent.com", + pathname: "**", + protocol: "https", + }, + ], + }, + headers: async () => { + return [ + { + source: "/:path*", + headers: [ + { + key: "X-Frame-Options", + value: "ALLOWALL", + }, + ], + }, + ]; + }, +}; + +export default nextConfig; diff --git a/apps/client/package.json b/apps/client/package.json new file mode 100644 index 0000000..4aecba1 --- /dev/null +++ b/apps/client/package.json @@ -0,0 +1,45 @@ +{ + "name": "client", + "version": "0.1.0", + "private": true, + "engines": { + "bun": ">=1.2.12" + }, + "type": "module", + "packageManager": "bun@1.2.12", + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@radix-ui/react-accordion": "^1.2.11", + "@radix-ui/react-slot": "^1.2.3", + "@repo/sanity-connection": "*", + "@repo/ui": "*", + "@sanity/client": "^7.6.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.6", + "lucide-react": "^0.525.0", + "next": "15.3.5", + "next-sanity": "^9.12.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.3.1" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@repo/typescript-config": "*", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "15.3.5", + "tailwindcss": "^4", + "tw-animate-css": "^1.3.5", + "typescript": "^5" + } +} diff --git a/apps/client/postcss.config.mjs b/apps/client/postcss.config.mjs new file mode 100644 index 0000000..c7bcb4b --- /dev/null +++ b/apps/client/postcss.config.mjs @@ -0,0 +1,5 @@ +const config = { + plugins: ["@tailwindcss/postcss"], +}; + +export default config; diff --git a/apps/client/public/manifest.webmanifest b/apps/client/public/manifest.webmanifest new file mode 100644 index 0000000..edcd510 --- /dev/null +++ b/apps/client/public/manifest.webmanifest @@ -0,0 +1,14 @@ +{ + "icons": [ + { + "src": "/favicon-192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "/favicon-512.png", + "type": "image/png", + "sizes": "512x512" + } + ] +} \ No newline at end of file diff --git a/apps/client/src/app/[slug]/page.tsx b/apps/client/src/app/[slug]/page.tsx new file mode 100644 index 0000000..f3a73e5 --- /dev/null +++ b/apps/client/src/app/[slug]/page.tsx @@ -0,0 +1,92 @@ +import { defineQuery } from "next-sanity"; +import { sanityFetch } from "@/sanity/live"; +import type { Custom } from "@/sanity/sanity.types"; +import type { Metadata } from "next"; +import SanityBlock from "@/components/sanity-block"; +import { notFound } from "next/navigation"; +import { fetchSettings } from "@/sanity/settings"; + +const CUSTOMS_QUERY = defineQuery(`*[_type == "custom"]{ slug }`); +const CUSTOM_QUERY = defineQuery( + `*[_type == "custom" && slug.current == $slug][0]`, +); + +type PageParams = Promise<{ + slug: string; +}>; + +export async function generateStaticParams() { + const customs: Custom[] = ( + await sanityFetch({ + query: CUSTOMS_QUERY, + stega: false, + perspective: "published", + }) + ).data; + return customs.map((custom) => ({ + slug: custom.slug?.current ?? "", + })); +} + +export async function generateMetadata(props: { + params: Promise; +}): Promise { + const params = await props.params; + if (!params.slug) { + return notFound(); + } + const settings: { title: string } = await fetchSettings("title"); + const custom: Custom = ( + await sanityFetch({ + query: CUSTOM_QUERY, + params, + stega: false, + perspective: "published", + }) + ).data; + const firstBlock = custom?.body ? custom.body[0] : undefined; + let description: string | undefined = undefined; + if (firstBlock && firstBlock._type === "block" && firstBlock.children) { + description = firstBlock.children.map((child) => child.text).join(" "); + } + + const firstWord = custom.title ? custom.title.split(" ")[0] : ""; + return { + title: `${firstWord} | ${settings.title}`, + description, + openGraph: { + title: `${firstWord} | ${settings.title}`, + description, + type: "article", + url: `/${custom.slug}`, + }, + twitter: { + card: "summary_large_image", + title: `${firstWord} | ${settings.title}`, + description, + }, + }; +} + +export default async function CustomPage(props: { + params: Promise; +}) { + const params = await props.params; + const custom: Custom = (await sanityFetch({ query: CUSTOM_QUERY, params })) + .data; + if (!custom) { + return notFound(); + } + + return ( +
+

{custom.title}

+
+ {custom.body && } +
+
+ ); +} diff --git a/apps/client/src/app/actions.ts b/apps/client/src/app/actions.ts new file mode 100644 index 0000000..f6b2d31 --- /dev/null +++ b/apps/client/src/app/actions.ts @@ -0,0 +1,10 @@ +'use server' + +import {draftMode} from 'next/headers' + +export async function disableDraftMode() { + const disable = (await draftMode()).disable() + const delay = new Promise((resolve) => setTimeout(resolve, 1000)) + + await Promise.allSettled([disable, delay]); +} \ No newline at end of file diff --git a/apps/client/src/app/api/draft-mode/enable/route.ts b/apps/client/src/app/api/draft-mode/enable/route.ts new file mode 100644 index 0000000..cce77de --- /dev/null +++ b/apps/client/src/app/api/draft-mode/enable/route.ts @@ -0,0 +1,9 @@ +import { client } from "@/sanity/client"; +import { sanityConnection } from "@repo/sanity-connection"; +import { defineEnableDraftMode } from "next-sanity/draft-mode"; + +export const { GET } = defineEnableDraftMode({ + client: client.withConfig({ + token: sanityConnection.publicViewerToken, + }), +}); \ No newline at end of file diff --git a/apps/client/src/app/globals.css b/apps/client/src/app/globals.css new file mode 100644 index 0000000..04093d4 --- /dev/null +++ b/apps/client/src/app/globals.css @@ -0,0 +1,104 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +@config "../../tailwind.config.ts"; + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--bg-primary); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply font-sans bg-background text-foreground text-lg; + } + h1, h2, h3, h4, h5, h6 { + @apply font-serif; + } + + h1 { + @apply text-4xl md:text-6xl uppercase font-bold; + } + + h2 { + @apply text-3xl font-bold; + } + + h3 { + @apply text-xl; + } + h4 { + @apply text-lg; + } +} diff --git a/apps/client/src/app/layout.tsx b/apps/client/src/app/layout.tsx new file mode 100644 index 0000000..a25ba8e --- /dev/null +++ b/apps/client/src/app/layout.tsx @@ -0,0 +1,61 @@ +import type { Metadata } from "next"; +import { Geist, Noto_Sans } from "next/font/google"; +import "./globals.css"; +import { VisualEditing } from "next-sanity"; +import { draftMode } from "next/headers"; +import { SanityLive } from "@/sanity/live"; +import { fetchSettings } from "@/sanity/settings"; +import { getImage } from "@/lib/asset-to-url"; +import Footer from "@/components/footer"; + +const sans = Geist({ + variable: "--font-sans", + subsets: ["latin"], +}); + +export async function generateMetadata(): Promise { + const settings = await fetchSettings(); + const logo = await getImage(settings?.logo?.asset?._ref); + + return { + title: settings.title, + description: settings.description, + openGraph: { + title: settings.longTitle, + description: settings.description + }, + twitter: { + title: settings.longTitle, + description: settings.description, + }, + robots: { + index: true, + follow: true, + }, + icons: { + icon: logo.url, + apple: logo.url, + }, + manifest: "/manifest.webmanifest", + }; +} + +export default async function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const settings = await fetchSettings(); + return ( + + + {children} +