TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
Management of lessons, gatherings and events for the family.
AI translation
ניהול שיעורים, מפגשים ואירועים למשפחה
ProductivityTypeScript · CSSGitHub @hadarsap1OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
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.Read the full 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.