Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
Answer seven questions about your skin and get a personalised morning and evening skincare routine, the ingredients that suit you, and products at every budget.
LifestyleTypeScript · HTMLGitHub @NadiaSakovichOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Personalized skincare routine builder — staged quiz + AI (Gemini) routine engine. Next.js 16, React 19, Tailwind v4.
Translation pending
Loading the full README. The saved excerpt is shown below.
A web service that builds a personalized skincare routine. You take a staged quiz
(skin type → concerns → preferences), get a skin analysis, and receive an AM/PM
routine plus example product picks sourced from live web results.
Content is heuristic and for general guidance only — it is not medical advice, and
the product names shown are examples rather than endorsements.Read the full README ↗A web service that builds a personalized skincare routine. You take a staged quiz (skin type → concerns → preferences), get a skin analysis, and receive an AM/PM routine plus example product picks sourced from live web results.
Live: https://sealedskin.vercel.app
Content is heuristic and for general guidance only — it is not medical advice, and the product names shown are examples rather than endorsements.
@theme block in src/app/globals.cssnpm install
cp .env.example .env.local # then fill in the values (see below)
npm run dev # http://localhost:3000
The app runs without any credentials — it just degrades. Without GEMINI_API_KEY
you always get the offline routine logic (labelled "Standard routine · AI
unavailable"), and without the Firebase keys sign-in and saved routines are
unavailable. Everything else works.
| Script | What it does |
|---|---|
npm run dev | Dev server on port 3000 |
npm run build | Production build |
npm start | Serve a production build |
npm run lint | ESLint |
npx tsc --noEmit | Typecheck (strict; unused locals fail the build) |
Copy .env.example → .env.local (git-ignored) and fill in:
| Variable | Required for | Where to get it |
|---|---|---|
AI_PROVIDER | AI routines | gemini (the only provider today) |
AI_MODEL | AI routines | Default model, e.g. gemini-3.5-flash-lite |
GEMINI_API_KEY | AI routines + grounding | https://aistudio.google.com/apikey |
NEXT_PUBLIC_FIREBASE_API_KEY | Sign-in | Firebase console → Project settings → Web app |
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN | Sign-in | ” |
NEXT_PUBLIC_FIREBASE_PROJECT_ID | Sign-in | ” |
NEXT_PUBLIC_FIREBASE_APP_ID | Sign-in | ” |
FIREBASE_PROJECT_ID | Saved routines | Project settings → Service accounts → generate key |
FIREBASE_CLIENT_EMAIL | Saved routines | ” |
FIREBASE_PRIVATE_KEY | Saved routines | ” — one line, in quotes, keeping the literal \n escapes |
The NEXT_PUBLIC_* values are browser-visible identifiers and safe to expose. The
FIREBASE_CLIENT_EMAIL / FIREBASE_PRIVATE_KEY pair is a service-account secret —
keep it out of the client and out of git.
The quiz (src/components/SkinQuiz.tsx) is a client-side step machine: skin type
(7 diagnostic questions) → concerns and priorities → preferences (commitment level,
region, pregnancy) → a review screen → results.
Skin-type analysis is local and deterministic (src/lib/analysis.ts) — it scores
answers rather than asking a model, since the result is shown mid-quiz.
The routine is built by an AI agent (src/lib/ai/agent.ts) in two steps, because
Gemini cannot reliably combine Google Search grounding with structured JSON output in a
single call — with search enabled the JSON comes back corrupted:
The AI is called first; the local engine is the fallback. On any failure — missing
key, network error, malformed response — the quiz silently falls back to the offline
logic in src/data/actives.ts, so a user is never stuck. Which path ran is tagged on
RoutineResult.source.
When a grounded answer is shown, the source links and the Google Search Suggestions chip are displayed. That is required by Google's grounding terms — don't remove them.
src/app/ routes: / (quiz), /about, /how-it-works, /profile, /api/*
src/components/ layout, quiz, results, profile, ui
src/data/ quiz content: questions, concerns, actives, products
src/lib/ai/ provider interface, Gemini provider, agent, result assembly
src/lib/firebase/ client sign-in + Admin SDK
Deployed on Vercel; pushes to main deploy to production and branches get preview
URLs, via the Vercel GitHub App. Set the same environment variables in the Vercel
project — note that NEXT_PUBLIC_* values are inlined at build time, so changing
one requires a redeploy, not just a restart.
Two things that are easy to miss:
/api/routine sets maxDuration = 60. The grounded pipeline takes 9–18s. If that
budget is lost the failure is silent — routines just quietly become offline ones.jose overridepackage.json pins jose to ^5.10.0 through overrides. firebase-admin depends on
jwks-rsa, which does a CommonJS require('jose'), but jose 6 is ESM-only; since
firebase-admin is in Next's default serverExternalPackages list it is loaded with
native require, which throws ERR_REQUIRE_ESM inside a serverless bundle and 500s
every /api/users request.
This is not reproducible locally — next dev and next build && next start both
serve the route correctly. Verify anything touching firebase-admin, jose, or the
externals config on a preview deployment. Remove the override once jwks-rsa switches
to a dynamic import().
Server-side events are logged as structured JSON to both the console (so
Vercel's own runtime logs are unchanged) and Better Stack, via
src/lib/logger.ts. Without BETTER_STACK_SOURCE_TOKEN the logger silently
degrades to console-only, so local development needs no setup.
This is the beginning of the README. Read the rest at the original. Read the full README ↗