Help us shape the future of Go! Take the 2026 Go Developer Survey

pcom

module
v0.0.0-...-af5a29e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: Apache-2.0

README

Pcom - private social network

Private as in the content is not public by default and discovery requires a human touch.

User guide and developer docs: https://can3p.github.io/pcom/

Pcom uses gogo to handle forms and some other things!

If you want to follow the development, there is a youtube playlist with demos!

Official client

Official client is blg, command line client that plays well with pcom. See docs/api.md for the API.

Quick start

Docker is the only dependency. Cold start, seeded users, ports, everyday commands and troubleshooting are in docs/running.md:

cp .env.example cmd/web/.env
make dev-up && make migrate && make seed
make dev        # app and asset watcher in containers, http://localhost:8080

Every setting is an environment variable (or flag) listed by go run ./cmd/web serve --help; other commands have their own --help. Defaults are production values, so cmd/web/.env (copied from .env.example) and compose turn off what doesn't fit plain-HTTP localhost, and log in the console format instead of JSON.

Local development uses tommy for mail and S3:

Tests
make check   # build + all tests, no artifacts
make test    # tests only
make lint    # golangci-lint

Docker must be running: tests that touch the database start a Postgres container via pkg/testutil/testdb. Tests that verify mail and media use pkg/testutil/tommy to read from the tommy container.

Browser tests

User flows (forms, htmx swaps, Stimulus controllers) are tested in a real Chromium driven by playwright-go. They live in e2e/browser behind the build tag browser, so make test and make check don't run them.

make ui-deps    # once: installs the Playwright driver and Chromium
make test-ui    # builds the frontend, then runs the suite
make test-ui RUN=TestSmoke COUNT=3                  # narrow it, repeat it
make test-ui HEADED=1 SLOWMO=250 RUN=TestSmoke_LoginAndBoostedNavigation
make ui-trace F=.ui-artifacts/<Test>.trace.zip      # inspect a failure

Chromium runs headless by default, so no window opens and a passing run prints only ok: test-ui. Add HEADED=1 to see the browser and SLOWMO=<ms> to slow each step down. Narrow the run with RUN when watching, because the tests run in parallel and each one opens its own window. A failed test saves a screenshot and a trace under .ui-artifacts/ and prints their paths. docs/testing.md explains how the suite works and how to write a test.

Initial Setup

  1. change remote and push to the new repo

  2. change flytoml to point to the new app pcom

  3. create the app on fly flyctl apps create pcom

  4. create db, set 4gb ram fly postgres create -n pcomdb

  5. attach db to the app flyctl postgres attach -a pcom pcomdb

  6. Set secrets:

    flyctl secrets set SESSION_SALT=<random string>
    flyctl secrets set SITE_ROOT=https://pcom.com
    flyctl secrets set MJ_APIKEY_PUBLIC=<public key from mailjet>
    flyctl secrets set MJ_APIKEY_PRIVATE=<private key from mailjet>
    # this one should include scheme
    flyctl secrets set USER_MEDIA_ENDPOINT=<endpoint>
    flyctl secrets set USER_MEDIA_BUCKET=<bucket>
    flyctl secrets set USER_MEDIA_KEY=<key>
    flyctl secrets set USER_MEDIA_REGION=<region>
    flyctl secrets set USER_MEDIA_SECRET=<secret>
    flyctl secrets set SENDER_ADDRESS=<address>
    flyctl secrets set ADMIN_ADDRESS=<address>
    flyctl secrets set STATIC_CDN=<address> # in case you want to put static resources behind the cdn
    flyctl secrets set USER_MEDIA_CDN=<address> # in case you want to put user images behind the cdn
    flyctl secrets set ENABLE_PPROF=true # optional, serves pprof on :8081 (see `make pprof_tunnel`)
    

    Production behavior (secure cookies, HSTS, long static caching, panic reports) is the default; web serve --help lists every setting. Migrations run on every deploy: fly's release_command runs sql-migrate up in the new image before it takes traffic (make migrate-prod remains as a manual fallback).

  7. Do first deploy fly deploy, make sure you can reach the app via .fly.dev

  8. Create a cert for your custom domain fly certs add pcom.com

  9. After it screams at you, add required A and AAAA records

  10. You might need to run fly certs check pcom.com a couple of times, fly certs list should show your domain with the status ready.

  11. You should be able to reach your app via custom domain at this point

  12. Go to mailjet and add new domain

  13. Add sender email address there

  14. Add required txt record to validate domain

  15. Add required txt records to add DKIM and SPF settings

  16. Run the following from the project root to get the database schema in place

