Skip to content

Latest commit

 

History

History
315 lines (233 loc) · 11.9 KB

File metadata and controls

315 lines (233 loc) · 11.9 KB

Contributing to unsight.dev

Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to unsight.dev.

Important

Please be respectful and constructive in all interactions. We aim to maintain a welcoming environment for all contributors. Read our Code of Conduct

Goals

unsight.dev helps detect duplicate GitHub issues, areas of concern, and more across related repositories. It uses AI-powered embeddings and clustering to surface patterns that are hard to spot manually.

Table of Contents

Getting started

Prerequisites

Quick start (UI only)

If you just want to work on the frontend/UI, you can use the deployed API as a backend:

corepack enable
pnpm install
pnpm dev --ui-only

This starts a local dev server at http://localhost:3000 using the remote API at https://unsight.dev to populate it.

Full development setup

A full development environment requires a GitHub App and Cloudflare integration. See the Development environment section in the README for the complete walkthrough, which covers:

  1. Starting a local tunnel (ngrok)
  2. Creating a GitHub App for development
  3. Configuring secrets (.env file)
  4. Linking your Cloudflare account via NuxtHub

Project structure

unsight.dev is a pnpm monorepo with two packages:

unsight.dev/
├── packages/
│   ├── web/                       # Nuxt 4 web application
│   │   ├── app/
│   │   │   ├── components/        # Vue components
│   │   │   ├── composables/       # Vue composables
│   │   │   ├── pages/             # File-based routing
│   │   │   └── app.vue            # Root component
│   │   ├── server/
│   │   │   ├── api/               # API routes (Nitro)
│   │   │   ├── db/                # Drizzle schema + migrations
│   │   │   ├── routes/            # Server routes (webhooks, auth)
│   │   │   ├── tasks/             # Background tasks (indexing, cleanup)
│   │   │   └── utils/             # Server utilities (AI, clustering, etc.)
│   │   ├── modules/               # Custom Nuxt modules
│   │   ├── nuxt.config.ts
│   │   └── uno.config.ts
│   │
│   └── extension/                 # Browser extension (Chrome + Firefox)
│       ├── components/            # Vue components
│       ├── entrypoints/           # WXT content script entry
│       └── wxt.config.ts
│
├── eslint.config.js               # Root ESLint config
├── vite.config.ts                 # vite-plus config (pre-commit hooks)
└── package.json                   # Workspace root

Tip

For more about the Nuxt directory conventions, check out the Nuxt directory structure docs.

Development workflow

Available commands

From the repository root:

# Development
pnpm dev                 # Start web app dev server
pnpm dev --ui-only       # Start with remote API (no GitHub App needed)
pnpm dev:ext             # Start browser extension dev server

# Code quality
pnpm lint                # Run ESLint across the monorepo
pnpm test:types          # TypeScript type checking (all packages)
pnpm test:unit           # Run unit tests (all packages)

From packages/web/:

pnpm build               # Production build
pnpm preview             # Preview production build
pnpm db:generate         # Generate Drizzle ORM migrations

From packages/extension/:

pnpm dev                 # Dev mode (Chrome)
pnpm dev:firefox         # Dev mode (Firefox)
pnpm build               # Build for Chrome
pnpm build:firefox       # Build for Firefox
pnpm zip                 # Zip for Chrome Web Store
pnpm zip:firefox         # Zip for Firefox Add-ons

Preset repos for development

By default, the dev server auto-indexes nuxt/module-builder and nuxt/cli so you can see clusters without installing the GitHub App on any repositories.

You can customise this with the DEV_REPOS_TO_INDEX environment variable:

# disable entirely
DEV_REPOS_TO_INDEX=false

# specify custom repos
DEV_REPOS_TO_INDEX=unjs/h3,vuejs/core

Environment variables

See the README for the full list of required environment variables. The key ones are:

