Skip to content

marprezd/synmet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

15 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Synmet - Development Activity Tracking Platform

Synmet is an open-source, SaaS-managed, and self-hosted development activity tracking platform with a strong emphasis on privacy and self-owned data.

🎯 Vision

Provide developers with a private, flexible, and transparent way to monitor their productivity and coding metrics without compromising their coding data.

✨ Core Features

  • πŸ“Š Heartbeat Tracking: Detailed recording of coding activity

    • File/entity being edited
    • Git project and branch information
    • Programming language used
    • Coding duration and timestamps
    • Activity type (coding, debugging, testing, etc.)
    • AI-assisted development time tracking
  • πŸ“ˆ Analytics & Metrics: Intuitive visualization of productivity patterns

    • Total coding time per day/week/month
    • Most-used programming languages
    • Streak of active days
    • Metrics per project
    • Export capabilities (GitHub, Images, PDF, JSON, CSV)
    • API consumption tracking
  • πŸ” Privacy First: 100% self-hosted

    • Your data stays in your infrastructure
    • Complete control over your data
    • No external telemetry or tracking
  • 🌍 Multi-language Support: Full support for multiple languages

    • Spanish (es)
    • English (en)
    • PortuguΓͺs (pt)
    • More coming soon...
  • πŸ”‘ API Keys: Integration with code editors

    • VS Code plugin (coming soon)
    • JetBrains IDEs plugin (coming soon)
    • Neovim plugin (coming soon)

πŸ› οΈ Tech Stack

This project is built with modern and robust technologies:

πŸš€ Quick Start

Prerequisites

  • Node.js 20+
  • pnpm 9+
  • PostgreSQL 14+ (local or remote)
  • Git

1. Clone the repository

git clone https://github.com/yourusername/synmet.git
cd synmet

2. Install dependencies

pnpm install

3. Configure environment variables

Copy and complete the environment file:

# For local development
cp .dev.vars.example .dev.vars

# Edit .dev.vars with your actual values

Required variables in .dev.vars:

# Database
DATABASE_URL="postgresql://user:password@localhost:5432/synmet_dev"

# NextAuth
NEXTAUTH_SECRET="openssl rand -hex 32"  # Generate with: openssl rand -hex 32
NEXTAUTH_URL="http://localhost:3000"

# GitHub OAuth (create at https://github.com/settings/developers)
GITHUB_ID="your-github-oauth-app-id"
GITHUB_SECRET="your-github-oauth-app-secret"

4. Configure the Database

# Generate Prisma client
pnpm generate

# Run migrations
pnpm migrate

# (Optional) Load test data
pnpm prisma db seed

5. Start the development server

pnpm dev

Open http://localhost:3000 in your browser.

πŸ“ Project Structure

synmet/
β”œβ”€β”€ src/                       # Source code
β”‚   β”œβ”€β”€ app/                   # Next.js App Router
β”‚   β”‚   β”œβ”€β”€ [locale]/          # i18n routing layer
β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ dashboard/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”‚   β”œβ”€β”€ settings/
β”‚   β”‚   β”‚   └── .../
β”‚   β”‚   └── api/                # API routes
β”‚   β”‚       β”œβ”€β”€ auth/           # Authentication
β”‚   β”‚       β”œβ”€β”€ heartbeat/      # Heartbeat tracking
β”‚   β”‚       β”œβ”€β”€ api-keys/       # API key management
β”‚   β”‚       β”œβ”€β”€ subscription/   # SaaS subscription
β”‚   β”‚       └── .../
β”‚   β”œβ”€β”€ components/            # React components
β”‚   β”‚   β”œβ”€β”€ ui/                # Reusable UI components
β”‚   β”‚   β”œβ”€β”€ dashboard/         # Dashboard components
β”‚   β”‚   └── .../
β”‚   β”œβ”€β”€ lib/                   # Utilities & services
β”‚   β”‚   β”œβ”€β”€ auth.ts            # Authentication logic
β”‚   β”‚   β”œβ”€β”€ subscription.ts    # SaaS subscription service
β”‚   β”‚   β”œβ”€β”€ ai-usage.ts        # AI usage tracking
β”‚   β”‚   β”œβ”€β”€ plan.ts            # Plan definitions
β”‚   β”‚   β”œβ”€β”€ validations/       # Zod schemas
β”‚   β”‚   └── .../
β”‚   β”œβ”€β”€ i18n/                  # Internationalization config
β”‚   β”œβ”€β”€ styles/                # Global styles
β”‚   └── middleware.ts          # Next.js middleware
β”œβ”€β”€ messages/                  # i18n translation files
β”‚   β”œβ”€β”€ es.json
β”‚   β”œβ”€β”€ en.json
β”‚   └── pt.json
β”œβ”€β”€ prisma/                    # Database
β”‚   β”œβ”€β”€ schema.prisma          # Database schema
β”‚   β”œβ”€β”€ migrations/            # DB migrations
β”‚   └── .../
β”œβ”€β”€ docs/                      # Documentation
β”‚   β”œβ”€β”€ SAAS-REFORMA-PLAN.md
β”‚   β”œβ”€β”€ TEST-PLAN.md
β”‚   └── .../
β”œβ”€β”€ public/                    # Static assets
β”œβ”€β”€ .github/workflows/         # CI/CD pipelines
β”œβ”€β”€ Dockerfile                 # Container setup
β”œβ”€β”€ docker-compose.yml         # Docker services
β”œβ”€β”€ next.config.ts             # Next.js config
β”œβ”€β”€ wrangler.jsonc             # Cloudflare Workers
└── .../

