TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗The "coming soon" waitlist page for Polyngual, the consumer language brand built on Voxeo's technology. It is a standalone Next.js app, kept separate from the Voxeo repo and Vercel project (see the brief).
| Route | What it is |
|---|---|
/ | Redirects to /es |
/es | Landing page in Spanish (default, x-default in hreflang) |
/en | Landing page in English. Copy lives in src/content/en.ts, same shape as es.ts; a new language is a new dictionary plus an entry in src/content/index.ts |
/toefl-practice, /toeic-practice, /ielts-practice, /cambridge-practice and /es/preparacion-{toefl,toeic,ielts,cambridge} | Standalone exam landing pages (not in the navigation; linked from footers and the sitemap, with hreflang between each pair). Registry in src/lib/exams.ts, copy in src/content/exams/ |
/privacidad, /en/privacy | Privacy policy (Spanish path fixed by the brief; /es/privacy redirects to it) |
/baja | Unsubscribe and delete my data (linked from every email; ?l=en shows it in English) |
/api/diagnostico?key=WAITLIST_SECRET | Private setup check: which settings are present, Resend domain status, GoHighLevel access; &to= sends a test email |
POST /api/waitlist | Signup: validates the email, requires consent, saves to Resend, copies to GoHighLevel, sends the confirmation email in the page's language |
POST /api/baja | Signed unsubscribe link and mail clients' one-click unsubscribe (RFC 8058) |
/examen, /examen/*, /api/examen/*, /examen-static/* | The TOEFL / TOEIC exam-prep product and its beta (/examen/beta). Not in this repo: forwarded to the exam app (repo exitohire-ai) by rewrites in next.config.ts; EXAM_APP_ORIGIN sets where (default https://exitohire-ai.vercel.app) |
npm install
cp .env.example .env.local # optional: without RESEND_API_KEY signups are only logged
npm run dev # http://localhost:3000/es
npm test && npm run typecheck && npm run build
Resend stores the waitlist (as contacts in one segment) and sends the confirmation email.
polyngual.app and add the DNS records it shows (SPF, DKIM and the MX record for bounces) where the domain is managed. Wait for "Verified".Polyngual waitlist. Put its ID in RESEND_SEGMENT_ID.signup_order (number), and country, signup_date, utm_source, utm_medium, utm_campaign, utm_content, utm_term, referrer, landing (all string).polyngual-waitlist with full access (it must manage contacts, not only send), and put it in RESEND_API_KEY.WAITLIST_FROM_EMAIL to [email protected] (an address on the verified domain), WAITLIST_REPLY_TO to the inbox you read ([email protected]), and WAITLIST_SECRET to a long random string (openssl rand -base64 32).How signups behave:
x-vercel-ip-country header. Source comes from first-touch UTM parameters, the referrer and the landing URL.Each new signup is also copied into the Polyngual sub-account of GoHighLevel, so the list can be filtered and used in workflows there. Resend still sends the confirmation email.
GHL_TOKEN.GHL_LOCATION_ID.signup_order (number) to see each person's place in line.What lands in GoHighLevel: email, country, source ("Polyngual waitlist (instagram)") and tags: polyngual-waitlist on everyone, polyngual-fundador for the first 200, and fuente:… / campana:… from the UTM parameters. Tags need no setup and can trigger workflows. If GoHighLevel is down or misconfigured, the signup still succeeds (it's already in Resend) and the error is logged in Vercel. The unsubscribe link deletes the contact from GoHighLevel too.
src/content/exams/ rendered by src/components/exam/ExamPage.tsx. English pages live under src/app/(en) (their own lang="en" layout); Spanish ones are src/app/[locale]/[slug].NEXT_PUBLIC_MOCK_TEST_URL with ?exam=, lang= and UTM parameters (plus variant= from the IELTS and Cambridge pickers). Unset, it goes to the waitlist form in the page's language (/en#lista or /es#lista), which stores the same parameters in the signup's landing URL.mock_test_cta event (exam, lang, placement, variant) to Vercel Analytics.ExamPage.tsx; it renders only outside production. Do not fill it with invented testimonials or figures.Vercel Web Analytics, which sets no cookies, always runs. Turn it on in the Vercel project (Analytics tab).
Google Tag Manager runs Polyngual's container GTM-P2QHWHJ6 (built in; NEXT_PUBLIC_GTM_ID overrides it, off disables it). Google Analytics 4 is configured as a tag inside that container, so NEXT_PUBLIC_GA4_ID stays empty unless you want gtag.js directly. They set cookies, so they load only after the visitor accepts the cookie notice (src/components/GoogleTags.tsx); a small "Cookies" button reopens it. The <noscript> iframe from GTM's install snippet is left out on purpose: it would set cookies for visitors who never saw the notice. The waitlist_signup and mock_test_cta events go to Vercel always and to the GTM/GA4 dataLayer after consent (src/lib/analytics.ts), ready to mark as conversions.
Page views work on every plan. The waitlist_signup custom event needs a Vercel Pro plan; the source of every signup is stored in Resend either way.
Nothing public should link Polyngual to Voxeo or to its founder: no founder name in emails or on the site, no "powered by Voxeo", and the sender is the Polyngual team. Keep it that way in new copy.
src/app/globals.css: Midnight and Paper carry the page; Lagoon, Cobalt and Marigold are accents.next/font, with Latin and Latin Extended subsets.prefers-reduced-motion, and the hero demo pauses when it is off screen or the tab is hidden.public/og.png is the share image (1200×630). src/app/icon.png and apple-icon.png are made from the logo icon.Import this repo as a new Vercel project (framework preset Next.js, root directory left as is), add the environment variables above, and point polyngual.app at it.