{"id":51656104,"url":"https://github.com/robbdimitrov/phasma","last_synced_at":"2026-07-14T09:04:28.108Z","repository":{"id":53474958,"uuid":"108114479","full_name":"robbdimitrov/phasma","owner":"robbdimitrov","description":"Modern image-sharing application delivering real-time visual feeds via responsive Svelte and a high-performance Go API.","archived":false,"fork":false,"pushed_at":"2026-07-10T17:49:43.000Z","size":9082,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-07-10T19:15:53.651Z","etag":null,"topics":["docker","golang","javascript","kubernetes","svelte","typescript"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robbdimitrov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2017-10-24T10:58:22.000Z","updated_at":"2026-07-10T17:49:47.000Z","dependencies_parsed_at":"2023-02-13T01:31:26.625Z","dependency_job_id":"d1e04500-ceb0-43b5-8b4e-d9f069e14925","html_url":"https://github.com/robbdimitrov/phasma","commit_stats":null,"previous_names":["robbdimitrov/phasma"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/robbdimitrov/phasma","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robbdimitrov%2Fphasma","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robbdimitrov%2Fphasma/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robbdimitrov%2Fphasma/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robbdimitrov%2Fphasma/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robbdimitrov","download_url":"https://codeload.github.com/robbdimitrov/phasma/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robbdimitrov%2Fphasma/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35453853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","golang","javascript","kubernetes","svelte","typescript"],"created_at":"2026-07-14T09:04:27.528Z","updated_at":"2026-07-14T09:04:28.101Z","avatar_url":"https://github.com/robbdimitrov.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Phasma\n\n**Phasma** is a full-stack image-sharing platform built with a production-grade\narchitecture. Combining a robust Go API with a modern SvelteKit frontend, it\nprovides a seamless experience for users to upload, browse, and interact with\nimages.\n\n![Feed page](docs/images/feed.png)\n\n## Features\n\n- **Image sharing**: Upload, browse, like, and comment on images with a\n  responsive feed and profile pages.\n- **Social feed**: Personalized feed of posts from followed users,\n  pre-materialized on write by a Kafka consumer group (fan-out on follow/post).\n- **Notifications**: Real-time like, comment, and follow notifications with\n  unread badge and mark-as-read support.\n- **Rich text**: Captions, comments, and bios render `@mention`, `#hashtag`, and\n  URL links. Compose typeahead suggests users and hashtags as you type.\n- **Global search**: Search users, posts, and hashtags with paginated results. A\n  leading `#` scopes results to hashtag-filtered posts.\n- **Object storage**: Image bytes are stored in SeaweedFS (S3-compatible),\n  decoupled from the database and served with `Cache-Control` and `ETag`\n  headers.\n- **Cache layer**: Dragonfly (Redis-protocol) backs rate-limit token buckets and\n  login-failure counters, keeping the hot path off PostgreSQL.\n- **Event streaming**: Every domain mutation writes to a transactional outbox.\n  The backend relay polls unpublished rows, publishes to Redpanda\n  (Kafka-compatible) topics, then marks the rows published. The topics are\n  consumed by the notifications and feed workers and the Meilisearch sync\n  pipeline.\n- **Session management**: Argon2id password hashing, HMAC-keyed session tokens,\n  per-user session listing and remote revocation.\n- **Production-ready**: Stateless Go API, bounded concurrency, absolute session\n  lifetimes, dependency-aware readiness probe, structured JSON logging, circuit\n  breaker and retry-with-backoff on every database call.\n- **HA-ready**: Ships at `replicas: 1` but correct at `replicas: N`. No shared\n  in-process state; outbox delivery is at least once and all consumers use\n  idempotent inserts with `ON CONFLICT DO NOTHING`.\n\n## Architecture\n\n```mermaid\ngraph TD\n    Browser[\"Browser\"]\n\n    subgraph cluster [\"Kubernetes Cluster\"]\n        Frontend[\"Frontend\u003cbr\u003e(SvelteKit)\"]:::frontend\n        Gateway[\"Backend\u003cbr\u003e(Go)\"]:::backend\n\n        subgraph data [\"Data \u0026 Storage\"]\n            DB[(\"PostgreSQL\u003cbr\u003e(source of truth)\")]:::database\n            Search[(\"Meilisearch\u003cbr\u003e(search index)\")]:::search\n        end\n    end\n\n    Browser --\u003e Frontend\n    Frontend --\u003e Gateway\n    Gateway --\u003e DB \u0026 Search\n\n    classDef frontend fill:#0ea5e9,stroke:#0284c7,stroke-width:2px,color:#fff\n    classDef backend fill:#6366f1,stroke:#4f46e5,stroke-width:2px,color:#fff\n    classDef database fill:#f59e0b,stroke:#d97706,stroke-width:2px,color:#fff\n    classDef search fill:#06b6d4,stroke:#0891b2,stroke-width:2px,color:#fff\n\n    style cluster fill:transparent,stroke:#64748b\n    style data fill:transparent,stroke:transparent\n```\n\n| Service                    | Language   | Description                                                    |\n| -------------------------- | ---------- | -------------------------------------------------------------- |\n| [frontend](/apps/frontend) | TypeScript | SvelteKit SSR application; sole public entry point and BFF.    |\n| [backend](/apps/backend)   | Go         | HTTP API handling users, sessions, images, likes, and uploads. |\n| [database](/apps/database) | PostgreSQL | Versioned schema migrations managed by `migrate/migrate`.      |\n\n### Infrastructure\n\nSix in-cluster services run alongside the application:\n\n- **PostgreSQL** — Primary source of truth for all application data.\n- **Dragonfly** — Redis-protocol cache backing rate-limit token buckets and\n  login-failure counters. The API fails open on unavailability.\n- **SeaweedFS** — S3-compatible object store holding image bytes. The API\n  streams blobs directly; no image data touches PostgreSQL.\n- **Meilisearch** — Derived search index. PostgreSQL is the only source of\n  truth; Meilisearch is populated and kept current via the Redpanda outbox\n  pipeline.\n- **Redpanda** — Kafka-compatible event broker. Receives `entity-changes` and\n  `activity` events published by the backend outbox relay; consumed by\n  Redpanda Connect and the backend's\n  `notifications-consumer` and `feed-consumer` goroutines.\n- **Redpanda Connect** — Stateless Kafka consumer for Meilisearch sync plus a\n  one-shot backfill job for users, posts, and hashtags.\n\n## Docs\n\nArchitectural specs live in [`docs/`](/docs/):\n\n| Doc                                          | Contents                                                       |\n| -------------------------------------------- | -------------------------------------------------------------- |\n| [architecture.md](/docs/architecture.md)     | Service topology, request flow, integration patterns           |\n| [api.md](/docs/api.md)                       | HTTP endpoints, middleware stack, pagination                   |\n| [data-model.md](/docs/data-model.md)         | Schema, indexes, entity relationships, domain invariants       |\n| [security.md](/docs/security.md)             | Session model, password policy, ownership rules, rate limiting |\n| [business-rules.md](/docs/business-rules.md) | Validation constraints, ordering, content policy               |\n| [frontend.md](/docs/frontend.md)             | Route map, layout hierarchy, SSR, data fetching                |\n| [design-system.md](/docs/design-system.md)   | Theme, component inventory, layout                             |\n| [infrastructure.md](/docs/infrastructure.md) | Kubernetes resources, secrets, probes, storage                 |\n\n## Deploy\n\nDeploy the application to your active Kubernetes cluster using the provided\nscript:\n\n```sh\n./scripts/deploy.sh\n```\n\nThe script builds the Docker images, creates the Kubernetes namespace (`phasma`\nby default) and resources, waits for pods to be ready, and starts a port-forward\nto the frontend at http://localhost:8080/. It is idempotent and safe to re-run\nfor updates.\n\n## Cleanup\n\nTo remove all deployed resources and the namespace:\n\n```sh\nkubectl delete -f ./deploy -n phasma\nkubectl delete namespace phasma\n```\n\n## Testing\n\nRun all unit tests across the frontend and backend:\n\n```sh\nmake test\n```\n\n## License\n\nLicensed under the [MIT](LICENSE) License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobbdimitrov%2Fphasma","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobbdimitrov%2Fphasma","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobbdimitrov%2Fphasma/lists"}