Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6b023aa
typo: fixed word shouldn't
Lucifer-0612 Nov 22, 2025
e8d144e
fix: typos in blog titles
Lucifer-0612 Nov 22, 2025
0808345
fix: normalize blog titles to lowercase
Lucifer-0612 Nov 24, 2025
b2322a8
feat(types): add SavedRepo shared types
Lucifer-0612 Dec 4, 2025
1193fb4
feat(store): add useSavedProjectsStore with localStorage
Lucifer-0612 Dec 4, 2025
da0e3fe
feat(ui): add SaveToggle component
Lucifer-0612 Dec 4, 2025
2787921
feat(ui): add SavedProjectsPanel component
Lucifer-0612 Dec 4, 2025
4f91bd4
feat(ui): integrate saved repos into ProjectsContainer
Lucifer-0612 Dec 4, 2025
cb7fb06
feat(db): add saved_repos column to User model
Lucifer-0612 Dec 4, 2025
e704336
feat(api): add saved repos service layer
Lucifer-0612 Dec 4, 2025
fcfa928
feat(api): add saved repos tRPC endpoints
Lucifer-0612 Dec 4, 2025
a0da2ac
docs: add saved repos documentation
Lucifer-0612 Dec 4, 2025
1513ef2
fix: code quality improvements and accessibility enhancements
Lucifer-0612 Dec 5, 2025
14c2e2b
Merge feature branch: code quality improvements and accessibility enh…
Lucifer-0612 Dec 5, 2025
091de8c
refactor: remove unused setAll from SavedProjectsPanel
Lucifer-0612 Dec 5, 2025
8127f1c
Merge feature: remove unused setAll from SavedProjectsPanel
Lucifer-0612 Dec 5, 2025
abbe479
fix: Improve DX with automated setup and Docker orchestration (#292)
Lucifer-0612 Dec 18, 2025
86df19f
Merge upstream/main and resolve conflicts
Lucifer-0612 Dec 18, 2025
b203d25
refactor: improve type safety and design token consistency
Lucifer-0612 Dec 18, 2025
df645b8
refactor: replace hardcoded red colors with semantic error tokens
Lucifer-0612 Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Changelog

All notable changes to this project will be documented in this file.

## [Unreleased]

### Added - Saved Repos Feature

#### Frontend
- **Zustand Store**: Created `useSavedProjectsStore` with localStorage persistence
- Stores saved repositories with key `oss_saved_repos_v1`
- Actions: `addProject`, `removeProject`, `toggleProject`, `clearAllSaved`, `setAll`, `isSaved`
- Automatic persistence across page reloads

- **UI Components**:
- `SaveToggle`: Star icon button in project rows to save/unsave repositories
- `SavedProjectsPanel`: Side panel for managing saved repos
- Export saved repos to JSON file
- Import saved repos from JSON file
- Clear all saved repos with confirmation
- View all saved repos with metadata

- **Projects Table**: Added "Save" column as first column in OSS Projects table
- **Header Button**: Added "Saved Projects" button with count badge in projects page header

#### Backend
- **Database**: Added `saved_repos` JSONB column to `User` model (default: `[]`)
- **Service Layer**: Created `savedReposService` with:
- `getSavedRepos`: Retrieve user's saved repos
- `mergeSavedRepos`: Merge local and server repos with conflict resolution
- `updateSavedRepos`: Update saved repos with add/remove/replace actions
- Maximum 100 saved repos per user enforcement

- **API Endpoints** (tRPC):
- `user.getSavedRepos`: Get user's saved repos (protected, feature flag: `FEATURE_SAVED_REPOS_DB`)
- `user.updateSavedRepos`: Update saved repos with merge logic (protected, feature flag: `FEATURE_SAVED_REPOS_DB`)
- Conflict resolution: Newer `savedAt` timestamp wins

#### Shared Types
- Created `SavedRepo` type definition in `@opensox/shared`
- Created `SavedReposAction` and `SavedReposUpdateInput` types

### Configuration
- **Feature Flag**: `FEATURE_SAVED_REPOS_DB` - Enable/disable database sync (default: disabled)
- When disabled: Client-only mode with localStorage
- When enabled: Full sync across devices with merge logic

### Migration
- Migration file: `add_saved_repos` - Adds `saved_repos` JSONB column to User table

---

## How to Use

### For Users
1. Navigate to `/dashboard/projects`
2. Click "Find projects" to search for repositories
3. Click the star icon on any project to save it
4. Click "Saved Projects" button to view/manage saved repos
5. Export/import saved repos as JSON for backup

### For Developers
1. **Client-only mode** (default): Works out of the box with localStorage
2. **Database sync mode**: Set `FEATURE_SAVED_REPOS_DB=true` in `apps/api/.env`
3. Run migration: `cd apps/api && npx prisma migrate dev`
4. Restart API server

### API Usage (when feature flag enabled)
```typescript
// Get saved repos
const savedRepos = await trpc.user.getSavedRepos.query();

// Add repos
await trpc.user.updateSavedRepos.mutate({
action: 'add',
repos: [{ id: '123', name: 'repo', url: 'https://...', savedAt: new Date().toISOString() }]
});

// Sync with merge
await trpc.user.updateSavedRepos.mutate({
action: 'replace',
repos: serverRepos,
localRepos: clientRepos // Will merge and resolve conflicts
});
```
32 changes: 32 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Base stage with pnpm
FROM node:20-alpine AS base
RUN npm install -g pnpm
WORKDIR /app

# API development
FROM base AS api
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY apps/api/package.json ./apps/api/
COPY packages/shared/package.json ./packages/shared/
RUN pnpm install
COPY packages/shared ./packages/shared
COPY apps/api ./apps/api
WORKDIR /app/packages/shared
RUN pnpm run build
WORKDIR /app/apps/api
RUN pnpm exec prisma generate
EXPOSE 8080
CMD ["pnpm", "run", "dev"]

# Web development
FROM base AS web
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY apps/web/package.json ./apps/web/
COPY packages/shared/package.json ./packages/shared/
COPY packages/ui/package.json ./packages/ui/
RUN pnpm install
COPY packages ./packages
COPY apps/web ./apps/web
WORKDIR /app/apps/web
EXPOSE 3000
CMD ["pnpm", "run", "dev"]
128 changes: 128 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
.PHONY: help start stop restart logs clean reset setup dev test status health migrate seed studio shell-api shell-db dev-local logs-api logs-web logs-db migrate-dev

# Default target - show help
help:
@echo ""
@echo "========================================================================"
@echo " Opensox Development CLI "
@echo "========================================================================"
@echo ""
@echo " GETTING STARTED:"
@echo " make setup - First-time setup wizard (run this first!)"
@echo " make start - Start all services (DB, API, Web)"
@echo ""
@echo " SERVICE MANAGEMENT:"
@echo " make stop - Stop all services"
@echo " make restart - Restart all services"
@echo " make logs - View logs from all services"
@echo " make status - Check service health"
@echo ""
@echo " DATABASE:"
@echo " make migrate - Run database migrations"
@echo " make seed - Seed database with initial data"
@echo " make studio - Open Prisma Studio (GUI)"
@echo " make reset - Stop services and reset database (DELETES DATA)"
@echo ""
@echo " DEBUGGING:"
@echo " make shell-api - Open shell in API container"
@echo " make shell-db - Open psql shell in database"
@echo " make logs-api - View API logs only"
@echo " make logs-web - View Web logs only"
@echo ""
@echo " CLEANUP:"
@echo " make clean - Remove containers, volumes, and build cache"
@echo ""
@echo "========================================================================"
@echo ""

# First-time setup
setup:
@echo "Starting Opensox setup wizard..."
@chmod +x ./scripts/setup.sh 2>/dev/null || true
@./scripts/setup.sh

# Start all services
start:
@echo "Starting all services..."
docker compose up -d
@$(MAKE) --no-print-directory health
@echo ""
@echo "Services started successfully!"
@echo " Frontend: http://localhost:3000"
@echo " API: http://localhost:8080"
@echo ""

# Stop all services
stop:
@echo "Stopping all services..."
docker compose down

# Restart services
restart: stop start

# View logs
logs:
docker compose logs -f

logs-api:
docker compose logs -f api

logs-web:
docker compose logs -f web

logs-db:
docker compose logs -f postgres

# Check status
status:
@docker compose ps

# Health check
health:
@echo "Waiting for services to be healthy..."
@sleep 3
@docker compose ps --format "table {{.Name}}\t{{.Status}}" | head -10

# Database operations
migrate:
@echo "Running database migrations..."
docker compose exec api pnpm exec prisma migrate deploy

migrate-dev:
docker compose exec api pnpm exec prisma migrate dev

seed:
@echo "Seeding database..."
docker compose exec api pnpm exec prisma db seed

studio:
@echo "Opening Prisma Studio..."
docker compose exec api pnpm exec prisma studio

# Reset database
reset:
@echo "WARNING: This will delete all data. Are you sure? [y/N] " && read ans && [ $${ans:-N} = y ]
docker compose down -v
@$(MAKE) --no-print-directory start
@$(MAKE) --no-print-directory migrate
@$(MAKE) --no-print-directory seed

# Clean everything
clean:
@echo "Cleaning up..."
docker compose down -v --rmi local --remove-orphans
rm -rf apps/api/node_modules apps/web/node_modules
rm -rf apps/api/dist apps/web/.next

# Shell access
shell-api:
docker compose exec api sh

shell-db:
docker compose exec postgres psql -U opensox -d opensox

# Development without Docker (uses local Node)
dev-local:
@echo "Starting local development..."
pnpm install
pnpm run dev
Loading