πŸ” Authentication

GitHub OAuth Setup

  1. Go to GitHub Settings β†’ Developer Settings β†’ OAuth Apps
  2. Click "New OAuth App"
  3. Fill in the following:
  4. Copy Client ID and Client Secret to .dev.vars

Protected Routes

Routes under /dashboard and /[locale]/dashboard require user authentication. Unauthenticated requests are redirected to the sign-in page.

🌍 Internationalization

The project supports multiple languages using next-intl:

messages/
β”œβ”€β”€ es.json  # Spanish
β”œβ”€β”€ en.json  # English
└── pt.json  # Portuguese

Language is automatically detected from the URL: /es/, /en/, /pt/

Default language is English. Users can switch languages by changing the URL prefix.

πŸ“Š Database

Core Models

  • User: System users with roles and sessions
  • Account: OAuth accounts (NextAuth integration)
  • Session: Authentication sessions
  • ApiKey: API keys for editor plugins
  • Project: User projects for organizing heartbeats
  • Heartbeat: Individual coding activity records
  • DailyMetrics: Aggregated daily metrics per user/project

Key Relations

  • User β†’ has many ApiKeys, Projects, Heartbeats, DailyMetrics
  • Project β†’ belongs to User, has many Heartbeats
  • Heartbeat β†’ belongs to User and Project
  • ApiKey β†’ belongs to User

See prisma/schema.prisma for complete schema details.

πŸš€ Deployment

To Cloudflare Workers

# Build and deploy
pnpm deploy

Requirements:

  • Cloudflare account with Workers enabled
  • Environment variables configured in Wrangler

GitHub Actions CI/CD

The project includes an automated CI/CD pipeline:

  • βœ… Lint and type-check on PRs
  • βœ… Build on each push to main
  • βœ… Automatic deploy to Cloudflare (main branch)
  • βœ… Docker image build and push

πŸ“ Available Scripts

# Development
pnpm dev              # Start development server
pnpm build            # Build for production
pnpm start            # Start production server
pnpm lint             # Run ESLint
pnpm lint:fix         # Fix ESLint issues

# Prisma
pnpm generate         # Generate Prisma client
pnpm migrate          # Run database migrations
pnpm studio           # Open Prisma Studio

# Deployment
pnpm preview          # Preview before deployment
pnpm deploy           # Deploy to Cloudflare
pnpm upload           # Upload to Cloudflare

πŸ›£οΈ Roadmap

Iteration 2 (Planned)

  • Real-time heartbeat collection
  • Interactive activity charts
  • Enhanced project management
  • User profile customization

Iteration 3 (Planned)

  • VS Code extension
  • JetBrains IDE plugin
  • Neovim plugin

Iteration 4 (Planned)

  • Stripe payment system
  • Subscription plans
  • Team management

Iteration 5+ (Future)

  • Share metrics publicly
  • Slack and Discord integrations
  • Custom webhooks
  • Data export features

⚠️ Known Issues & Technical Debt

API Key Expiration Status

Issue: API keys do not automatically transition from active to expired status when their expiration date passes.

Impact: Expired API keys may still appear as "active" in the UI and can be used to authenticate heartbeats until manually revoked.

Workaround: Manually revoke expired keys from the API Keys settings page.

Solution (Iteration 2): Implement one of the following:

  • Option A: Add a scheduled background job (cron) to mark expired keys as expired status
  • Option B: Validate API key expiration at auth time in the heartbeat validation middleware
  • Option C: Combine both approaches for comprehensive coverage

Affected Endpoints:

  • POST /api/heartbeat - Accepts expired keys
  • GET /api/api-keys - Shows expired keys as "active"

Related Tasks

  • Add expiration validation middleware for API key authentication
  • Implement background job for periodic status updates
  • Add visual warnings in UI for soon-to-expire keys
  • Add audit logging for key usage and expiration events

πŸ“„ License

This project is licensed under the Server Side Public License (SSPL).

The SSPL is designed to ensure that if you offer the functionality of this software as a service to third parties, you must make the service's source code available under this license. This protects against large cloud providers offering the software as a service without contributing back to the open source community.

For more details, see the SSPL FAQ.

πŸ™‹ Support


Made with ❀️ by @marprezd and the Synmet community

About

Synmet - Development Activity Tracking Platform

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors