Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기AI-assisted recipe app for importing, organizing, searching, and chatting about the recipes you want to cook.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
The recipe you loved last month deserves better than another lost browser tab.
Janella Cookbook is a home for recipes worth keeping. Save what you cook, pull recipes in from a webpage or video, and search your collection when the familiar question returns: “What should we make tonight?”
“Find something quick and vegetarian with the ingredients I already have.”
Use cookbook filters and search, or ask the recipe assistant to help explore the collection.README 전문 보기 ↗The recipe you loved last month deserves better than another lost browser tab.
Janella Cookbook is a home for recipes worth keeping. Save what you cook, pull recipes in from a webpage or video, and search your collection when the familiar question returns: “What should we make tonight?”
“Find something quick and vegetarian with the ingredients I already have.”
Use cookbook filters and search, or ask the recipe assistant to help explore the collection.
AI recipe parsing, photo extraction, nutrition, and chat use the Railway-hosted FreeLLMAPI router through the @ai-sdk/openai-compatible adapter and its Chat Completions endpoint. The default auto model follows the router's active fallback chain. Hosted embeddings run automatically for recipe indexing and semantic search, with keyword search available if the provider fails.
Requirements: Node.js 24 or later and the pnpm version pinned in
package.json, plus PostgreSQL with the pgvector extension enabled.
pnpm install
cp .env.example .env
Set DATABASE_URL to your PostgreSQL database. Create a dedicated client profile under Keys → Unified API key on FreeLLMAPI and save its key as FREELLM_API_KEY in .env.local and the deployment's server environment. FREELLM_BASE_URL defaults to https://freellmapi-production-1175.up.railway.app/v1; Optional FREELLM_MODEL overrides auto for chat. Recipe extraction and nutrition use auto:fast by default; set FREELLM_RECIPE_MODEL to override it. The legacy value auto for that recipe setting is normalized to auto:fast. Existing OpenRouter environment variables are no longer used.
Embeddings always use FreeLLMAPI with the same FREELLM_API_KEY and base URL as chat, through /v1/embeddings. FREELLM_EMBEDDING_MODEL is pinned to embeddinggemma-300m, matching the existing 768-dimensional index. The router may fail over between providers of this model, but changing model families requires reindexing and a schema update. The cookbook no longer needs a separate Hugging Face key; manage provider keys in FreeLLMAPI.
Optional Cloudflare R2 credentials enable managed recipe-image storage.
Application configuration is centralized in lib/env.ts using t3-env. Next.js validates it when loading its config. Empty optional values are treated as unset; provider keys remain optional, while DATABASE_URL must be a valid URL and DATABASE_POOL_MAX must be a positive integer (default 5). Only declared NEXT_PUBLIC_* values are accessible on the client. Prisma and test-runner configuration retain their own environment loading so dependency installation and client generation work without application credentials.
Create or update the database schema, then launch Next.js:
pnpm db:push
pnpm dev
Open https://janella-cookbook.localhost. pnpm dev runs through Portless (a dev dependency); its first run may ask for sudo to bind port 443 and trust a local certificate. The production website runs on Vercel, with its database and FreeLLMAPI service on Railway. Set runtime application variables in the Vercel project environment.
The cookbook exposes recipe tools at /api/mcp, using Vercel's mcp-handler. It runs in the existing Next.js app. The handler uses stateless Streamable HTTP and does not need Redis or a separate server.
MCP and the app share recipe queries in lib/recipe-queries.ts: listing, filters, pagination, and recipe lookup are reused by the tools, REST endpoints, and recipe browsing, detail, and edit pages. Saving uses the same createRecipe action as the app's recipe form. MCP keeps its own protocol response formatting and returns compact summaries when browsing.
Set MCP_API_TOKEN to a random secret in your local environment or the Vercel production environment. Generate one with:
openssl rand -hex 32
All MCP requests require Authorization: Bearer <your token>. A missing server token disables the endpoint with HTTP 503; missing or invalid client credentials return HTTP 401. This setup uses a shared token; clients must support an explicit Authorization header. Interactive OAuth sign-in is not implemented.
For clients that accept a remote MCP URL and headers, add this entry to their mcpServers configuration:
{
"mcpServers": {
"janella-cookbook": {
"url": "https://janella-cookbook.localhost/api/mcp",
"headers": {
"Authorization": "Bearer <your MCP_API_TOKEN>"
}
}
}
}
Replace the URL with https://janella-cookbook.vercel.app/api/mcp when connecting to the deployed app. Keep the real token out of committed configuration files.
| Tool | What it does |
|---|---|
list_recipes | Returns summaries with slugs and recipe page paths. Supports keyword query, cuisine, course, difficulty, tag (slug), isFavorite, and maxTime. Pagination uses limit (default 20, maximum 100) and offset, with total count and hasMore. |
get_recipe | Takes a slug and returns the full recipe, including ordered ingredients and instructions, tags, images, notes, and cooking history. |
add_recipe | Saves a complete recipe using the app's validation, transaction, search indexing, and page refresh logic. Requires title, ingredients, and instructions; accepts optional recipe metadata and a saveKey UUID for retry protection. |
For example, call add_recipe with:
{
"title": "Simple tomato soup",
"ingredients": [
{ "quantity": "1", "unit": "tbsp", "name": "olive oil" },
{ "quantity": "800", "unit": "g", "name": "canned tomatoes" }
],
"instructions": [
{ "text": "Heat the oil, add the tomatoes, and simmer for 15 minutes.", "duration": 15 },
{ "text": "Blend until smooth and season to taste." }
],
"prepTime": 5,
"cookTime": 15,
"servings": "2",
"course": "LUNCH",
"difficulty": "EASY",
"tags": ["soup", "vegetarian"],
"saveKey": "b3c0f8e4-9d79-4bd3-83db-cdc581290fe8"
}
Generate a new saveKey UUID for each recipe and reuse it only when retrying that same save. Times and instruction durations are in minutes, and array order determines ingredient and step order. Recipes added through MCP have source type API. Adding structured recipes and keyword browsing work without AI API keys; embedding generation runs in the background through FreeLLMAPI and provider failures do not block saving.
Run the MCP protocol and tool tests with pnpm exec vitest run tests/recipe-mcp.test.mjs.
pnpm lint
pnpm format:check
pnpm typecheck
pnpm test:e2e
For current follow-up work, see IMPROVEMENTS.md.