danwel



What Is It?

danwel is a multi-tenant SaaS application that helps organizations manage their weekly time planning with seamless integration to external calendar and invoicing systems.

**Core idea**: Plan your week visually, sync to your calendar, track time for invoicing—all in one place.

---

The Problem



Freelancers and teams juggle multiple tools:
  • • Google Calendar / Outlook for scheduling

  • • Moneybird / Harvest for time tracking & invoicing

  • • Manual copy-paste between systems

  • • No unified view of "what am I working on this week?"


  • **Pain points:**
  • • Double entry (calendar + time tracker)

  • • Forgetting to log billable hours

  • • No visual weekly planning tool that connects everything

  • • Teams can't see each other's availability
  • ---

    The Solution



    A weekly planner that:
    1. **Shows your week** in a clean, visual grid (Mon-Sun, 8am-6pm)
    2. **Syncs bidirectionally** with Google Calendar / Office 365
    3. **Logs time automatically** to Moneybird / Harvest
    4. **Works for teams** with shared visibility and organization management

    ┌─────────────────────────────────────────────────────────────┐
    │ danwel │
    │ │
    │ Plan Block ──► Syncs to Google Calendar │
    │ │ │
    │ └───────► Logs to Moneybird (billable time) │
    │ │
    │ Team members see shared calendar, plan together │
    └─────────────────────────────────────────────────────────────┘

    ---

    Who Is It For?



    Primary Users


  • • **Freelancers** managing multiple clients

  • • **Small agencies** (2-20 people) needing team visibility

  • • **Consultants** billing hourly to different projects


  • User Roles


    | Role | Can Do |
    |------|--------|
    | **Owner** | Everything + billing + delete org |
    | **Admin** | Manage team, integrations, see all time blocks |
    | **Member** | Create/edit own time blocks, view clients/projects |
    | **Viewer** | Read-only access to calendar |

    ---

    Key Features



    Implemented Features


  • • [x] Weekly calendar grid with drag-drop time blocks

  • • [x] Horizontal scroll for calendar (smooth day navigation)

  • • [x] Google Calendar integration (read/write with two-way sync)

  • • [x] Moneybird integration (time entries, clients, projects, invoices)

  • • [x] Multi-tenant organizations

  • • [x] Multiple calendars per integration

  • • [x] User preferences (timezone, work hours, work days, locale)

  • • [x] Statistics & analytics dashboard

  • • [x] Income tracking with hourly rates

  • • [x] Invoice sync from Moneybird

  • • [x] Favorites for clients and projects

  • • [x] External event import with client/project assignment

  • • [x] Billable vs non-billable tracking

  • • [x] Privacy controls (show/hide external event details)

  • • [x] Multi-language support (EN/NL)


  • Additional Implemented Features


  • • [x] Team invitations and roles

  • • [x] Advanced authentication (OAuth, WebAuthn, 2FA)

  • • [x] Task/Entry management system with comments and labels

  • • [x] GitHub integration for project management

  • • [x] Platform administration with impersonation

  • • [x] Multi-language support (EN/NL)

  • • [x] Demo mode with restrictions

  • • [x] Mobile app support with token generation

  • • [x] Billing integration with VAT validation

  • • [x] Favorites system for clients/projects

  • • [x] Advanced user preferences and privacy controls

  • • [x] Audit logging and system monitoring


  • Future Enhancements


  • • [ ] Office 365 calendar integration

  • • [ ] Harvest integration

  • • [ ] Mobile/tablet PWA

  • • [ ] Recurring time blocks

  • • [ ] Subdomain per organization
  • ---

    How It Works



    1. Sign Up & Create Organization


    User registers → Creates "Acme Agency" org → Becomes owner


    2. Connect Integrations


    Settings → Connect Google Calendar → Select calendars to sync
    Settings → Connect Moneybird → Clients & projects imported


    3. Plan Your Week


    Drag to create block → Saved to DB instantly → Background sync to Calendar/Moneybird


    4. Invite Team


    Settings → Team → Invite colleague → They join with "member" role

    ---

    Data Strategy



    Source of Truth: danwel Database



    ┌─────────────────────────────────────────────────────────────────┐
    │ danwel Database │
    │ (Source of Truth) │
    └─────────────────────────────────────────────────────────────────┘
    │ │
    ▼ ▼
    ┌─────────────┐ ┌─────────────┐
    │ Google │ │ Moneybird │
    │ Calendar │ │ │
    │ (Mirror) │ │ (Mirror) │
    └─────────────┘ └─────────────┘


    **Why local DB, not Google Calendar as source of truth?**
  • • **Offline resilience** - Works even if Google/Moneybird is down

  • • **Fast UI** - Load instantly from DB, sync in background

  • • **Data ownership** - You control your data

  • • **Reporting** - Query hours per client, trends, etc.

  • • **Provider flexibility** - Switch calendar providers without losing data


  • **Sync approach:**
    1. Save to database immediately (instant UI response)
    2. Queue background job to sync to external services
    3. Show sync status: ✓ synced, ⟳ pending, ⚠ error
    4. Periodic inbound sync pulls external changes

    ---

    Data Model (Simplified)



    Organization (tenant)
    ├── Users (with roles: owner/admin/member/viewer)
    │ └── Preferences
    │ ├── timezone (e.g., 'Europe/Amsterdam')
    │ ├── work_days (e.g., ['mon','tue','wed','thu','fri'])
    │ ├── work_hours_start (e.g., '08:00')
    │ └── work_hours_end (e.g., '18:00')
    ├── Integrations
    │ ├── Google Calendar → Calendars (multiple)
    │ └── Moneybird → Clients, Projects
    └── Time Blocks
    ├── Synced to calendar
    └── Synced to invoicing

    ---

    Technical Approach



    | Aspect | Choice |
    |--------|--------|
    | **Framework** | Laravel 11 |
    | **Multi-tenancy** | Single DB with organization_id scoping |
    | **Frontend** | Blade + Alpine.js + Tailwind |
    | **Integrations** | Strategy pattern (pluggable providers) |
    | **Security** | Encrypted OAuth tokens, 5-layer access control |
    | **Deployment** | SpinupWP (MySQL, Redis, PHP 8.2+) |

    ---

    Integration Architecture



    **Extensible by design**—adding a new provider (e.g., Office 365) requires:
    1. Implement CalendarProviderInterface
    2. Add config entry
    3. Register in service provider

    No changes to core application logic.

    CalendarProviderInterface
    ├── GoogleCalendarProvider ✓
    ├── Office365CalendarProvider (future)
    └── [Your Provider Here]

    InvoicingProviderInterface
    ├── MoneybirdProvider ✓
    ├── HarvestProvider (future)
    └── [Your Provider Here]

    ---

    Security Highlights



  • • **Tenant isolation**: Global scopes prevent cross-organization data access

  • • **Token encryption**: OAuth tokens stored with AES-256 encryption

  • • **Role-based access**: Policies enforce permissions at every level

  • • **Audit logging**: Sensitive operations tracked

  • • **No secrets in code**: All credentials via environment variables
  • ---

    What Already Exists (Prototype)

    The original prototype is preserved in initial_prototype/ (~2,500 lines):

    Files


    | File | Purpose | Lines |
    |------|---------|-------|
    | initial_prototype/config.php | OAuth credentials, constants | 44 |
    | initial_prototype/index.php | Settings page (connection status) | 182 |
    | initial_prototype/callback.php | Google OAuth callback | ~90 |
    | initial_prototype/moneybird-callback.php | Moneybird OAuth callback | ~87 |
    | initial_prototype/disconnect.php | Google disconnect | 15 |
    | initial_prototype/moneybird-disconnect.php | Moneybird disconnect | 11 |
    | initial_prototype/oauth-relay.php | Localhost OAuth relay (Google) | 18 |
    | initial_prototype/moneybird-relay.php | Localhost OAuth relay (Moneybird) | 18 |
    | initial_prototype/api.php | JSON API backend | 758 |
    | initial_prototype/calendar.php | Calendar UI + JavaScript | 1,434 |

    Working Features


  • • **Google Calendar OAuth** - Full flow with token refresh

  • • **Moneybird OAuth** - Full flow with token refresh

  • • **Weekly Calendar UI** - Mon-Sun, 8am-6pm grid

  • • **Drag-and-drop** - Move and resize time blocks (using interact.js)

  • • **Week navigation** - Previous/next week, week picker

  • • **Time block CRUD** - Create, update, delete via API

  • • **Bidirectional sync** - Events sync to Google Calendar

  • • **Moneybird time entries** - Auto-create time entries when blocks created

  • • **Clients/Projects** - Load from Moneybird, create new inline

  • • **External events** - Display non-danwel Google Calendar events (read-only)

  • • **Metadata on external events** - Assign project/client to any event

  • • **Color coding** - danwel events (teal), external events (Google colors)

  • • **Summary row** - Total hours per day and week


  • Token Storage (Prototype - File-based)


  • initial_prototype/token.json - Google OAuth tokens

  • initial_prototype/moneybird_token.json - Moneybird OAuth tokens + administration ID


  • Known Limitations (Why Rebuild)


  • • Single-user only (no multi-tenancy)

  • • File-based token storage (not secure for production)

  • • No authentication/authorization

  • • No database (relies on Google Calendar as source of truth)

  • • Hardcoded config values

  • • No team features

  • • Fixed 8am-6pm, Mon-Sun (no customization)
  • **This will be rebuilt** using proper Laravel architecture with multi-tenancy.

    ---

    Success Metrics



    1. **User activation**: User connects at least one integration within 24h
    2. **Weekly active**: User creates 5+ time blocks per week
    3. **Team adoption**: 50% of org members active weekly
    4. **Sync reliability**: 99.9% successful syncs to external services

    ---

    Open Questions



    1. **Billing model**: Per-seat? Per-org? Free tier limits?
    2. **Conflict resolution**: What if calendar event edited externally?
    3. **Offline support**: How important for MVP?
    4. **White-label**: Should orgs customize branding?

    ---

    Documentation

    For detailed technical documentation, see:

  • • [ARCHITECTURE.md](./ARCHITECTURE.md) - Core architecture decisions, multi-tenancy, security

  • • [DATABASE.md](./DATABASE.md) - Database schema and migrations

  • • [INTEGRATIONS.md](./INTEGRATIONS.md) - Provider interfaces, OAuth flows, data sync

  • • [API.md](./API.md) - RESTful API endpoints and formats

  • • [FRONTEND.md](./FRONTEND.md) - UI requirements and components

  • • [IMPLEMENTATION.md](./IMPLEMENTATION.md) - Phased implementation plan


  • **Phase 1 starts with:**
    1. Fresh Laravel 11 installation
    2. Multi-tenancy foundation (organizations, users, roles)
    3. Integration framework
    4. Google Calendar provider
    5. Moneybird provider
    6. Calendar UI