Synaplan
기업을 위한 오픈소스 AI 플랫폼
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Service preparation tool for small churches (WIP)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗WorshipFlow is becoming a multi-church church management system with a public church website for each church. Each church is a workspace. It began as a worship-service preparation tool; that work is now the Worship module.
Where the product is going is recorded in docs/core/:
Product, Architecture,
Data model,
Access and privacy, and
Roadmap. Later changes to those decisions are logged in
docs/changes/YYYYMMDD.md. Agent and contributor rules are in
AGENTS.md; the visual contract is DESIGN.md.
What exists today is described under Current Workflows below: Worship (services, songs, media tools, sermon captions), a calendar-first Events foundation, People and Ministries (the roster, with a PEOPLE permission), and workspace settings and access. Planned, not built yet: Announcements, the public Page Builder site, and a summary Dashboard.
Server failures use structured logs and OpenTelemetry trace annotations. Run
npm run test:observability to verify failure metrics and trace correlation.
/w/{workspaceSlug}/events, with a secondary list viewOpen /w/{workspaceSlug}/captions on the booth PC. Use the options button (sliders icon) at the top right to choose and test the PC input that carries the speaking microphones from your mixer (the Setup and troubleshooting section there explains the wiring step by step), then press Start captions. Keep the booth Captions page open in its own tab or window during the broadcast; navigating that same tab to another page ends the booth stream. A short drop in the booth connection recovers by itself on the same session. If the booth page closes or crashes, press Start captions again: a session that has sent no heartbeat for two minutes is ended automatically and a new one starts.
One link for the congregation. Each church has one stable listener link, /captions/live/<token>, that does not change from week to week. Press the share icon at the top right to see it as text and as a QR code, with Copy link and Download QR (the QR code is drawn in your browser). Captions keep running when you move to another page in the app or switch windows: the session lives above the pages, its heartbeat runs in a worker, and the screen is kept awake while live. A purple pulsing microphone button at the bottom right shows it is still live from other pages, with Open Captions and Stop captions. Reloading the page reconnects to the same session and link by itself (if the browser allows the input again); closing the tab, shutting down or putting the computer to sleep ends captions, and the browser asks before you reload, close or sign out while live. Test this at the booth with docs/worship/captions-booth-checklist.md. Start and Stop only control whether captions are live: before the service the page says captions will start, and it checks again by itself, so listeners never need a new link. After Stop, the last ten lines stay readable for one hour. One session can run per workspace and expires after four hours. After Stop, the last ten lines stay readable for one hour and are then erased within a day (the daily keep-alive job clears what the feed no longer shows). Anyone with the link can read the captions, so share it only as widely as the sermon itself. The link and QR code are built from APP_URL: set it to your public https address (for example https://sndev-worship-flow.vercel.app), because the team alias and per-deployment addresses are behind a Vercel login and would not open for the congregation. The public feed is cached for a second while live and ten seconds while waiting, so its load does not grow with the audience. When the dev server runs against the hosted database, Start captions asks for an extra confirmation, because test captions would appear on the real congregation link. Regenerate link (Owner and Admin only, and not while captions run) makes a new link and stops every old link and printed QR code. In Settings → Membership, Admins grant View captions, Operate live captions, and Share captions link to Members; a Member needs View plus Operate to run the booth feed, and View plus Share to see the link.
Set DEEPGRAM_API_KEY, AZURE_TRANSLATOR_KEY, and AZURE_TRANSLATOR_REGION in the server environment. The Deepgram key needs Member permission to issue temporary browser tokens. The Azure Translator key and Deepgram API key must never use a NEXT_PUBLIC_ name. Apply the 20261027000000_caption_share_link migration (the Share permission and the CaptionSettings table), and the 20261025000000_sermon_captions_live, 20261025010000_caption_module_permissions, 20261025020000_caption_connection_state, 20261025030000_caption_usage_day, and 20261025040000_caption_usage_baseline Prisma migrations in each environment. Audio goes from the booth browser to Deepgram; recognized text goes through WorshipFlow to Azure. Viewers receive only English text from the temporary link.
Owner/Admin can open /w/{workspaceSlug}/settings?tab=usage to see the current UTC month's Azure characters. If a dated Azure Monitor baseline exists, the page shows the baseline plus later characters metered through this workspace as an estimate; use outside WorshipFlow after the export is excluded. The Angeles City Bible Church hosted development workspace has an October 2026 baseline of 8,538 characters from an Azure Monitor export ending October 25 at 19:54:44 Asia/Manila. For Deepgram project balances, also set server-only DEEPGRAM_PROJECT_ID and a separate DEEPGRAM_BILLING_API_KEY with billing access; without them, the page points to the Deepgram Console. The balance response does not identify free versus paid credits. The page does not stop broadcasts at a threshold.
To try the proposed yt-dlp worker flow without changing the app, install
yt-dlp and FFmpeg on your PATH, then run:
npm run try:media-worker
npm run try:media-worker -- --format mp4
The command creates a two-second local fixture, serves it on localhost, runs
yt-dlp and FFmpeg, and writes an MP3 or MP4 plus job.json under ignored
.tmp/media-worker-spike/<job-id>/. JSON status lines show queued,
processing, and done or failed. This verifies the local processing path;
it does not verify YouTube availability or permission to download a video.
For a YouTube video you have permission to download and convert, use the explicit opt-in:
npm run try:media-worker -- --url "https://www.youtube.com/watch?v=VIDEO_ID" --format mp3 --execute --rights-confirmed
The real URL mode accepts HTTPS YouTube URLs only, downloads one video, and limits the file to 100 MB. Keep this local experiment separate from the deployed app; the media converter remains disabled for web deployment.
WorshipService is the core domain object. One record represents one real
worship service.
New services copy all active blocks from the selected template. After creation, the service owns that stored order. UI code must render that order and must not replace it with a global hard-coded lineup.
See AGENTS.md for guardrails, docs/core/ for the product baseline, and DESIGN.md for the visual system.
tokens.cssRequirements:
Install dependencies:
npm install
Copy-Item .env.example .env
Put the hosted Supabase URL, publishable key, secret key, matching pooled
DATABASE_URL, and migration-safe DIRECT_DATABASE_URL in ignored .env.local.
Use .env for optional local settings. Start the local app against the hosted
project:
npm run dev
The default local URL is http://localhost:3000. Changes made through the app
appear in the hosted Supabase project selected by .env.local. npm run dev
checks that Auth, Storage, and Postgres target the same project before starting.
It does not apply schema migrations automatically; run and review migrations
separately before using new database fields. Do not run the seed script against
an existing hosted project unless you intend to add its sample records. This is
a live project connection,
so use a dedicated development project if you need isolated test data.
In Settings → Templates → Comment Card Name Template, administrators can save several default filenames and choose one active name. Comment Card loads the active name each time the module opens while keeping saved comment content and layout settings. Apply the checked-in Prisma migration before using this setting on a database.
For local sign-in with hosted Supabase, open that project's Authentication →
URL Configuration in the Supabase Dashboard. Keep the deployed app as the
Site URL and add http://localhost:3000/** to Redirect URLs. The app sends
http://localhost:3000/auth/callback with a next query parameter for Google
and email sign-in. Without the localhost allowlist entry, Supabase can return
to the deployed Site URL instead. supabase/config.toml only configures the
local Docker stack; it does not update hosted Auth settings.
Use this mode when the app, database, API, and authentication should all run against the local Docker Supabase stack.
Add the Google OAuth credentials to the ignored root .env file:
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID="your-google-client-id"
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_SECRET="your-google-client-secret"
In the same Google Cloud web OAuth client, add:
http://localhost:3000http://127.0.0.1:54321/auth/v1/callbackGoogle returns to Supabase at the second URL. Supabase then returns to the
app at http://localhost:3000/auth/callback; the app callback does not
belong in Google's redirect URI list.
Launch local Supabase and Next.js together:
npm run dev:docker
npm run dev:docker starts Docker Desktop automatically on Windows when needed, waits
for its daemon, starts the local Supabase Docker stack (excluding the optional
Vector log collector), then loads
.env.local.docker, and applies the checked-in Prisma migrations before Next.js
starts. On a fresh local database, it safely bootstraps the Prisma baseline before
applying future migrations. Those process variables override hosted values in .env.local, keeping the OAuth callback on
http://localhost:3000/auth/callback.
To copy only the remote workspaces where a locally signed-in user has active
membership, first create a local Auth account by signing in at
http://localhost:3000. Then, after making a local database backup, run:
node scripts/import-remote-workspace.mjs --email [email protected] --apply --reset-local
This replaces local app tables only. It preserves local Supabase Auth, maps the matching app user to the local Auth identity, and skips encrypted integrations and file-backed records until Storage objects are copied separately.
The deployed app remains separate: Vercel must use the hosted Supabase URL,
the hosted Supabase Site URL stays https://sndev-worship-flow.vercel.app, and
its redirect allowlist includes
https://sndev-worship-flow.vercel.app/auth/callback.
Required:
DATABASE_URL: pooled application connectionDIRECT_DATABASE_URL: direct connection for Prisma migrationsOptional:
APP_URL: public application URL used for invitation callbacksNEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: Supabase Auth SSR configurationSUPABASE_SECRET_KEY: server-only Supabase admin key for invitationsOPENAI_API_KEY: AI-assisted lyric cleanup and image generationCRON_SECRET: server-only secret (at least 32 random characters) that protects
/api/internal/keep-alive. Vercel Cron calls that route once a day (vercel.json) and sends the
secret as a bearer token; the route makes one small database write so a Supabase Free project is
not paused for inactivity. Set it in the Vercel project's Production environment. Without it the
route answers 503 and does nothing.GITHUB_TOKEN: server-only token with Issues write access for sending user
reports to Sijan079/WorshipFlow; create the issue and feedback labels
in that repository before enabling submissionsWORKSPACE_INTEGRATION_ENCRYPTION_KEY: server-only key used to encrypt workspace AI integration overridesNEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: realtime featuresSUPABASE_URL, SUPABASE_SECRET_KEY, and
SUPABASE_PRIVATE_BUCKET: private generated-output storageWORSHIP_WORKSPACE_SLUG: fallback workspace slug for local jobs; normally
leave this as defaultGEMINI_API_KEY and GEMINI_BACKGROUND_VIDEO_MODEL: optional video
generation configurationMEDIA_GENERATION_VIDEO_HOURLY_LIMIT and
MEDIA_GENERATION_VIDEO_DAILY_LIMIT: optional video generation limitsRemoved authentication settings:
APP_ACCESS_USERAPP_ACCESS_PASSWORDAPP_ACCESS_SESSION_SECRETThese belonged to the retired shared-password gate and should be removed from local and deployment environments. Supabase Auth is now the only supported application authentication mechanism.
See .env.example for the complete list.
Google sign-in is handled by Supabase Auth. The downloaded Google OAuth client
JSON (for example, client_secret*.json) is local setup material only; the app
does not read it. The repository ignores those files. Never copy the client
secret into source code, a NEXT_PUBLIC_* variable, or this repository.
https://<project-ref>.supabase.co/auth/v1/callback.NEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY in the local .env and deployment
environment. Set APP_URL to the app's public URL for callback redirects.The Google client secret belongs in Supabase's server-side provider settings, not in the app's environment variables. The app only receives Supabase's public URL and publishable key in the browser. If the secret has been exposed, rotate it in Google Cloud Console before continuing.
Supabase Auth provides user sessions and email invitations. Each church is a
workspace addressed at /w/{workspaceSlug}. Access requires an active
workspace membership. Owners and Admins can manage invitations. Members see only
what their per-module, per-action grants allow; the Member default for new
modules is no access. Accounts are for the church's tech team; congregants do
not log in and will see only the public site.
Provision a workspace with:
npm run provision:workspace -- --name "Example Church" --slug example --owner-email [email protected]
See Architecture for the tenancy boundary and Access and privacy for roles and grants.
npm run dev # Local Next.js with hosted Supabase
npm run dev:docker # Local development with Docker Supabase
npm run build # Prisma generation and production build
npm run lint # ESLint
npm test # Security and domain checks
npm run test:formatter-file -- "C:\\path\\song.docx" # Print formatter output for a DOCX or PDF
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 1920 --height 1080 # Render standard and text-clarity comparison PNGs without starting the app
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 1080 --height 2400 --crop 40,120,900,600 # Resize first, then crop in target pixels; use --trim for automatic post-resize border removal
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 2400 --height 2400 --fit fill # Fill the complete target without distortion by center-cropping overflow
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 2400 --height 2400 --fit fill --sharpness 0.9 # Compare edge-aware text sharpening; accepted range is 0 to 2
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 2400 --height 2400 --fit contain --ai # Add a local Real-ESRGAN comparison; the official portable model downloads once into .tmp/tools
npm run test:resize-image -- "C:\\path\\screenshot.png" --width 2400 --height 2400 --fit contain --ai --ai-provider openai --ai-region 300,200,1900,1400 # Retain the experimental OpenAI region-edit comparison
npm run test:song-editor # Document editing, pagination, and draft recovery tests
npm run test:formatter-drafts # Local PostgreSQL lifecycle/concurrency tests
npm run cleanup:formatter # Delete expired formatter payloads once; -- --watch repeats every five minutes
npm run verify:song-editor # Isolated browser fixture at http://127.0.0.1:4318
The song editor fixture uses test identity responses and the real editor/DOCX
code. It does not access workspace data. For the full authenticated workflow,
use npm run dev. The formatter supports editing and temporary cross-device
draft recovery. The normal development
command starts the five-minute draft cleanup runner. Production requires an authenticated cleanup schedule
(a secret-protected call to /api/internal/formatter-cleanup) before enabling
this workflow; no cloud scheduler is provisioned by local development.
For the real server-backed recovery hook in disposable local database fixtures:
node --env-file=.env.local.docker --experimental-strip-types scripts/verify-formatter-drafts.mjs.
This serves port 4319, creates isolated test identities, and removes them on
Ctrl+C. It never bypasses application authentication. Browser assertions live in
scripts/fixtures/assert-server-draft.js and assert-song-actions.js.
The formatter keeps zoom and save status in its separate top controls card.
At 50% or 75%, the editable viewer shows two pages when both fit; narrow
windows and phones remain single-column. DOCX downloads preserve the editor
filename and spaces (for example, Way Maker.docx) without adding -lyrics.
The browser regression scripts include scripts/fixtures/assert-song-two-pages.js
for desktop layout, selection, editing, undo and responsive fallback checks.
scripts/fixtures/assert-song-editor-focus.js covers later-page Enter/caret
scrolling, available-height layout, section highlighting and pinned outline
move controls.
scripts/fixtures/assert-song-ribbon.js verifies inline title editing, save
indicators, direct section actions, menu highlights and clear confirmation.
See DESIGN.md for the visual contract. Use semantic tokens, real domain data, restrained motion, visible focus states, and purposeful containment. Avoid ornamental gradients, glow, fake metrics, badge spam, repeated eyebrow copy, unnecessary card grids, and nested modal surfaces. Many users are elderly: favor plain wording and large targets.
Follow docs/core/Roadmap.md: finish deploying People and Ministries (applying the queued Servant drop), then a daily database keep-alive, Events repeat and headcounts, Announcements, and the public Page Builder site.