TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A family scheduling platform for Israeli parents and teachers. Manage children's lessons, playdates, and personal events in one place — with Google Calendar sync and daily email digests.README 전문 보기 ↗A family scheduling platform for Israeli parents and teachers. Manage children's lessons, playdates, and personal events in one place — with Google Calendar sync and daily email digests.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, React 19) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4, shadcn/ui, Lucide icons |
| Auth | NextAuth.js 4 (Google OAuth) |
| Database | PostgreSQL (Neon serverless) via Prisma 7 |
| Resend | |
| Calendar | Google Calendar API v3 |
| Testing | Playwright (E2E) |
| Deployment | Vercel |
git clone <repo-url>
cd otef-parents
npm install
Copy .env.example to .env.local and fill in the values:
# Database (Neon PostgreSQL)
DATABASE_URL="postgresql://[USER]:[PASSWORD]@[HOST].neon.tech/[DBNAME]?sslmode=require"
# NextAuth
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="<generate with: openssl rand -base64 32>"
# Google OAuth
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
# Resend (email)
RESEND_API_KEY=""
# Cron job authentication
CRON_SECRET=""
npx prisma generate
npx prisma db push
Optional — seed sample data:
npx tsx scripts/seed-groups.ts
npm run dev
Open http://localhost:3000.
src/
├── app/
│ ├── api/ # API routes (52 endpoints)
│ │ ├── auth/ # NextAuth handler
│ │ ├── children/ # Child CRUD + invite codes
│ │ ├── groups/ # Group management
│ │ ├── schools/ # School management + import
│ │ ├── playdates/ # Playdate CRUD + join
│ │ ├── schedule/ # Schedule items
│ │ ├── lessons/ # Recurring lessons
│ │ ├── events/ # Personal events
│ │ ├── calendar/ # Google Calendar sync
│ │ ├── dashboard/ # Daily feed data
│ │ ├── admin/ # Admin endpoints
│ │ ├── cron/ # Daily digest cron job
│ │ └── account/ # User account + Google disconnect
│ ├── dashboard/ # Authenticated app pages
│ │ ├── children/ # Manage children
│ │ ├── playdates/ # Browse playdates
│ │ ├── lessons/ # View lessons
│ │ ├── teacher/ # Teacher dashboard
│ │ ├── admin/ # Admin panel
│ │ ├── settings/ # User preferences
│ │ └── help/ # Help & FAQ
│ ├── login/ # Sign-in page
│ ├── privacy/ # Privacy policy
│ ├── terms/ # Terms of service
│ └── walkthrough/ # Onboarding flow
├── components/ # React components
│ ├── ui/ # shadcn/ui base components
│ ├── daily-feed.tsx # Main schedule view
│ ├── add-lesson-dialog.tsx
│ ├── add-to-calendar-button.tsx
│ ├── teacher-dashboard-tabs.tsx
│ ├── admin-panel.tsx
│ └── ...
├── lib/
│ ├── auth.ts # NextAuth config + role helpers + requireAdmin()
│ ├── google-calendar.ts # Calendar API client
│ ├── email.ts # Resend email + digest formatting
│ ├── prisma.ts # Prisma client
│ ├── import-parsers.ts # CSV/XLSX import parsing
│ ├── rate-limit.ts # In-memory rate limiter
│ ├── validation.ts # Input sanitization + validation helpers
│ └── format.ts # Date/time utilities
└── types/ # TypeScript definitions
prisma/
├── schema.prisma # Database schema (14 models)
└── migrations/ # Migration history
scripts/
├── seed-groups.ts # Seed sample groups
├── seed-mock-playdate.ts # Seed test playdates
└── migrate-default-school.ts # Default school migration
e2e/ # Playwright tests (8 specs)
Key models:
PARENT, TEACHER, ADMIN, SUPERADMINChildParent (supports co-parenting)Invite codes (ChildInvite, GroupInvite) are 6-character, single-use, 24-hour expiry.
The app uses Google OAuth for authentication and Calendar API for event sync.
Scopes requested:
| Scope | Purpose |
|---|---|
openid | Google Sign-In |
email | User identification + digest emails |
profile | Display name and avatar |
calendar.events | Sync lessons, playdates, and events to Google Calendar |
The app only creates and deletes events it owns — it never reads or modifies existing calendar data. Users can disconnect Google Calendar from Settings at any time.
Offline access is enabled so the daily digest cron can manage calendar events without the user being logged in.
| Job | Schedule | Description |
|---|---|---|
| Daily Digest | 0 6 * * * (6 AM UTC) | Sends personalized email summaries to users with digest enabled, respecting their preferred time in Israel timezone |
Configured in vercel.json and secured with CRON_SECRET.
# Run E2E tests
npx playwright test
# Run with UI
npx playwright test --ui
Tests cover: login page, auth redirects, API protection, PWA manifest, RTL layout, input validation, static assets, and accessibility.
Config: Chromium, he-IL locale, Asia/Jerusalem timezone, port 3002.
Hardened per Web Application Security for AI Agents (CandleKeep).
src/middleware.ts) protects all /dashboard/* and /api/* routes — defense-in-depth on top of per-route auth checksPARENT, TEACHER, ADMIN, SUPERADMIN) enforced via requireRole() and requireSchoolRole() helpersrequireAdmin() in lib/auth.ts — single source of truth for SUPERADMIN checksTEACHER and above — parents cannot self-elevatelib/validation.ts)sanitizeString(input, maxLength) — trims and enforces length limits on every text input across all 30+ API routesisValidEmail() — format validation on email inputsisValidUrl() — protocol validation (http/https only) on all Zoom/URL fieldslib/rate-limit.ts)In-memory per-process rate limiter on critical endpoints:
| Endpoint | Limit | Window |
|---|---|---|
| Invite code redemption | 10 requests | 60s per user |
| Admin child search | 30 requests | 60s per admin |
| Bulk import | 5 requests | 60s per user |
{ error: string } JSON with appropriate HTTP status codeshttp(s):// before storage and renderingcrypto.randomBytes(), not Math.random()Configured in next.config.ts:
Content-Security-Policy — restricts script, style, img, connect, and frame sourcesCross-Origin-Opener-Policy: same-origin-allow-popupsStrict-Transport-Security (HSTS with preload, 2-year max-age)X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: strict-origin-when-cross-originPermissions-Policy (camera, microphone, geolocation disabled)/api/cron/daily-digest requires a Bearer token matching CRON_SECRETCRON_SECRET is not configured (prevents Bearer undefined bypass).env* files excluded in .gitignoreopenssl rand -base64 32NEXT_PUBLIC_ prefix on any secretDeployed on Vercel. The build command runs Prisma generate before Next.js build:
prisma generate && next build
he-IL) as primary languageAsia/Jerusalem)Private project.