https://github.com/dorasto/sayr
Project management & feedback portal in one open defined tool
https://github.com/dorasto/sayr
feedback kanban project-management self-hosted user-feedback
Last synced: about 2 months ago
JSON representation
Project management & feedback portal in one open defined tool
- Host: GitHub
- URL: https://github.com/dorasto/sayr
- Owner: dorasto
- License: other
- Created: 2025-08-16T19:23:18.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-04-23T13:57:17.000Z (about 2 months ago)
- Last Synced: 2026-04-23T14:12:57.831Z (about 2 months ago)
- Topics: feedback, kanban, project-management, self-hosted, user-feedback
- Language: TypeScript
- Homepage: https://sayr.io
- Size: 6.5 MB
- Stars: 11
- Watchers: 0
- Forks: 1
- Open Issues: 41
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
- Agents: AGENTS.md
- Cla: CLA.md
Awesome Lists containing this project
README
# Sayr.io
**Project management your users can see.**
Sayr is a source-available project management platform with a built-in public-facing portal. Your team works internally while users submit feedback, vote on features, and track progress — all from the same tool.
[](https://www.typescriptlang.org/)
[](https://tanstack.com/start)
[](https://react.dev/)
[](https://hono.dev/)
[](https://bun.sh/)
---
## The Problem
Teams juggle a project management tool and a separate customer feedback tool — duplicated work, stale updates, and users who never know what's happening.
Sayr replaces both with one board, two views: your team sees everything, the public sees only what you allow.
---
## Features
### Task Management
- Tasks with statuses: Backlog, Todo, In Progress, Done, Canceled
- 5 priority levels: Urgent, High, Medium, Low, None
- Multiple assignees per task
- **Subtasks** — one level deep
- **Task relations** — Blocks, Depends on, Related to
- **Labels** — color-coded, multiple per task, with own visibility settings
- **Categories** — group tasks and route to GitHub repositories
- **Releases** — milestones/versions with progress charts, assignee workload, and priority distribution
- **Saved views** — filtered/grouped views persisted per organization
- **Issue templates** — pre-fill title, description, labels, assignees, category, priority, status, release, and visibility
- Kanban and list views
- Bulk operations (status changes, label assignment)
- Full audit timeline — every change recorded
### Visibility System
The core differentiator. Every item carries its own public/private toggle: tasks, comments (public vs. internal), labels, and timeline entries. Changes take effect immediately.
### Public Portal
- Each organization gets a dedicated subdomain (`{org}.sayr.io` on cloud, or your own domain when self-hosting)
- Live task board showing public tasks with sorting (Most Popular, Newest, Trending)
- User voting on tasks (real-time counts)
- Public task submission by signed-in visitors, optionally from a template
- Public comments with reactions; member badge distinguishes official responses
- Real-time updates via WebSocket
- Organization branding (banner, logo, name, description)
### GitHub Integration
- Connect one or more GitHub organizations via GitHub App
- Bidirectional task ↔ issue sync, per repository, optionally scoped by category
- Keyword references in commits and PRs: `Ref #N`, `Fixes #N`, `Closes #N`, `Resolves #N`
- Commit and PR lifecycle tracking appear on the task timeline
- Comment syncing from GitHub to Sayr
- Respects repository visibility (private repo activity stays internal)
### Collaboration & Real-Time
- Rich text editor (ProseKit) with headings, lists, code blocks, images, and @mentions
- Threaded comments with edit history and emoji reactions
- WebSocket broadcasting for all create/update/delete events
- Notifications and inbox
- My Tasks — cross-organization view of all assigned work
### Account & Security
- GitHub OAuth login
- Email + password authentication
- **Two-factor authentication** (TOTP + backup codes)
- **Passkeys** — Face ID, Touch ID, Windows Hello, hardware security keys (WebAuthn)
- Active session management — view and revoke individual sessions
### Organization Management
- Members and teams with granular per-permission controls
- Permission categories: Organization, Content Settings, Tasks, Moderation
- "Most permissive wins" model across team memberships
- Blocked users list
### API
- REST API with OpenAPI spec (served via Scalar)
- Bearer token authentication
- Rate limiting: 100 req/min authenticated, 10 req/min unauthenticated
---
## Editions
Sayr ships in three editions. Docker images are edition-locked at build time.
| | Community | Cloud | Enterprise |
|---|---|---|---|
| **For** | Free self-hosting | Hosted sayr.io | Licensed self-hosting |
| **Organizations** | 1 | Unlimited | Unlimited |
| **Members** | Unlimited | Free: 5 / Pro: unlimited | Unlimited |
| **Releases** | Unlimited | Free: 0 / Pro: unlimited | Unlimited |
| **Saved views** | Unlimited | Free: 3 / Pro: unlimited | Unlimited |
| **Issue templates** | Unlimited | Free: 3 / Pro: unlimited | Unlimited |
| **Teams** | Unlimited | Free: 1 / Pro: unlimited | Unlimited |
| **Availability** | Now | Now | Coming soon |
Community Edition images are published at `ghcr.io/dorasto/sayr-ce-*`.
---
## Tech Stack
### Frontend
| Technology | Purpose |
|------------|---------|
| [TanStack Start](https://tanstack.com/start) | Full-stack React framework (SSR + server functions) |
| [React](https://react.dev/) | UI library |
| [TanStack Router](https://tanstack.com/router) | Type-safe file-based routing |
| [TanStack Query](https://tanstack.com/query) | Server state management |
| [Tailwind CSS](https://tailwindcss.com/) | Utility-first CSS |
| [Shadcn/ui](https://ui.shadcn.com/) | Accessible component library (Radix primitives) |
| [ProseKit](https://prosekit.dev/) | Block-based rich text editor (ProseMirror) |
| [Vite](https://vite.dev/) | Build tool |
### Backend
| Technology | Purpose |
|------------|---------|
| [Bun](https://bun.sh/) | JavaScript runtime |
| [Hono](https://hono.dev/) | Lightweight web framework (REST + WebSocket) |
| [Drizzle ORM](https://orm.drizzle.team/) | TypeScript ORM |
| [PostgreSQL](https://www.postgresql.org/) | Primary database |
| [Redis](https://redis.io/) | Job queue and caching |
| [MinIO](https://min.io/) | S3-compatible object storage |
| [Zod](https://zod.dev/) | Validation |
### Infrastructure & Tooling
| Technology | Purpose |
|------------|---------|
| [Turborepo](https://turbo.build/repo) | Monorepo build orchestration |
| [pnpm](https://pnpm.io/) | Package manager |
| [Biome](https://biomejs.dev/) | Linting and formatting |
| [TypeScript](https://www.typescriptlang.org/) | Type-safe JavaScript throughout |
| [Docker](https://www.docker.com/) | Containerization |
| [Nginx](https://nginx.org/) | Reverse proxy and subdomain routing |
---
## Project Structure
```
sayr/
├── apps/
│ ├── backend/ # Hono API server (Bun runtime, port 5468)
│ ├── marketing/ # Astro marketing site + Starlight docs (port 3001)
│ ├── nginx/ # Nginx reverse-proxy config
│ ├── start/ # TanStack Start frontend (port 3000)
│ ├── traefik/ # Traefik TLS termination config
│ └── worker/ # Background job processor (GitHub webhooks, cron)
└── packages/
├── auth/ # Better Auth configuration
├── database/ # Drizzle ORM schemas and CRUD functions
├── edition/ # Edition detection, capabilities, and plan limits
├── opentelemetry/ # Tracing and observability utilities
├── queue/ # Job queue abstraction (Redis or file-based)
├── storage/ # MinIO/S3 client with obfuscated filenames
├── ui/ # Shared Shadcn/ui component library
├── util/ # Shared utilities (slugs, date formatting, CDN URLs)
└── typescript-config/# Shared TypeScript configurations
```
---
## Getting Started
### Prerequisites
- **Bun** 1.2+
- **Node.js** 22+ (LTS)
- **pnpm** 10.6+ (`npm install -g pnpm`)
- **PostgreSQL** 15+
- **Redis** (required for the job queue in production)
- **Docker** (optional, for containerized development)
### Available Commands
#### Root
| Command | Description |
|---------|-------------|
| `pnpm dev` | Start all apps in development mode |
| `pnpm build` | Build all apps for production |
| `pnpm lint` | Run Biome linting |
| `pnpm lint:fix` | Fix linting issues |
| `pnpm format-write` | Format code with Biome |
| `pnpm check-types` | TypeScript type checking |
#### Per App/Package
| Command | Description |
|---------|-------------|
| `pnpm -F backend dev` | Backend only |
| `pnpm -F start dev` | Frontend only |
| `pnpm -F marketing dev` | Marketing site only |
| `pnpm -F worker dev` | Worker only |
| `pnpm -F @repo/database generate` | Generate database schema |
| `pnpm -F @repo/database migrate` | Apply schema migrations |
| `pnpm -F @repo/database db:studio` | Open Drizzle Studio |
| `pnpm -F start test` | Run tests (Vitest) |
---
## Integrations
Sayr supports extensible integrations that can add custom API routes and UI pages.
### Creating an Integration
Use the create-integration scaffolding tool:
```bash
pnpm create-integration -a -d
```
This generates a new integration in `packages/integrations/` with:
- **API Routes** — Custom REST endpoints (`/api/integrations/:orgId/:integrationId/...`)
- **UI Pages** — Admin pages rendered from config (cards, lists, tabs, grids)
- **Settings** — Per-organization configuration
### Integration Structure
```
my-integration/
├── api/
│ └── index.ts # API route handlers
├── src/
│ └── index.ts # Business logic, commands, utilities
├── ui/
│ ├── pages.ts # UI page config (settings, items, sync, etc.)
│ ├── renderer.tsx # Reusable UI components
│ └── components/ # Custom React components
├── integration.ts # Manifest registration
├── docs.ts # Documentation
└── README.md # Integration-specific docs
```
### UI Page Configuration
Pages are defined with a declarative config:
```typescript
const settingsPage: UIPage = {
title: "Settings",
layout: "admin",
api: {
path: "/settings",
methods: { get: {}, patch: {} },
},
sections: [
{
type: "card",
title: "Configuration",
fields: [
{ name: "apiKey", type: "string", label: "API Key", required: true },
{ name: "enabled", type: "boolean", label: "Enabled" },
],
actions: [{ type: "save", label: "Save" }],
},
],
};
```
### Available Section Types
| Type | Description |
|------|-------------|
| `card` | Card with fields and optional actions |
| `list` | Table or card list with CRUD actions |
| `tabs` | Tabbed sections |
| `grid` | Multi-column grid layout |
### Field Types
- `string`, `number` — Text/number input
- `boolean` — Checkbox
- `select` — Dropdown with options
- `textarea` — Multi-line text
- `readonly` — Display-only field
- `heading`, `label` — Typography
### Data Binding
Use `bind` to extract nested data from API responses:
```typescript
{ name: "status", type: "readonly", bind: "$.preview.status" }
{ name: "data", type: "readonly", bind: "$.preview.stringify" } // JSON stringify
```
### Enabling an Integration
```bash
export INTEGRATION_MYINTEGRATION_ENABLED=true
```
Then configure per-organization in the admin UI.
---
## Contributing
### Development Workflow
1. Fork the repository
2. Create a feature branch: `git checkout -b feat/my-feature`
3. Make your changes following the code style guidelines below
4. Push and open a Pull Request
### Code Style
- **Indentation**: Tabs, width 3
- **Line width**: 120 characters
- **Quotes**: Double quotes, semicolons always
- **Imports**: Use `@repo/*` for workspace packages, `@/` for local app imports
- **TypeScript**: Strict mode, avoid `any`, use `import type` for type-only imports
- **Naming**: camelCase for variables/functions, PascalCase for components/types
### Commit Convention
We follow [Conventional Commits](https://www.conventionalcommits.org/):
- `feat:` — New features
- `fix:` — Bug fixes
- `docs:` — Documentation changes
- `style:` — Formatting only
- `refactor:` — Code refactoring
- `test:` — Tests
- `chore:` — Maintenance
---
## Acknowledgments
- [Turborepo](https://turbo.build/repo) for monorepo tooling
- [Shadcn/ui](https://ui.shadcn.com/) for accessible components
- [Better Auth](https://www.better-auth.com/) for authentication
- [Drizzle ORM](https://orm.drizzle.team/) for type-safe database operations
- [Hono](https://hono.dev/) for the fast, lightweight web framework
- [TanStack](https://tanstack.com/) for the excellent full-stack toolkit
---
Made with care by Doras Media Ltd