-
Notifications
You must be signed in to change notification settings - Fork 829
feat: add global-onboard demo app (closes #1761) #1890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Maulik176
wants to merge
12
commits into
lingodotdev:main
Choose a base branch
from
Maulik176:feat/community-global-onboard
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+18,781
−0
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
d938a6a
Add GlobalOnboard demo app to /community
Maulik176 6e27d00
chore: add changeset for community submission
Maulik176 487249c
fix(global-onboard): harden export and task edits
Maulik176 3d40607
fix(global-onboard): prevent stale translations and update docs
Maulik176 88c1ba2
Update community/global-onboard/app/page.tsx
Maulik176 fb43333
Merge branch 'main' into feat/community-global-onboard
sumitsaurabh927 9171c68
fix(global-onboard): tighten api guards and cleanup
Maulik176 6e9c324
fix(global-onboard): harden translation errors
Maulik176 11da20c
fix(global-onboard): harden api and align tailwind v4
Maulik176 1ad61e5
fix(global-onboard): improve tooling and translations
Maulik176 5694a02
fix(global-onboard): defer download url cleanup
Maulik176 bb1c4d9
Merge branch 'main' into feat/community-global-onboard
sumitsaurabh927 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "globalonboard": patch | ||
| --- | ||
|
|
||
| Harden onboarding pack export and task editing by escaping user content, converting edited template tasks to custom, and tightening UI defaults. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| # GlobalOnboard · LingoHack25 ✨ | ||
|
|
||
|
|
||
| **One onboarding checklist. Any language. Fully Configurable** | ||
| HR writes once in English, and GlobalOnboard turns it into a polished, localized employee experience by combining **Lingo CLI**, **Lingo JavaScript SDK**, and **Lingo CI**. | ||
|
|
||
|
|
||
| ## 🧠 The MAIN Pillars of GlobalOnboard | ||
|
|
||
| - **Real personas:** HR Workspace (authoring) + Employee Experience (preview) wired together in real time. | ||
| - **Full Lingo toolchain:** Static JSON via CLI, runtime personalization via SDK, and CI automation so translations stay fresh. | ||
| - **Enterprise-ready touches:** Translation QA mode, localization health warnings, onboarding pack export, and translation spinners that prove we’re production aware. | ||
|
|
||
| ### 🏅 Lingo Product Scorecard | ||
|
|
||
| | Lingo product | How GlobalOnboard uses it | Why it matters | | ||
| | --- | --- | --- | | ||
| | **Lingo CLI** | Generates `data/ui.{locale}.json` and `data/onboarding_template.{locale}.json` from English sources via `npx lingo.dev@latest run`. | Demonstrates the official static localization workflow. | | ||
| | **Lingo JavaScript SDK** | Translates the welcome note and every custom task at runtime with caching, spinners, and graceful fallbacks. | Shows dynamic personalization for each employee preview. | | ||
| | **Lingo CI** | `.github/workflows/i18n.yml` runs `npx lingo.dev@latest ci --pull-request` whenever English JSON or `i18n.json` changes. | Proves translation automation and GitHub integration end-to-end. | | ||
|
|
||
| --- | ||
|
|
||
| ## 🔑 Feature Highlights | ||
|
|
||
| | Area | What it unlocks | Lingo capability | | ||
| | --- | --- | --- | | ||
| | HR Workspace | Edit company, role, welcome note, and a fully dynamic checklist (add/delete/modify tasks). | Authoring surface for English source | | ||
| | Employee Experience | Switch between `en`, `es`, `fr`, `hi` previews with live updates + translation loading overlay. | CLI JSON + SDK runtime translations | | ||
| | Preview Modes | `Employee view` or `Translation QA` (side-by-side EN vs target locale) with Machine → Edited → Approved overrides. | Human-in-the-loop QA | | ||
| | Localization Health | Warns when translated copy is >1.5× English length, per task + summary. | QA signal | | ||
| | Onboarding Pack Export | One click generates a `.doc` bundle for the current locale (company, role, tasks, welcome note). | HR enablement | | ||
| | Lingo CI Workflow | GitHub Action auto-runs `lingo.dev ci` whenever English JSON changes. | Translation automation | | ||
|
|
||
| --- | ||
|
|
||
| ## 🧩 Architecture At-a-Glance | ||
|
|
||
| ```text | ||
| HR inputs ──▶ English JSON templates ──▶ Lingo CLI generates data/ui.{locale}.json | ||
| │ │ | ||
| │ └─▶ Lingo CI keeps translations up to date | ||
| │ | ||
| ├─▶ React state + localStorage overrides | ||
| │ | ||
| └─▶ Lingo JS SDK | ||
| ├─ Welcome note runtime translation | ||
| └─ Custom task translations (per locale) + caching | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 🧪 Getting Started (Local Dev) | ||
|
|
||
| ```bash | ||
| git clone https://github.com/lingodotdev/lingo.dev.git | ||
| cd lingo.dev/community/global-onboard | ||
| npm install | ||
|
|
||
| # Provide your API key so CLI + SDK can translate | ||
| export LINGO_DOT_DEV_API_KEY="your-key" | ||
| # Optional alias used by some shells/CLIs | ||
| export LINGODOTDEV_API_KEY="$LINGO_DOT_DEV_API_KEY" | ||
|
|
||
| npm run dev | ||
| ``` | ||
|
|
||
| Visit **<http://localhost:3000>** — left panel is HR Workspace, right panel is the localized Employee preview. | ||
|
|
||
| --- | ||
|
|
||
| ## 🌐 Localization Workflow Cheat Sheet | ||
|
|
||
| ### 1. Static JSON (Lingo CLI) | ||
| - Source files: `data/ui.en.json`, `data/onboarding_template.en.json` | ||
| - Configure targets in `i18n.json` | ||
| - Generate translations: | ||
| ```bash | ||
| export LINGO_DOT_DEV_API_KEY="your-key" | ||
| npx lingo.dev@latest run | ||
| ``` | ||
| - CI automation: `.github/workflows/i18n.yml` runs `npx lingo.dev@latest ci --pull-request` on every push to `main` touching English JSON or `i18n.json`. | ||
|
|
||
| ### 2. Runtime Personalization (Lingo JS SDK) | ||
| - Welcome note + any **custom tasks** run through `lib/lingo-client.ts`. | ||
| - We cache translations per locale, show a loading spinner overlay, and gracefully fall back to English if the SDK errors. | ||
|
|
||
| ### 3. Translation QA Mode | ||
| - Side-by-side English vs target locale. | ||
| - Inline editing with Machine → Edited → Approved chips. | ||
| - Reset/Unlock controls to manage overrides. | ||
| - Length-based warnings + summary so HR spots risky strings fast. | ||
| - Overrides feed every other view (single preview + export). | ||
|
|
||
| --- | ||
|
|
||
| ## 📦 Onboarding Pack Export | ||
|
|
||
| 1. Choose a locale via the Employee panel dropdown. | ||
| 2. Ensure QA overrides are final (Approved if needed). | ||
| 3. Click **Download Onboarding Pack** → generates `onboarding-pack-<locale>.doc` with: | ||
| - Locale code | ||
| - Localized company + role | ||
| - Welcome note (SDK translation if non-English) | ||
| - Full task list using effective text (overrides or machine) | ||
|
|
||
| Perfect for HRIS uploads, emails, or sharing with managers. | ||
|
|
||
| --- | ||
|
|
||
| ## 🛠 Tech Stack | ||
|
|
||
| - **Next.js 16** (App Router, TypeScript) | ||
| - **Tailwind CSS 4** (custom gradient + glassmorphism theme) | ||
| - **Lingo.dev CLI, JS SDK, CI** | ||
| - **next-themes** + custom design tokens for dark-first UI | ||
| - **GitHub Actions** for automated localization runs | ||
|
|
||
| --- | ||
|
|
||
| ## 📁 Project Structure | ||
|
|
||
| ```text | ||
| app/ | ||
| layout.tsx # Root metadata + ThemeProvider | ||
| page.tsx # HR + Employee panels, QA, overrides, spinner | ||
| globals.css # Tailwind layers + design tokens | ||
| components/ | ||
| mode-toggle.tsx # Shadcn-style theme toggle (hidden by default) | ||
| data/ | ||
| ui.*.json # Static UI translations (CLI managed) | ||
| onboarding_template.*.json | ||
| lib/ | ||
| i18n.ts # Typed loaders for JSON bundles | ||
| lingo-client.ts # SDK setup + runtime translation helpers | ||
| .github/workflows/ | ||
| i18n.yml # CI job running `lingo.dev ci` | ||
| i18n.json # Bucket + locale configuration | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 🧾 Useful Scripts | ||
|
|
||
| - `npm run dev` – Next.js dev server | ||
| - `npm run build` – Production build | ||
| - `npm run lint` – ESLint via `eslint-config-next` | ||
|
|
||
| --- | ||
|
|
||
| ## ✅ Hackathon Compliance & Notes | ||
|
|
||
| - All code, UI, and assets created fresh during **LingoHack25**. | ||
| - API keys are required only for translation features; none are checked into the repo. | ||
| - Want more locales? Add them to `SUPPORTED_LOCALES` + `i18n.json`, re-run the CLI, and you’re done. | ||
|
|
||
| --- | ||
|
|
||
| ### 💬 Questions for Judges? | ||
| Open an issue or ping me — I'd love to show how GlobalOnboard can become the multilingual onboarding cockpit for any global company. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import { NextResponse } from "next/server"; | ||
|
|
||
| import { translateWithLingo } from "@/lib/lingo"; | ||
| import { SUPPORTED_LOCALES, type Locale } from "@/lib/i18n"; | ||
|
|
||
| type TranslationPayload = { | ||
| text?: string; | ||
| targetLocale?: Locale; | ||
| }; | ||
|
|
||
| const MAX_TEXT_LENGTH = 2000; | ||
|
|
||
| export async function POST(request: Request) { | ||
| let payload: TranslationPayload; | ||
|
|
||
| try { | ||
| payload = (await request.json()) as TranslationPayload; | ||
| } catch (error) { | ||
| console.error("Invalid translation payload", error); | ||
| return NextResponse.json({ error: "Invalid request body" }, { status: 400 }); | ||
| } | ||
|
|
||
| const { text, targetLocale } = payload; | ||
|
|
||
| if (!text || typeof text !== "string") { | ||
| return NextResponse.json({ error: "Missing welcome note" }, { status: 400 }); | ||
| } | ||
|
|
||
| if (text.length > MAX_TEXT_LENGTH) { | ||
| return NextResponse.json({ error: "Welcome note is too long" }, { status: 413 }); | ||
| } | ||
|
|
||
| if (!targetLocale || !SUPPORTED_LOCALES.includes(targetLocale)) { | ||
| return NextResponse.json({ error: "Unsupported locale" }, { status: 400 }); | ||
| } | ||
|
|
||
| try { | ||
| const translated = await translateWithLingo(text, targetLocale); | ||
| return NextResponse.json({ translated }); | ||
| } catch (error) { | ||
| console.error("Lingo translation failed", error); | ||
| return NextResponse.json( | ||
| { error: "Unable to translate welcome note" }, | ||
| { status: 500 }, | ||
| ); | ||
| } | ||
| } |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| @source "../app/**/*.{js,ts,jsx,tsx}"; | ||
| @source "../components/**/*.{js,ts,jsx,tsx}"; | ||
| @source "../lib/**/*.{js,ts,jsx,tsx}"; | ||
|
|
||
| @custom-variant dark (&:where(.dark, .dark *)); | ||
Maulik176 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| :root { | ||
| --background: linear-gradient(135deg, #e3f2ff, #f9f1ff); | ||
| --foreground: #0f172a; | ||
| --muted: rgba(255, 255, 255, 0.8); | ||
| --muted-foreground: #475569; | ||
| --panel-start: #eef2ff; | ||
| --panel-end: #fdf2f8; | ||
| } | ||
|
|
||
| .dark { | ||
| --background: linear-gradient(145deg, #05010c, #0f172a 55%, #1f2937); | ||
| --foreground: #f8fafc; | ||
| --muted: rgba(15, 23, 42, 0.85); | ||
| --muted-foreground: #94a3b8; | ||
| --panel-start: rgba(15, 23, 42, 0.9); | ||
| --panel-end: rgba(79, 70, 229, 0.35); | ||
| } | ||
|
|
||
| @theme inline { | ||
| --color-background: var(--background); | ||
| --color-foreground: var(--foreground); | ||
| --color-muted: var(--muted); | ||
| --color-muted-foreground: var(--muted-foreground); | ||
| --font-sans: "Inter", "Sohne", system-ui, -apple-system, blinkmacsystemfont, | ||
| "Segoe UI", sans-serif; | ||
| --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace; | ||
| } | ||
|
|
||
| body { | ||
| background: var(--background); | ||
| color: var(--foreground); | ||
| font-family: var(--font-sans); | ||
| transition: color 0.3s ease; | ||
| background-attachment: fixed; | ||
| } | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import type { Metadata } from "next"; | ||
| import "./globals.css"; | ||
| import { ThemeProvider } from "@/components/theme-provider"; | ||
| import { cn } from "@/lib/utils"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "GlobalOnboard", | ||
| description: | ||
| "GlobalOnboard lets HR teams create one onboarding checklist and preview it in multiple languages via Lingo.dev.", | ||
| icons: { | ||
| icon: [ | ||
| { url: "/favicon.svg", type: "image/svg+xml" }, | ||
| { url: "/favicon.svg", rel: "alternate icon", type: "image/svg+xml" }, | ||
| ], | ||
| }, | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: Readonly<{ | ||
| children: React.ReactNode; | ||
| }>) { | ||
| return ( | ||
| <html lang="en" className="dark" suppressHydrationWarning> | ||
| <body | ||
| className={cn( | ||
| "min-h-screen bg-background text-foreground antialiased transition-colors", | ||
| )} | ||
| > | ||
| <ThemeProvider | ||
| attribute="class" | ||
| defaultTheme="dark" | ||
| forcedTheme="dark" | ||
| enableSystem={false} | ||
| disableTransitionOnChange | ||
Maulik176 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| > | ||
| {children} | ||
| </ThemeProvider> | ||
| </body> | ||
| </html> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Maulik176 there's no need for a patch (it will bump the package version/trigger an NPM release).
Can you please update it to an empty changeset.
Just remove this file and run: