MyGo 云音乐
Go와 MyGo로 만든 서드파티 네이버 클라우드 뮤직 데스크톱 클라이언트
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Coeus is a standalone, local-first RSS reader for building a deliberate reading stack. It combines source discovery, configurable feed views, transparent personal ranking, a portable archive, and sourced social sharing in a sparse editorial interface.
It is inspired by brutalist.report and is not affiliated with it.
Use the Node version in .nvmrc (Node 24; nvm use). Then:
.github/workflows/ci.yml runs on every pull request
and every push to main. Two jobs must pass before merge (mark them required in
branch protection):README 전문 보기 ↗Coeus is a standalone, local-first RSS reader for building a deliberate reading stack. It combines source discovery, configurable feed views, transparent personal ranking, a portable archive, and sourced social sharing in a sparse editorial interface.
It is inspired by brutalist.report and is not affiliated with it.
Use the Node version in .nvmrc (Node 24; nvm use). Then:
npm install
npm run dev
Open http://localhost:3000. For a production check:
npm test
./node_modules/.bin/tsc --noEmit
npm run lint
npm run build
npm run audit:ci
CI classifies changed files on every pull request.
It skips unrelated jobs while keeping their check names stable for branch
protection. A push to main repeats the Node job as a backstop:
npm ci, npm run lint, npx tsc --noEmit, npm test
(unit + jsdom UI), npm run build, and npm run audit:ci (fails on high+
advisories, except dated dev-only exceptions in
scripts/audit-policy.mts). The build receives only public, non-secret placeholder
NEXT_PUBLIC_* values; no production secret is present in CI.supabase/ or CI config changes. It pins the Supabase CLI (2.75.0), runs supabase start (Docker
is preinstalled on GitHub-hosted ubuntu-latest; migrations apply on start),
then supabase test db for the pgTAP suite.Documentation and agent-instruction edits only run the change classifier. A server script edit runs the Node job without starting Docker or Chromium. The database and browser jobs run on relevant PRs, not again after merge. For local work, run the checks affected by the edit first; use the full suite when a change crosses boundaries or before a higher-risk release.
Node is pinned via .nvmrc and consumed by actions/setup-node
(node-version-file). To reproduce CI locally you need Docker Desktop running.
| Route | Purpose |
|---|---|
/ | Reader with Grid, Top, Focus, and opt-in Ranked views |
/sources | Search, filter, rate, add, and remove reading sources |
/discover | Shared collections, sourced articles, and links from people |
/archive | Saved articles, notes, tags, collections, search, and export |
/u/[handle] | Public profile (+ /followers, /following); owner-console affordances inline |
/c, /c/[slug] | Public collection listing and pages (+ /c/[slug]/rss.xml) |
/signin, /welcome, /auth/callback | Passwordless account flow (optional; anonymous use is unaffected) |
/about | Concise guide to the product and its core sections |
/social, /product | Legacy redirects to /discover and /about |
/api/feeds | Validated server-side RSS aggregation endpoint |
/api/archive, /api/archive/sync | Authenticated archive retrieval and transactional synchronization |
/api/collections/*, /api/posts/*, /api/profiles/*, /api/replies, /api/reposts, /api/likes, /api/account/* | Authenticated JSON boundaries for publications, the person graph, and account management |
/api/health | Unauthenticated readiness (GET) and liveness (HEAD) probe |
src/
app/ Next.js routes and the feed route handler
components/ Route applications and shared UI
AppProviders.tsx Composition shell: usePreferencesProvider + useArchiveProvider
PrimaryNav.tsx Shared application navigation
hooks/
useFeedQuery.ts Reader feed lifecycle
lib/
feedContract.ts Public API query validation
feedApi.ts Testable HTTP response/cache policy
feeds/feeds.server.ts Server-only RSS cache and aggregation
engagement.server.ts Server-only provider enrichment
feedQuery.ts Browser batching and progressive merge
prefs.ts Validated local preference store
archiveTypes.ts Archive contracts and repository interface
archiveDomain.ts Pure archive operations
archiveFixtures.ts Seeded local demo data
archiveValidation.ts Runtime validation and migrations
localArchiveRepository.ts Browser persistence adapter
archiveSync.ts Versioned operations and conflict reducer
archiveApi.ts Authenticated HTTP boundary
archiveSyncStore.server.ts Supabase transaction adapter
styles/
base.css Tokens, themes, fonts, and document defaults
reader.css Reader, settings, search, and feed views
archive-social.css Archive, sharing, and social surfaces
product.css About page
discover.css Sources directory
responsive.css Cross-feature responsive overrides
docs/lib-architecture.md defines the intended
src/lib shape — the six domains (archive, publications, conversations,
profiles, feeds, destinations), the five layers (route → API → store → core →
primitives) and the allowed dependency direction, plus where new work goes.
Modules move toward it in small slices, not a flag-day rewrite.
The root provider is the only UI integration point for preferences, theme hydration, and archive persistence. Screens mutate archives through a typed repository boundary; the wired repository is SyncedArchiveRepository, so a signed-in browser gets authenticated background sync on top of localStorage without any route component changing.
The feed endpoint validates and deduplicates inputs, rejects unknown sources and topics, rate-limits forced refresh fan-out, and marks server-only RSS/provider modules explicitly. Ordinary responses expose short public cache headers; forced refreshes and errors are no-store.
Destination delivery (Obsidian/GitHub, Notion) runs from three overlapping
triggers — the post-sync after() hook, the manual "sync now" route, and the
daily cron sweep. Each destination is guarded by a durable lease
(acquire_destination_delivery_lease) that gives both cross-instance mutual
exclusion (so two runs can't create duplicate Notion pages) and a
cross-invocation rate limit via a minimum interval between runs. Outbound
adapter requests carry per-request timeouts and bounded retry/backoff. A
delivery failure is captured in a structured, correlation-id-tagged log and
never fails or delays the archive sync response.
coeus.prefs.v1, with migration from bareaga.prefs.v1 and, before that, brp.prefs.v1.coeus.archive.v1, with migration from bareaga.archive.v1; runtime-validated and migrated on read.Archive exports remain portable Markdown and CSV. The authenticated sync API,
durable schema, and the browser adapter (SyncedArchiveRepository — durable
operation queue, background retry/rebase, first-account migration) are all
implemented. Anonymous users stay entirely on local storage.
Per-account budgets are enforced at the database boundary (a trigger on the
immutable revision table) and mirrored by the service-role sync store for
clearer errors. Defaults live in src/lib/archive/archiveBudget.ts
and are meant as generous pre-launch ceilings, not usage shaping:
| Budget | Default | Enforced by |
|---|---|---|
| Items / collections / posts per archive | 5000 / 2000 / 5000 | archive_revisions_budget trigger + checkArchiveBudget |
| Serialized snapshot size | 8 MiB | same |
| Any single string field | 20000 chars | checkArchiveBudget |
| Sync requests per account | 60 per 5 min | consume_archive_sync_budget (durable, cross-instance); 429 + Retry-After |
| Sync batch body / operations | 2 MiB / 500 ops | handleArchiveSync / parseArchiveSyncBatch |
| Revision retention | keep last 50 and last 30 days | prune_all_archive_revisions, run by the daily cron route |
archive_storage_stats() reports per-archive revision counts, byte totals, and
operation counts for monitoring storage growth.
src/lib/serverLog.ts is the structured-logging
boundary. instrument({ route, operation, correlationId }, fn) wraps a critical
server operation and emits one JSON line with route, operation,
durationMs, statusClass (2xx/4xx/5xx/error), and a correlationId
(taken from x-request-id / x-vercel-id when present). A redact() pass and
scrubMessage() keep secrets, tokens, JWTs, private notes, captured content,
and raw personal data out of the logs; client responses are unchanged. Every
API route handler is wrapped in instrument() (bareaga_web-cnu).
GET /api/health is the readiness probe (HEAD is liveness, always 200). It
checks required configuration and Supabase reachability and returns
{ status: "ok" | "degraded", checks, durationMs } with 200 when every check
passes and 503 otherwise. The body is only names, booleans, and durations —
no identifiers or error messages. Verify a running server with
npm run smoke:health (honors SMOKE_BASE_URL).
Uptime — in place now. .github/workflows/uptime.yml
probes https://coeuscoeus.com/api/health (and /) every ~15 min; a failure
fails the run, which emails the repo owner and pushes to GitHub mobile. Set an
ALERT_WEBHOOK_URL repo secret (Slack or Discord incoming webhook) to also get
a chat message. GitHub's scheduler is best-effort — for sub-minute paging add a
dedicated monitor (see docs/deployment.md).
Log-based thresholds — backstop in place now.
.github/workflows/log-alerts.yml pulls the
last ~30 min of production runtime/request logs from Vercel every ~30 min,
evaluates the table below with src/lib/logThresholds.ts,
and fails the run on any Page breach (email + GitHub mobile, plus
ALERT_WEBHOOK_URL when set); Warning breaches print but keep the run
green. Rate signals have a minimum-sample floor so one error on a quiet route
can't read as 100%. Run it locally against a window with
npm run check:log-thresholds (VERCEL_TOKEN env, or --input <file> of
JSON-lines). Required repo secret: VERCEL_TOKEN; optional VERCEL_PROJECT,
VERCEL_TEAM_ID.
Storage growth — backstop in place now.
.github/workflows/storage-growth.yml
runs weekly: it appends an archive_storage_stats() byte total to
storage_growth_snapshots via the capture_storage_growth() RPC, diffs it
against the previous reading normalised to a 7-day rate
(src/lib/storageGrowth.ts), and fails the run on a
Page breach. Run it locally with npm run check:storage-growth. Activate it
by setting the SUPABASE_URL and SUPABASE_SECRET_KEY (production service-role
key) repo secrets — until then the run prints a warning and stays green.
This is a short-polling safety net — a real log platform (Vercel Observability,
or a Log Drain to BetterStack / Axiom / Datadog) with sustained-window alerting
on the same serverLog.ts events is still the recommended primary.
| Signal | Warning | Page | Backstopped |
|---|---|---|---|
GET /api/health non-200 | any, 1 sample | sustained > 2 min | ✅ |
*.error log rate (any route) | > 1% of that route's requests over 15 min | > 5% over 5 min | ✅ |
archive.sync 5xx rate | > 2% over 15 min | > 10% over 5 min | ✅ |
archive.sync p95 durationMs | > 2000 | > 5000 | ✅ |
destination_delivery.*.error | > 5 in 1 h | > 50 in 1 h | ✅ |
archive_storage_stats total snapshot_bytes growth | > 25%/week | > 100%/week | ✅ |
Install the Supabase CLI and Docker Desktop, then run:
supabase start
supabase db reset
supabase test db
supabase status -o env
Copy the URL, publishable/anon key, and service-role key into a local .env.local
using .env.example. SUPABASE_SECRET_KEY is server-only and
must never use a NEXT_PUBLIC_ prefix. The database migration creates immutable
archive revisions, operation idempotency records, owner-only RLS policies, and a
private archive-snapshots bucket.
Edit src/lib/feeds/sources.ts and provide the full SourceDef metadata. Source IDs are validated by /api/feeds; adding a catalog entry does not silently enable it for existing users.
Required secrets, database migration steps, the deploy flow, and rollback
procedure are in docs/deployment.md.
This repository uses Beads for durable work tracking. Run bd ready to see unblocked work and bd show <id> for acceptance criteria.