{"id":51457081,"url":"https://github.com/jpbaking/shred-after-reading","last_synced_at":"2026-07-06T01:03:55.757Z","repository":{"id":369420771,"uuid":"1289780236","full_name":"jpbaking/shred-after-reading","owner":"jpbaking","description":"Self-destructing text shares — Docker Compose app with a React front end, Express + Prisma API, and PostgreSQL. Public /sar/\u003cid\u003e links with optional per-share passwords and admin moderation.","archived":false,"fork":false,"pushed_at":"2026-07-05T07:44:03.000Z","size":187,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-05T09:13:40.219Z","etag":null,"topics":["docker-compose","express","nginx","postgresql","prisma","react","self-destructing-messages","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"0bsd","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jpbaking.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":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-05T07:35:46.000Z","updated_at":"2026-07-05T07:44:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jpbaking/shred-after-reading","commit_stats":null,"previous_names":["jpbaking/shred-after-reading"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jpbaking/shred-after-reading","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fshred-after-reading","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fshred-after-reading/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fshred-after-reading/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fshred-after-reading/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpbaking","download_url":"https://codeload.github.com/jpbaking/shred-after-reading/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fshred-after-reading/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35174081,"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-05T02:00:06.290Z","response_time":100,"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-compose","express","nginx","postgresql","prisma","react","self-destructing-messages","typescript"],"created_at":"2026-07-06T01:03:55.087Z","updated_at":"2026-07-06T01:03:55.713Z","avatar_url":"https://github.com/jpbaking.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ShredAfterReading\n\nShredAfterReading is a Docker Compose app for self-destructing text shares. It ships with:\n\n- Nginx fronting a React app and an Express + Prisma API\n- PostgreSQL for users, sessions, SARs, and settings\n- Mailpit for local email verification\n- Public `/sar/\u003cid\u003e` links with optional per-SAR passwords\n- An `/administration` area for user moderation, SAR inspection, and global expiry control\n\n## Prerequisites\n\n- Node.js 24+\n- npm\n- Docker with the Compose v2 plugin\n- `python3` for the smoke scripts\n\n## Local Setup\n\n1. Install dependencies:\n\n   ```bash\n   (cd apps/api \u0026\u0026 npm install)\n   (cd apps/web \u0026\u0026 npm install)\n   ```\n\n   Dependencies now live only under `apps/api/node_modules` and `apps/web/node_modules`; the repo root has no shared Node workspace.\n\n2. Copy the root app env file and change at least `ADMIN_PASSWORD` before exposing the stack beyond your machine:\n\n   ```bash\n   cp .env.example .env\n   ```\n\n3. Review `compose-helper.env` if you want to override helper-only behavior such as the compose project name or log tail length.\n\n4. Start the stack with the helper, not raw `docker compose`:\n\n   ```bash\n   ./compose-helper.sh rebuild\n   ```\n\n5. Open:\n\n   - Main app: `http://localhost:8080`\n   - Admin app: `http://localhost:8080/administration`\n   - Mailpit: `http://localhost:8025`\n\n## Environment Variables\n\n### Compose stack\n\n`compose-helper.env` is now helper-only configuration:\n\n- `DCH_PROJECT_NAME`, `DCH_STOP_TIMEOUT`, `DCH_LOGS_TAIL`\n\nThe real app and stack settings live in the root `.env` / `.env.example`:\n\n- `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`\n- `APP_PORT`\n- `PORT`, `BODY_SIZE_LIMIT`\n- `ADMIN_EMAIL`, `ADMIN_PASSWORD`\n- `DATABASE_URL`\n- `APP_BASE_URL`, `COOKIE_SECURE`\n- `SMTP_HOST`, `SMTP_PORT`, `SMTP_FROM_ADDRESS`\n- `SESSION_TTL_HOURS`, `REMEMBER_ME_TTL_DAYS`, `EMAIL_VERIFICATION_TTL_DAYS`\n\n### Host-side API / Prisma commands\n\nThe API and Prisma host-side commands also read the root `.env`, so there is no second app env file to keep in sync.\n\n## Compose Helper Commands\n\nUse `./compose-helper.sh`, not raw `docker compose`, for normal project operations.\n\nThe helper is surfaced at the root, while the actual compose stack files live under `.compose/` so the project root stays cleaner.\n\n- Validate compose config: `./compose-helper.sh config --quiet`\n- Build and start: `./compose-helper.sh rebuild`\n- Start without rebuilding: `./compose-helper.sh start`\n- Stop without wiping volumes: `./compose-helper.sh stop`\n- Inspect services: `./compose-helper.sh ps`\n- Read recent logs without following forever: `./compose-helper.sh logs --tail=100`\n\nNever run `./compose-helper.sh down` unless you explicitly want to wipe named volumes.\n\n## Mailpit Verification Flow\n\nLocal registrations send email through Mailpit. You can:\n\n- Open `http://localhost:8025`\n- Find the verification email\n- Open the `verify-email` link inside it\n\nThe auth smoke test automates that flow:\n\n```bash\nbash scripts/smoke-auth.sh\n```\n\n## Admin Bootstrap\n\nOn seed, the API creates or promotes the account from `ADMIN_EMAIL` / `ADMIN_PASSWORD` and marks it verified. That account can sign in on `http://localhost:8080/administration`.\n\n## Testing And Verification\n\nApp checks:\n\n```bash\n(cd apps/api \u0026\u0026 npm run build \u0026\u0026 npm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test)\n(cd apps/web \u0026\u0026 npm run build \u0026\u0026 npm run typecheck \u0026\u0026 npm run test)\n```\n\nAPI-only checks:\n\n```bash\ncd apps/api\nnpm run test\nnpm run typecheck\nnpm run lint\nnpm run build\nnpx prisma validate --schema prisma/schema.prisma\n```\n\nWeb-only checks:\n\n```bash\ncd apps/web\nnpm run test\nnpm run typecheck\nnpm run build\n```\n\nDocker smoke checks:\n\n```bash\nbash scripts/smoke-auth.sh\nbash scripts/smoke-sar.sh\nbash scripts/smoke-admin.sh\n```\n\n## Security Choices\n\nThe current security and lifecycle contract is:\n\n- Raw HTML inside Markdown is disabled; scripts and unsafe URLs must never execute.\n- Plain-text SARs render as text, not HTML.\n- Email verification is required before protected user actions.\n- Sessions are opaque, server-side, and stored hashed at rest.\n- SAR passwords are optional per note and stored only as strong hashes.\n- Owner deletes are soft deletes; expired and deleted SARs remain admin-visible for 30 days, then cleanup purges them.\n- Admins can lower the global expiry limit for future SAR creation and future expiry edits, but existing SAR expiries are left unchanged.\n\n## License\n\n[0BSD](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpbaking%2Fshred-after-reading","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpbaking%2Fshred-after-reading","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpbaking%2Fshred-after-reading/lists"}