Synaplan
기업을 위한 오픈소스 AI 플랫폼
스웨덴 건설 현장·플랜트 위험·사고·근접 사고(tillbud) 신고 SAM·Arbetsmiljöverket 기준에 부합
Report hazards, accidents and near-misses (tillbud) for Swedish construction sites and plants. SAM / Arbetsmiljöverket aligned.
비즈니스TypeScript · PLpgSQLGitHub @thealbayrak온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Mobile-first PWA for Swedish construction sites and plants: workers report near-misses (tillbud), hazards and accidents in three taps; the safety organisation follows up with CAPA, weekly skyddsronder (AFS 2001:1) and AML 3:3a notices to Arbetsmiljöverket.
npm install
npm run dev # http://localhost:3000 — demo mode until Supabase is configured
npm test # vitest unit tests
npm run lint
npm run typecheck
Copy .env.local.example to .env.local and set NEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (or ..._ANON_KEY). Both are public values.
Apply the schema (tables, RLS policies, RPCs, storage bucket, realtime):
npx supabase login
npx supabase link --project-ref <your-project-ref>
npx supabase db push
npx supabase db query -f supabase/seed.sql # optional demo sites and locations
Without the CLI, paste supabase/apply-all.sql (migrations + seed in one script) into the
SQL editor of the Supabase dashboard and run it. Regenerate it after editing a migration:
node scripts/build-apply-all.mjs
Create the safety officers' accounts under Authentication → Users (email + password, or invite by e-mail). Field workers never need an account.
| Role | Can |
|---|---|
| Anonymous visitor (field worker) | read sites and locations, submit a report through the submit_incident RPC, upload photos / voice notes |
| Signed-in user (safety officer) | read and update incidents, CAPA actions, skyddsronder and media |
The dashboard and /skyddsrond redirect to /login when Supabase is configured. Media lives in
the private incident-media bucket and is served through short-lived signed URLs.
Workers never sign in. Each company and each place has a report key; the QR code carries it (/report?k=<key>).
The submit_incident RPC refuses an anonymous report without the current key of that company or place, so the
form cannot be used for another company. A manager (or the owner) replaces a key in Settings / Projects and the
old printed code stops working at once. The RPC also limits reports per phone, per network and per company per
hour, and flags a report sent from outside the place (a flag, not a block). Signed-in people of the company
report without a key. Optional: Cloudflare Turnstile (NEXT_PUBLIC_TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY).
Staff see only the places a manager ticks for them (People page); managers see their whole company.
With NEXT_PUBLIC_ROOT_DOMAIN set, each company gets <slug>.<root domain> (add a wildcard domain in Vercel).
Set RESEND_API_KEY, SAFETY_ALERT_RECIPIENT (comma-separated allowed), optionally RESEND_FROM
and NEXT_PUBLIC_APP_URL. The browser pings /api/alerts/critical-incident after a report; the
route calls the claim_incident_alert RPC, which returns the incident only if it is critical and
has not been alerted before, so the e-mail can be neither forged nor duplicated.
For delivery that does not depend on the reporter's browser, add a Database Webhook in
Supabase (table incidents, event INSERT, URL https://<your-app>/api/alerts/critical-incident,
HTTP header x-alert-secret: <ALERT_WEBHOOK_SECRET>) and set ALERT_WEBHOOK_SECRET in the app.
app/ routes (report, dashboard, skyddsrond, login, api/alerts)
components/ UI: report wizard, dashboard, skyddsrond checklist, auth, shell
lib/data/ repository contract + Supabase and in-memory implementations
lib/supabase/ client/server factories, row mappers, hand-maintained DB types
lib/offline/ IndexedDB queue for reports written without a connection
lib/alerts/ critical-incident payload, parsing and e-mail template
lib/compliance/ AML 3:3a notice model and print template
supabase/ migrations, seed data, CLI config
tests/ vitest unit tests for the pure modules
public/sw.js caches the app shell (network-first for pages, cache-first for static assets) and is
registered in production builds only. iOS splash screens are generated by
node scripts/generate-ios-assets.mjs.