Variable Purpose
NUXT_WEBHOOK_GITHUB_SECRET_KEY GitHub webhook secret
NUXT_GITHUB_APP_ID GitHub App ID
NUXT_GITHUB_PRIVATE_KEY GitHub App private key (PKCS#8 format)
NUXT_PUBLIC_GITHUB_APP_SLUG Your GitHub App slug
NUXT_OAUTH_GITHUB_CLIENT_ID GitHub OAuth client ID
NUXT_OAUTH_GITHUB_CLIENT_SECRET GitHub OAuth client secret
NUXT_SESSION_PASSWORD Session encryption password
NUXT_CLOUDFLARE_ACCOUNT_ID Cloudflare account ID (for local dev AI without Workers bindings)
NUXT_CLOUDFLARE_API_TOKEN Cloudflare API token (for local dev AI without Workers bindings)
NUXT_HUB_PROJECT_KEY NuxtHub project key (auto-generated)
DEV_REPOS_TO_INDEX Preset repos for local dev

Tech stack

Layer Technology
Framework Nuxt 4 (Vue 3)
Server engine Nitro
Styling UnoCSS (with Tailwind compat reset)
UI primitives Reka UI
Database Cloudflare D1 (SQLite) via Drizzle ORM
Vector search Cloudflare Vectorize
AI / Embeddings Cloudflare Workers AI
Clustering ml-kmeans + ml-distance
GitHub integration GitHub App via @octokit/rest
Authentication GitHub OAuth via nuxt-auth-utils
Deployment Cloudflare Workers via NuxtHub
Extension framework WXT + Vue 3
Package manager pnpm (monorepo workspaces)
Task runner vite-plus (vp)
Linting ESLint 9 (flat config) with @antfu/eslint-config
Type checking TypeScript + vue-tsc
CI GitHub Actions

Code style

Formatting is handled entirely by ESLint's stylistic rules via @antfu/eslint-config -- there is no Prettier in this project.

When committing, a pre-commit hook runs ESLint --fix on staged files automatically (via vite-plus). If you want to lint everything ahead of time:

pnpm lint

TypeScript

  • Avoid any -- use proper types
  • Validate inputs rather than just asserting types

Vue components

  • Use Composition API with <script setup lang="ts">
  • Define props with TypeScript: defineProps<{ text: string }>()
  • Keep components focused and functions short
<script setup lang="ts">
defineProps<{
  title: string
  score: number
}>()
</script>

Server API patterns

Server API routes live in packages/web/server/api/ and follow Nitro conventions:

  • File names include the HTTP method: repos.get.ts, dashboards.post.ts
  • Use defineEventHandler for route handlers
  • Background work is handled via Nitro tasks in server/tasks/

Naming conventions

Type Convention Example
Vue components PascalCase GitHubIssue.vue
Pages kebab-case index.vue, [issue].vue
Composables camelCase + use prefix useRepos.ts
Server routes kebab-case + method repos.get.ts
Functions camelCase indexRepo, fetchClusters
Constants SCREAMING_SNAKE_CASE DEV_REPOS_TO_INDEX
Types/Interfaces PascalCase Issue, Cluster

Submitting changes

Before submitting

  1. Run linting: pnpm lint
  2. Run type checking: pnpm test:types
  3. Make sure the dev server starts without errors

Pull request process

  1. Fork the repository and create a branch from main
  2. Make your changes with clear, descriptive commits
  3. Push your branch and open a pull request
  4. Ensure CI checks pass (lint, type-check, provenance)
  5. Request review from maintainers

Commit messages and PR titles

We use Conventional Commits. Since we squash on merge, the PR title becomes the commit message in main.

Format: type(scope): description

Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore

Examples:

  • fix: resolve clustering accuracy for small repos
  • feat: add dashboard sharing
  • docs: update contributing guide
  • chore(deps): update nuxt to v4.1

Note

Use lowercase in your PR title. Individual commits within the PR don't need to follow this format since they'll be squashed.

Pre-commit hooks

The project uses vite-plus to manage pre-commit hooks. On every commit, ESLint --fix runs automatically on staged files matching *.{js,ts,tsx,vue,mjs,cjs,json,.*rc}.

You don't need to configure anything -- this is set up in vite.config.ts at the repo root.

Browser extension

The browser extension is in packages/extension/. It's a WXT content script that injects a "Similar Issues" panel into GitHub issue pages.

  • Content script injects into github.com issue pages
  • Fetches similar issues from the unsight.dev API
  • Built separately from the web app

To work on the extension:

pnpm dev:ext         # Start extension dev (Chrome)

Extension releases are automated: bump the version with bumpp in packages/extension/, merge to main, and CI handles Chrome Web Store and Firefox Add-ons submission.

Using AI

You're welcome to use AI tools to help you contribute, with two ground rules:

  1. Never let an LLM speak for you. When writing comments, issues, or PR descriptions, use your own words. Clarity beats polish.
  2. Never let an LLM think for you. If AI writes code for you, understand it before contributing it. Take personal responsibility for your contributions.

For more context, see Using AI in open source.

Questions?

If you have questions or need help, feel free to open an issue for discussion.

License

By contributing to unsight.dev, you agree that your contributions will be licensed under the MIT License.