Tab 1:

make tunnel          # fly proxy 5433 -a pcomdb

Tab 2:

make migrate-prod    # asks for confirmation first

make migrate-prod runs the migrations from the tools container against the tunnel, with DATABASE_URL taken from ./env.pl (the app's secrets on fly). On Linux the tunnel must listen on an address the container can reach (flyctl proxy --bind-addr). See docs/running.md.

Operational notes

  • App instance is running in a wrong dc:

    fly scale count 0
    fly scale count 1 --region ams
    
Admin commands

Use the web admin subcommand to manage registrations and invitations:

web admin invite --email <email> --num <count>    # generate invites for email
web admin registration --open                      # allow open registration
web admin registration --close                     # close registration

Modernization

Work to add test coverage and then modernize the codebase is planned in docs/implementation-plan.md.

Credits

The project has been generated by gogo-cli and uses gogo library

Directories

Path Synopsis
cmd
web command
Package e2e runs the real web binary against a fresh database and drives it over HTTP.
Package e2e runs the real web binary against a fresh database and drives it over HTTP.
pkg
config
Package config declares every setting of the pcom binary as a go-flags option with paired `long:` and `env:` tags, so `web --help` is the configuration reference.
Package config declares every setting of the pcom binary as a go-flags option with paired `long:` and `env:` tags, so `web --help` is the configuration reference.
logging
Package logging carries pcom's one logger, a *zap.Logger.
Package logging carries pcom's one logger, a *zap.Logger.
mail
Package mail formats the mail pcom sends.
Package mail formats the mail pcom sends.
markdown/mdext/strikethrough
Package strikethrough renders ~~text~~ as <del>text</del>.
Package strikethrough renders ~~text~~ as <del>text</del>.
model
Package model holds pcom's database rows: one struct per table, written by hand.
Package model holds pcom's database rows: one struct per table, written by hand.
proofread
Package proofread is what pcom asks a language model about a post and what it accepts back: the grammar check (suggestions to replace exact passages) and the style review (notes on the text as a whole, which follow up the post's previous review).
Package proofread is what pcom asks a language model about a post and what it accepts back: the grammar check (suggestions to replace exact passages) and the style review (notes on the text as a whole, which follow up the post's previous review).
proofread/claude
Package claude is the proofread.Model over the Claude API, through the official Go SDK.
Package claude is the proofread.Model over the Claude API, through the official Go SDK.
proofread/proofreadtest
Package proofreadtest is an in-memory proofread.Model for tests.
Package proofreadtest is an in-memory proofread.Model for tests.
repo
Package repo holds database queries.
Package repo holds database queries.
service
Package service holds the errors every service returns.
Package service holds the errors every service returns.
service/accounts
Package accounts holds everything about who a user is and how they get in: signup, the waiting list, invitations, login credentials, passwords, the settings page, user styles, API keys, feed tokens and the registration switch.
Package accounts holds everything about who a user is and how they get in: signup, the waiting list, invitations, login credentials, passwords, the settings page, user styles, API keys, feed tokens and the registration switch.
service/connections
Package connections manages who is connected to whom: whitelist grants (people allowed to connect without mediation), connections themselves and mediation requests, where common connections vouch for a stranger.
Package connections manages who is connected to whom: whitelist grants (people allowed to connect without mediation), connections themselves and mediation requests, where common connections vouch for a stranger.
service/feeds
Package feeds manages RSS subscriptions: what a user follows, the items the poller delivers to them, and dismissing an item.
Package feeds manages RSS subscriptions: what a user follows, the items the poller delivers to them, and dismissing an item.
service/graph
Package graph answers how two users are connected.
Package graph answers how two users are connected.
service/media
Package media handles media uploads.
Package media handles media uploads.
service/posts
Package posts is everything users do with posts: write, edit, autosave, publish and delete them, comment on them, prompt others to write, export and import a blog, and the API v1 that does the same for scripts.
Package posts is everything users do with posts: write, edit, autosave, publish and delete them, comment on them, prompt others to write, export and import a blog, and the API v1 that does the same for scripts.
service/proofread
Package proofread is the grammar check and the style review of a post the author is writing: it enforces the per-user hourly limits and the site's daily cap, records every call to the model, keeps a post's style reviews and the status of their notes, and ties the model's answers to the text (pkg/proofread).
Package proofread is the grammar check and the style review of a post the author is writing: it enforces the per-user hourly limits and the site's daily cap, records every call to the model, keeps a post's style reviews and the status of their notes, and ties the model's answers to the text (pkg/proofread).
service/reading
Package reading decides who may read what: a single post with its comments, a user's journal, the explore page, the feed and the RSS feeds built from them.
Package reading decides who may read what: a single post with its comments, a user's journal, the explore page, the feed and the RSS feeds built from them.
service/registry
Package registry builds every service over one store.
Package registry builds every service over one store.
service/shares
Package shares manages share links: a secret URL that shows one published post to anybody who has it, logged in or not.
Package shares manages share links: a secret URL that shows one published post to anybody who has it, logged in or not.
testutil
Package testutil holds the smallest, most widely used test helper: Must.
Package testutil holds the smallest, most widely used test helper: Must.
testutil/factory
Package factory builds valid rows for pcom's tables so that tests (and cmd/seed) don't have to know the schema.
Package factory builds valid rows for pcom's tables so that tests (and cmd/seed) don't have to know the schema.
testutil/fakesender
Package fakesender is a fake of github.com/can3p/pcom/pkg/repo.MailQueue for unit and package tests: it records every mail instead of delivering it.
Package fakesender is a fake of github.com/can3p/pcom/pkg/repo.MailQueue for unit and package tests: it records every mail instead of delivering it.
testutil/fakestorage
Package fakestorage is an in-memory implementation of github.com/can3p/pcom/pkg/media/server.MediaStorage, for tests that exercise upload/download code without a real object store.
Package fakestorage is an in-memory implementation of github.com/can3p/pcom/pkg/media/server.MediaStorage, for tests that exercise upload/download code without a real object store.
testutil/ginctx
Package ginctx builds a *gin.Context for a handler test, wired up the way cmd/web/main.go wires a real request: a cookie-backed session under the name "sess".
Package ginctx builds a *gin.Context for a handler test, wired up the way cmd/web/main.go wires a real request: a cookie-backed session under the name "sess".
testutil/golden
Package golden compares test output against a checked-in file, the convention docs/testing.md uses for mail content: run with UPDATE_GOLDEN=1 to write the file, and without it to check the current output still matches.
Package golden compares test output against a checked-in file, the convention docs/testing.md uses for mail content: run with UPDATE_GOLDEN=1 to write the file, and without it to check the current output still matches.
testutil/seed
Package seed fills a development database with a small, named world that exercises every feature of pcom.
Package seed fills a development database with a small, named world that exercises every feature of pcom.
testutil/testdb
Package testdb gives a test its own empty Postgres database with pcom's migrations applied.
Package testdb gives a test its own empty Postgres database with pcom's migrations applied.
testutil/testlog
Package testlog records what code under test logs, so a test can assert on the entries.
Package testlog records what code under test logs, so a test can assert on the entries.
testutil/tommy
Package tommy runs one tommy container (github.com/can3p/tommy) per test binary: the Mailjet API mail is sent to, and the S3 bucket user media is stored in.
Package tommy runs one tommy container (github.com/can3p/tommy) per test binary: the Mailjet API mail is sent to, and the S3 bucket user media is stored in.
testutil/wiremock
Package wiremock runs one WireMock container per test binary.
Package wiremock runs one WireMock container per test binary.
web
web/app
Package app assembles the web server: it wires the handlers of every area onto one gin engine.
Package app assembles the web server: it wires the handlers of every area onto one gin engine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL