diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 99fe7d0..2dc61be 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,7 @@ jobs: - name: Build landing Docker image run: | docker build --build-arg NEXT_PUBLIC_APP_URL=${{ secrets.NEXT_PUBLIC_APP_URL }} \ + --build-arg NEXT_PUBLIC_GA_ID=G-N8FTR16C4L \ -t markmdev/lingput-landing:${{ github.sha }} \ -t markmdev/lingput-landing \ ./apps/landing diff --git a/apps/frontend/public/apple-touch-icon.png b/apps/frontend/public/apple-touch-icon.png new file mode 100644 index 0000000..7b83c7f Binary files /dev/null and b/apps/frontend/public/apple-touch-icon.png differ diff --git a/apps/frontend/public/favicon-96x96.png b/apps/frontend/public/favicon-96x96.png new file mode 100644 index 0000000..ac6d901 Binary files /dev/null and b/apps/frontend/public/favicon-96x96.png differ diff --git a/apps/frontend/public/favicon.ico b/apps/frontend/public/favicon.ico new file mode 100644 index 0000000..f85cc23 Binary files /dev/null and b/apps/frontend/public/favicon.ico differ diff --git a/apps/frontend/public/favicon.svg b/apps/frontend/public/favicon.svg new file mode 100644 index 0000000..56d4ece --- /dev/null +++ b/apps/frontend/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/frontend/public/site.webmanifest b/apps/frontend/public/site.webmanifest new file mode 100644 index 0000000..8b77109 --- /dev/null +++ b/apps/frontend/public/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "Lingput", + "short_name": "Lingput", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/apps/frontend/public/web-app-manifest-192x192.png b/apps/frontend/public/web-app-manifest-192x192.png new file mode 100644 index 0000000..ad2c57f Binary files /dev/null and b/apps/frontend/public/web-app-manifest-192x192.png differ diff --git a/apps/frontend/public/web-app-manifest-512x512.png b/apps/frontend/public/web-app-manifest-512x512.png new file mode 100644 index 0000000..435a059 Binary files /dev/null and b/apps/frontend/public/web-app-manifest-512x512.png differ diff --git a/apps/frontend/src/app/(unprotected)/login/page.tsx b/apps/frontend/src/app/(unprotected)/login/page.tsx index dc2856f..f80e159 100644 --- a/apps/frontend/src/app/(unprotected)/login/page.tsx +++ b/apps/frontend/src/app/(unprotected)/login/page.tsx @@ -63,6 +63,17 @@ export default function LoginPage() { Sign up

+

+ By logging in, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + + . +

{error?.message}

diff --git a/apps/frontend/src/app/(unprotected)/signup/page.tsx b/apps/frontend/src/app/(unprotected)/signup/page.tsx index 1e93f6a..a6d501d 100644 --- a/apps/frontend/src/app/(unprotected)/signup/page.tsx +++ b/apps/frontend/src/app/(unprotected)/signup/page.tsx @@ -61,6 +61,19 @@ export default function SignupPage() { Log in

+ +

+ By signing up, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + + . +

+

{error?.message}

diff --git a/apps/frontend/src/app/cookie/page.tsx b/apps/frontend/src/app/cookie/page.tsx new file mode 100644 index 0000000..7b7f1a3 --- /dev/null +++ b/apps/frontend/src/app/cookie/page.tsx @@ -0,0 +1,63 @@ +import ReactMarkdown from "react-markdown"; + +export default function TermsPage() { + const content = ` +# Cookie Policy — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. What Are Cookies? + +Cookies are small text files stored on your device when you visit a website. They help websites remember your preferences and improve your browsing experience. Some cookies are essential, while others are optional. + +--- + +## 2. How Lingput Uses Cookies + +We use cookies in the following categories: + +* **Essential cookies (required)** + Needed for core functionality such as login sessions, account security, and remembering your language progress. + These cannot be disabled. + +* **Analytics cookies (optional)** + With your consent, we use Google Analytics 4 (Consent Mode) to understand how users interact with Lingput and to improve the platform. These cookies are only activated if you click **Accept** in the cookie banner. + +* **No advertising cookies** + Lingput does not use advertising, remarketing, or personalization cookies. + +--- + +## 3. Managing Your Cookie Preferences + +* When you first visit Lingput, you can accept or reject analytics cookies via the cookie banner. +* You can change your choice at any time by clicking **Cookie Settings** in the footer. +* You can also delete cookies through your browser settings. + +--- + +## 4. Third-Party Cookies + +Some cookies may be placed by trusted third parties: + +* **Google Analytics (Google LLC, USA)** — analytics cookies (only with your consent). + +--- + +## 5. More Information + +For details on how we handle personal data, see our [Privacy Policy](/privacy). + +If you have questions about this Cookie Policy, contact us at **support@lingput.dev**. + + `; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/frontend/src/app/layout.tsx b/apps/frontend/src/app/layout.tsx index a0064ac..4395785 100644 --- a/apps/frontend/src/app/layout.tsx +++ b/apps/frontend/src/app/layout.tsx @@ -2,9 +2,63 @@ import { ToastContainer } from "react-toastify"; import "react-loading-skeleton/dist/skeleton.css"; import "./globals.css"; import { Inter } from "next/font/google"; +import { Metadata } from "next"; +import CookieBanner from "@/components/CookieBanner"; const inter = Inter({ subsets: ["latin"], display: "swap" }); +export const metadata: Metadata = { + metadataBase: new URL("https://lingput.dev"), + title: "Lingput - Learn German with AI-Generated Stories", + description: + "Learn German with short, AI-generated stories tailored to your vocabulary level. Natural comprehensible input for English speakers with translations, audio, and smart word tracking.", + keywords: [ + "learn german", + "language learning", + "comprehensible input", + "AI stories", + "german for english speakers", + "vocabulary builder", + ], + openGraph: { + title: "Lingput - Learn German with AI-Generated Stories", + description: + "Learn German with short, AI-generated stories tailored to your vocabulary level for English speakers.", + url: "https://lingput.dev", + siteName: "Lingput", + images: [ + { + url: "/logo_min.png", + width: 1024, + height: 366, + alt: "Lingput Logo", + }, + ], + locale: "en_US", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: "Lingput - Learn German with AI-Generated Stories", + description: "Learn German with AI-generated stories tailored to your vocabulary level.", + images: ["/logo_min.png"], + }, + icons: { + icon: [ + { url: "/favicon.ico", sizes: "any" }, + { url: "/favicon.svg", type: "image/svg+xml" }, + ], + apple: [{ url: "/apple-touch-icon.png" }], + }, + manifest: "/site.webmanifest", + authors: [{ name: "Mark Morgan", url: "https://markmdev.com" }], + robots: { + index: true, + follow: true, + nocache: false, + }, +}; + export default function RootLayout({ children, }: Readonly<{ @@ -17,6 +71,7 @@ export default function RootLayout({ > {children} + ); diff --git a/apps/frontend/src/app/privacy/page.tsx b/apps/frontend/src/app/privacy/page.tsx new file mode 100644 index 0000000..7d20e9c --- /dev/null +++ b/apps/frontend/src/app/privacy/page.tsx @@ -0,0 +1,125 @@ +import ReactMarkdown from "react-markdown"; + +export default function PrivacyPage() { + const content = ` +# Privacy Policy — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. Introduction + +Lingput is an AI-powered language learning application. This Privacy Policy explains how we collect, use, and protect your personal data when you use Lingput. + +--- + +## 2. What Data We Collect + +* **Account information**: email address, username, password (hashed). +* **Learning progress**: words, stories, and exercises you complete, your vocabulary history, and session stats. +* **Generated content**: stories, translations, and audio files generated for you by our AI. +* **Technical data**: browser type, IP address, device information, cookies (only with your consent). +* **Payment data**: if applicable, processed securely by third-party payment providers (we do not store your card details). + +--- + +## 3. How We Use Your Data + +* To provide the Lingput service (saving your learning history, generating personalized exercises). +* To improve the platform (analytics, performance monitoring, bug fixing). +* To ensure security (account authentication, fraud prevention). +* To comply with legal obligations (tax, accounting, regulatory compliance). + +We do **not** sell your personal information. + +--- + +## 4. AI-Generated Content + +Lingput uses third-party AI services (e.g., OpenAI APIs) to generate stories, translations, and audio. + +* Your input text may be transmitted to these services to generate the output. +* Data is not used by these providers to train their models (per their policies at the time of writing). +* We only store the outputs relevant to your learning history. + +--- + +## 5. Cookies and Tracking + +Lingput uses cookies only with your consent: + +* **Functional cookies**: required for login and session security. +* **Analytics cookies**: optional, used to understand usage patterns (Google Analytics 4 with Consent Mode). +* **No advertising cookies** are used. + +You can change your cookie preferences anytime via the “Cookie Settings” link. + +--- + +## 6. Data Sharing + +We share data only with trusted providers necessary to operate Lingput: + +* **Hosting & infrastructure**: DigitalOcean, AWS, Supabase, Redis. +* **Analytics**: Google Analytics (if you consent). +* **AI processing**: OpenAI API for text and audio generation. +* **Payments**: Stripe or other payment processors (if you purchase a subscription). + +--- + +## 7. Data Retention + +* Account data is stored until you delete your account. +* Learning history persists while your account is active. +* Analytics data (if enabled) is retained per provider defaults (up to 14 months). +* Server logs are rotated every 30–90 days. + +--- + +## 8. Your Rights + +Depending on your jurisdiction (EU/EEA, UK, California), you may have the right to: + +* Access, correct, or delete your personal data. +* Request export of your data (data portability). +* Withdraw consent for analytics cookies. +* Delete your account at any time. + +To exercise these rights, contact us at **support@lingput.dev**. + +--- + +## 9. Security + +We use HTTPS, hashed passwords, access controls, and monitoring to protect your data. +However, no online service is 100% secure — please use a strong password and keep it private. + +--- + +## 10. Children’s Privacy + +Lingput is not directed to children under 13 (or the age of digital consent in your region). +We do not knowingly collect personal information from children. + +--- + +## 11. Changes + +We may update this Privacy Policy occasionally. Updates will be posted here with a new “Effective date.” + +--- + +## 12. Contact + +For questions, requests, or concerns: +Email: **[support@lingput.dev](mailto:support@lingput.dev)** +`; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/frontend/src/app/terms/page.tsx b/apps/frontend/src/app/terms/page.tsx new file mode 100644 index 0000000..9c918ac --- /dev/null +++ b/apps/frontend/src/app/terms/page.tsx @@ -0,0 +1,112 @@ +import ReactMarkdown from "react-markdown"; + +export default function TermsPage() { + const content = ` +# Terms of Service — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. Acceptance of Terms + +By creating an account or using Lingput, you agree to be bound by these Terms of Service and our [Privacy Policy](/privacy). +If you do not agree, you may not use the Service. + +--- + +## 2. Eligibility + +You must be at least 13 years old (or the age of digital consent in your country) to use Lingput. +By using Lingput, you represent that you meet this requirement. + +--- + +## 3. Accounts + +* You are responsible for maintaining the security of your account and password. +* You must provide accurate information when creating an account. +* You are responsible for all activity that occurs under your account. +* You may delete your account at any time. + +--- + +## 4. Acceptable Use + +You agree **not to**: + +* Use Lingput for unlawful, harmful, or abusive purposes. +* Attempt to disrupt, hack, or overload the Service. +* Upload or generate offensive, discriminatory, or illegal content. + +We reserve the right to suspend or terminate accounts that violate these rules. + +--- + +## 5. Content & Intellectual Property + +* **Your content**: You own the learning inputs you provide (e.g., words, sentences). +* **AI-generated outputs**: You may use the generated stories, translations, and audio for personal learning. Commercial use requires prior written permission. +* **Our content**: The Lingput name, code, and design are owned by us and protected by copyright and trademark laws. + +--- + +## 6. Payments (if applicable) + +* Some features may require a paid subscription. +* Payments are processed securely by third-party providers (e.g., Stripe). +* Refunds are governed by our Refund Policy (published separately if applicable). +* We may change pricing with reasonable notice. + +--- + +## 7. Service Availability + +Lingput is provided “as is” and “as available.” +We do not guarantee uninterrupted or error-free service. +We may modify, suspend, or discontinue features at any time. + +--- + +## 8. Limitation of Liability + +To the maximum extent permitted by law: + +* We are not liable for indirect, incidental, or consequential damages. +* Our total liability for any claim related to Lingput will not exceed the amount you paid us in the last 12 months (if any). + +--- + +## 9. Indemnification + +You agree to indemnify and hold us harmless from claims, damages, or expenses arising from your misuse of Lingput or violation of these Terms. + +--- + +## 10. Changes to Terms + +We may update these Terms from time to time. Updates will be posted on this page with a new effective date. Continued use after updates means you accept the changes. + +--- + +## 11. Governing Law + +These Terms are governed by the laws of the United States and the State of California. +Any disputes will be handled in courts located in California. + +--- + +## 12. Contact + +For questions about these Terms: +Email: **support@lingput.dev** + +`; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/frontend/src/components/CookieBanner.tsx b/apps/frontend/src/components/CookieBanner.tsx new file mode 100644 index 0000000..65bd6a1 --- /dev/null +++ b/apps/frontend/src/components/CookieBanner.tsx @@ -0,0 +1,94 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import { useEffect, useRef, useState } from "react"; + +const STORAGE_KEY = "cookie-consent:v1"; + +export default function CookieBanner() { + const [visible, setVisible] = useState(false); + const mounted = useRef(false); + + useEffect(() => { + if (mounted.current) return; + mounted.current = true; + try { + const hasChoice = localStorage.getItem(STORAGE_KEY) !== null; + if (!hasChoice) setVisible(true); + } catch { + setVisible(true); + } + + (window as any).showCookieBanner = () => setVisible(true); + }, []); + + const updateConsent = (granted: boolean) => { + const state = granted ? "granted" : "denied"; + const call = () => { + if (typeof (window as any).gtag !== "function") return false; + (window as any).gtag("consent", "update", { + ad_storage: "denied", + ad_user_data: "denied", + ad_personalization: "denied", + analytics_storage: state, + functionality_storage: "granted", + security_storage: "granted", + }); + return true; + }; + if (!call()) { + // retry for up to ~8s while gtag loads + let tries = 0; + const t = setInterval(() => { + tries++; + if (call() || tries > 32) clearInterval(t); + }, 250); + } + }; + + const choose = (val: "accept" | "reject") => { + try { + localStorage.setItem(STORAGE_KEY, val); + } catch { + console.log("error"); + } + updateConsent(val === "accept"); + setVisible(false); + }; + + if (!visible) return null; + + return ( +
+
+

+ We use cookies for analytics only. Ads & personalization are off by + default. Choose Accept to enable analytics or Reject to continue with + essentials. See our{" "} + + Privacy Policy + + . +

+
+ + +
+
+
+ ); +} diff --git a/apps/landing/Dockerfile b/apps/landing/Dockerfile index 7455d3f..f3ab406 100644 --- a/apps/landing/Dockerfile +++ b/apps/landing/Dockerfile @@ -2,6 +2,8 @@ FROM node:alpine WORKDIR "/app" ARG NEXT_PUBLIC_APP_URL ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL +ARG NEXT_PUBLIC_GA_ID +ENV NEXT_PUBLIC_GA_ID=$NEXT_PUBLIC_GA_ID COPY ./package*.json . RUN npm install COPY . . diff --git a/apps/landing/app/cookie/page.tsx b/apps/landing/app/cookie/page.tsx new file mode 100644 index 0000000..7b7f1a3 --- /dev/null +++ b/apps/landing/app/cookie/page.tsx @@ -0,0 +1,63 @@ +import ReactMarkdown from "react-markdown"; + +export default function TermsPage() { + const content = ` +# Cookie Policy — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. What Are Cookies? + +Cookies are small text files stored on your device when you visit a website. They help websites remember your preferences and improve your browsing experience. Some cookies are essential, while others are optional. + +--- + +## 2. How Lingput Uses Cookies + +We use cookies in the following categories: + +* **Essential cookies (required)** + Needed for core functionality such as login sessions, account security, and remembering your language progress. + These cannot be disabled. + +* **Analytics cookies (optional)** + With your consent, we use Google Analytics 4 (Consent Mode) to understand how users interact with Lingput and to improve the platform. These cookies are only activated if you click **Accept** in the cookie banner. + +* **No advertising cookies** + Lingput does not use advertising, remarketing, or personalization cookies. + +--- + +## 3. Managing Your Cookie Preferences + +* When you first visit Lingput, you can accept or reject analytics cookies via the cookie banner. +* You can change your choice at any time by clicking **Cookie Settings** in the footer. +* You can also delete cookies through your browser settings. + +--- + +## 4. Third-Party Cookies + +Some cookies may be placed by trusted third parties: + +* **Google Analytics (Google LLC, USA)** — analytics cookies (only with your consent). + +--- + +## 5. More Information + +For details on how we handle personal data, see our [Privacy Policy](/privacy). + +If you have questions about this Cookie Policy, contact us at **support@lingput.dev**. + + `; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/landing/app/ga.tsx b/apps/landing/app/ga.tsx new file mode 100644 index 0000000..0aa451d --- /dev/null +++ b/apps/landing/app/ga.tsx @@ -0,0 +1,34 @@ +"use client"; + +import Script from "next/script"; + +export default function GA({ id }: { id: string }) { + return ( + <> + + + ); +} diff --git a/apps/landing/app/layout.tsx b/apps/landing/app/layout.tsx index bd00b8b..b9f676f 100644 --- a/apps/landing/app/layout.tsx +++ b/apps/landing/app/layout.tsx @@ -1,39 +1,61 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; +import CookieBanner from "@/components/CookieBanner"; +import GA from "./ga"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - // TODO: Replace with actual URL - metadataBase: new URL("http://localhost:3000"), + metadataBase: new URL("https://lingput.dev"), title: "Lingput - Learn German with AI-Generated Stories", description: "Learn German with short, AI-generated stories tailored to your vocabulary level. Natural comprehensible input for English speakers with translations, audio, and smart word tracking.", + keywords: [ + "learn german", + "language learning", + "comprehensible input", + "AI stories", + "german for english speakers", + "vocabulary builder", + ], openGraph: { title: "Lingput - Learn German with AI-Generated Stories", description: "Learn German with short, AI-generated stories tailored to your vocabulary level for English speakers.", - url: "https://lingput.com", // TODO: Replace with actual URL + url: "https://lingput.dev", siteName: "Lingput", images: [ { - url: "/og-image.png", // TODO: Add actual OG image - width: 1200, - height: 630, + url: "/logo_min.png", + width: 1024, + height: 366, + alt: "Lingput Logo", }, ], locale: "en_US", type: "website", }, - keywords: [ - "learn german", - "language learning", - "comprehensible input", - "AI stories", - "german for english speakers", - "vocabulary builder", - ], + twitter: { + card: "summary_large_image", + title: "Lingput - Learn German with AI-Generated Stories", + description: "Learn German with AI-generated stories tailored to your vocabulary level.", + images: ["/logo_min.png"], + }, + icons: { + icon: [ + { url: "/favicon.ico", sizes: "any" }, + { url: "/favicon.svg", type: "image/svg+xml" }, + ], + apple: [{ url: "/apple-touch-icon.png" }], + }, + manifest: "/site.webmanifest", + authors: [{ name: "Mark Morgan", url: "https://markmdev.com" }], + robots: { + index: true, + follow: true, + nocache: false, + }, }; export default function RootLayout({ @@ -44,7 +66,9 @@ export default function RootLayout({ return ( + {children} + ); diff --git a/apps/landing/app/privacy/page.tsx b/apps/landing/app/privacy/page.tsx new file mode 100644 index 0000000..7d20e9c --- /dev/null +++ b/apps/landing/app/privacy/page.tsx @@ -0,0 +1,125 @@ +import ReactMarkdown from "react-markdown"; + +export default function PrivacyPage() { + const content = ` +# Privacy Policy — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. Introduction + +Lingput is an AI-powered language learning application. This Privacy Policy explains how we collect, use, and protect your personal data when you use Lingput. + +--- + +## 2. What Data We Collect + +* **Account information**: email address, username, password (hashed). +* **Learning progress**: words, stories, and exercises you complete, your vocabulary history, and session stats. +* **Generated content**: stories, translations, and audio files generated for you by our AI. +* **Technical data**: browser type, IP address, device information, cookies (only with your consent). +* **Payment data**: if applicable, processed securely by third-party payment providers (we do not store your card details). + +--- + +## 3. How We Use Your Data + +* To provide the Lingput service (saving your learning history, generating personalized exercises). +* To improve the platform (analytics, performance monitoring, bug fixing). +* To ensure security (account authentication, fraud prevention). +* To comply with legal obligations (tax, accounting, regulatory compliance). + +We do **not** sell your personal information. + +--- + +## 4. AI-Generated Content + +Lingput uses third-party AI services (e.g., OpenAI APIs) to generate stories, translations, and audio. + +* Your input text may be transmitted to these services to generate the output. +* Data is not used by these providers to train their models (per their policies at the time of writing). +* We only store the outputs relevant to your learning history. + +--- + +## 5. Cookies and Tracking + +Lingput uses cookies only with your consent: + +* **Functional cookies**: required for login and session security. +* **Analytics cookies**: optional, used to understand usage patterns (Google Analytics 4 with Consent Mode). +* **No advertising cookies** are used. + +You can change your cookie preferences anytime via the “Cookie Settings” link. + +--- + +## 6. Data Sharing + +We share data only with trusted providers necessary to operate Lingput: + +* **Hosting & infrastructure**: DigitalOcean, AWS, Supabase, Redis. +* **Analytics**: Google Analytics (if you consent). +* **AI processing**: OpenAI API for text and audio generation. +* **Payments**: Stripe or other payment processors (if you purchase a subscription). + +--- + +## 7. Data Retention + +* Account data is stored until you delete your account. +* Learning history persists while your account is active. +* Analytics data (if enabled) is retained per provider defaults (up to 14 months). +* Server logs are rotated every 30–90 days. + +--- + +## 8. Your Rights + +Depending on your jurisdiction (EU/EEA, UK, California), you may have the right to: + +* Access, correct, or delete your personal data. +* Request export of your data (data portability). +* Withdraw consent for analytics cookies. +* Delete your account at any time. + +To exercise these rights, contact us at **support@lingput.dev**. + +--- + +## 9. Security + +We use HTTPS, hashed passwords, access controls, and monitoring to protect your data. +However, no online service is 100% secure — please use a strong password and keep it private. + +--- + +## 10. Children’s Privacy + +Lingput is not directed to children under 13 (or the age of digital consent in your region). +We do not knowingly collect personal information from children. + +--- + +## 11. Changes + +We may update this Privacy Policy occasionally. Updates will be posted here with a new “Effective date.” + +--- + +## 12. Contact + +For questions, requests, or concerns: +Email: **[support@lingput.dev](mailto:support@lingput.dev)** +`; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/landing/app/sitemap.ts b/apps/landing/app/sitemap.ts index 8db5846..27bea62 100644 --- a/apps/landing/app/sitemap.ts +++ b/apps/landing/app/sitemap.ts @@ -1,8 +1,7 @@ import { MetadataRoute } from "next"; export default function sitemap(): MetadataRoute.Sitemap { - // TODO: Replace with actual URL - const baseUrl = "https://lingput.com"; + const baseUrl = "https://lingput.dev"; return [ { diff --git a/apps/landing/app/terms/page.tsx b/apps/landing/app/terms/page.tsx new file mode 100644 index 0000000..9c918ac --- /dev/null +++ b/apps/landing/app/terms/page.tsx @@ -0,0 +1,112 @@ +import ReactMarkdown from "react-markdown"; + +export default function TermsPage() { + const content = ` +# Terms of Service — Lingput + +**Effective date:** September 4, 2025 +**Service:** Lingput (AI-powered language learning platform) + +--- + +## 1. Acceptance of Terms + +By creating an account or using Lingput, you agree to be bound by these Terms of Service and our [Privacy Policy](/privacy). +If you do not agree, you may not use the Service. + +--- + +## 2. Eligibility + +You must be at least 13 years old (or the age of digital consent in your country) to use Lingput. +By using Lingput, you represent that you meet this requirement. + +--- + +## 3. Accounts + +* You are responsible for maintaining the security of your account and password. +* You must provide accurate information when creating an account. +* You are responsible for all activity that occurs under your account. +* You may delete your account at any time. + +--- + +## 4. Acceptable Use + +You agree **not to**: + +* Use Lingput for unlawful, harmful, or abusive purposes. +* Attempt to disrupt, hack, or overload the Service. +* Upload or generate offensive, discriminatory, or illegal content. + +We reserve the right to suspend or terminate accounts that violate these rules. + +--- + +## 5. Content & Intellectual Property + +* **Your content**: You own the learning inputs you provide (e.g., words, sentences). +* **AI-generated outputs**: You may use the generated stories, translations, and audio for personal learning. Commercial use requires prior written permission. +* **Our content**: The Lingput name, code, and design are owned by us and protected by copyright and trademark laws. + +--- + +## 6. Payments (if applicable) + +* Some features may require a paid subscription. +* Payments are processed securely by third-party providers (e.g., Stripe). +* Refunds are governed by our Refund Policy (published separately if applicable). +* We may change pricing with reasonable notice. + +--- + +## 7. Service Availability + +Lingput is provided “as is” and “as available.” +We do not guarantee uninterrupted or error-free service. +We may modify, suspend, or discontinue features at any time. + +--- + +## 8. Limitation of Liability + +To the maximum extent permitted by law: + +* We are not liable for indirect, incidental, or consequential damages. +* Our total liability for any claim related to Lingput will not exceed the amount you paid us in the last 12 months (if any). + +--- + +## 9. Indemnification + +You agree to indemnify and hold us harmless from claims, damages, or expenses arising from your misuse of Lingput or violation of these Terms. + +--- + +## 10. Changes to Terms + +We may update these Terms from time to time. Updates will be posted on this page with a new effective date. Continued use after updates means you accept the changes. + +--- + +## 11. Governing Law + +These Terms are governed by the laws of the United States and the State of California. +Any disputes will be handled in courts located in California. + +--- + +## 12. Contact + +For questions about these Terms: +Email: **support@lingput.dev** + +`; + + return ( +
+ {content} +
+ ); +} diff --git a/apps/landing/components/CookieBanner.tsx b/apps/landing/components/CookieBanner.tsx new file mode 100644 index 0000000..1056398 --- /dev/null +++ b/apps/landing/components/CookieBanner.tsx @@ -0,0 +1,96 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import { useEffect, useRef, useState } from "react"; + +const STORAGE_KEY = "cookie-consent:v1"; + +export default function CookieBanner() { + const [visible, setVisible] = useState(false); + const mounted = useRef(false); + + useEffect(() => { + if (mounted.current) return; + mounted.current = true; + try { + const hasChoice = localStorage.getItem(STORAGE_KEY) !== null; + if (!hasChoice) setVisible(true); + } catch { + // SSR / restricted storage: keep banner visible by default + setVisible(true); + } + + // expose reopen API + (window as any).showCookieBanner = () => setVisible(true); + }, []); + + const updateConsent = (granted: boolean) => { + const state = granted ? "granted" : "denied"; + const call = () => { + if (typeof (window as any).gtag !== "function") return false; + (window as any).gtag("consent", "update", { + ad_storage: "denied", + ad_user_data: "denied", + ad_personalization: "denied", + analytics_storage: state, + functionality_storage: "granted", + security_storage: "granted", + }); + return true; + }; + if (!call()) { + // retry for up to ~8s while gtag loads + let tries = 0; + const t = setInterval(() => { + tries++; + if (call() || tries > 32) clearInterval(t); + }, 250); + } + }; + + const choose = (val: "accept" | "reject") => { + try { + localStorage.setItem(STORAGE_KEY, val); + } catch { + console.log("error"); + } + updateConsent(val === "accept"); + setVisible(false); + }; + + if (!visible) return null; + + return ( +
+
+

+ We use cookies for analytics only. Ads & personalization are off by + default. Choose Accept to enable analytics or Reject to continue with + essentials. See our{" "} + + Privacy Policy + + . +

+
+ + +
+
+
+ ); +} diff --git a/apps/landing/components/landing/Footer.tsx b/apps/landing/components/landing/Footer.tsx index 25ec024..6427b99 100644 --- a/apps/landing/components/landing/Footer.tsx +++ b/apps/landing/components/landing/Footer.tsx @@ -13,6 +13,11 @@ export default function Footer() {

© {new Date().getFullYear()} Lingput. All rights reserved.

+

+ Privacy Policy + Terms of Service + Cookie Policy +

= 0.4" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2165,6 +2227,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2182,6 +2254,46 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2263,6 +2375,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2309,7 +2431,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -2377,7 +2498,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2391,6 +2511,19 @@ } } }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2434,6 +2567,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -3169,6 +3324,16 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3179,6 +3344,12 @@ "node": ">=0.10.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3733,6 +3904,56 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3789,6 +4010,12 @@ "dev": true, "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -3804,6 +4031,30 @@ "node": ">= 0.4" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -3960,6 +4211,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4025,6 +4286,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -4087,6 +4358,18 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -4444,6 +4727,16 @@ "dev": true, "license": "MIT" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4481,94 +4774,688 @@ "node": ">= 0.4" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", - "engines": { - "node": ">= 8" + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, - "engines": { - "node": ">=8.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/motion-dom": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", - "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "license": "MIT", "dependencies": { - "motion-utils": "^11.18.1" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/motion-utils": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", - "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "license": "MIT", "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/nanoid": { + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/motion-dom": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", + "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", + "license": "MIT", + "dependencies": { + "motion-utils": "^11.18.1" + } + }, + "node_modules/motion-utils": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", + "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", @@ -4935,6 +5822,31 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5172,6 +6084,16 @@ "react-is": "^16.13.1" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5234,6 +6156,33 @@ "dev": true, "license": "MIT" }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -5299,6 +6248,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -5665,6 +6647,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -5872,6 +6864,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5920,6 +6926,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -6169,6 +7193,26 @@ "node": ">=8.0" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -6571,6 +7615,93 @@ "dev": true, "license": "MIT" }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", @@ -6653,6 +7784,34 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6892,6 +8051,16 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/apps/landing/package.json b/apps/landing/package.json index 5bbde6d..7939ad5 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -18,6 +18,7 @@ "next": "14.2.3", "react": "^18", "react-dom": "^18", + "react-markdown": "^10.1.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7" }, diff --git a/apps/landing/public/apple-touch-icon.png b/apps/landing/public/apple-touch-icon.png new file mode 100644 index 0000000..7b83c7f Binary files /dev/null and b/apps/landing/public/apple-touch-icon.png differ diff --git a/apps/landing/public/favicon-96x96.png b/apps/landing/public/favicon-96x96.png new file mode 100644 index 0000000..ac6d901 Binary files /dev/null and b/apps/landing/public/favicon-96x96.png differ diff --git a/apps/landing/public/favicon.ico b/apps/landing/public/favicon.ico new file mode 100644 index 0000000..f85cc23 Binary files /dev/null and b/apps/landing/public/favicon.ico differ diff --git a/apps/landing/public/favicon.svg b/apps/landing/public/favicon.svg new file mode 100644 index 0000000..56d4ece --- /dev/null +++ b/apps/landing/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/site.webmanifest b/apps/landing/public/site.webmanifest new file mode 100644 index 0000000..8b77109 --- /dev/null +++ b/apps/landing/public/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "Lingput", + "short_name": "Lingput", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/apps/landing/public/web-app-manifest-192x192.png b/apps/landing/public/web-app-manifest-192x192.png new file mode 100644 index 0000000..ad2c57f Binary files /dev/null and b/apps/landing/public/web-app-manifest-192x192.png differ diff --git a/apps/landing/public/web-app-manifest-512x512.png b/apps/landing/public/web-app-manifest-512x512.png new file mode 100644 index 0000000..435a059 Binary files /dev/null and b/apps/landing/public/web-app-manifest-512x512.png differ