docs: sync README with actual features, fix default port to 8000
- Add missing features: profile fields, custom CSS, visibility levels, CW/sensitive, feed sort/filter, popular tags, account migration - Fix top friends limit: 5→8 - Default PORT 3000→8000 in code, README, and .env.example - Deduplicate frontend env docs, update contributing section
This commit is contained in:
26
README.md
26
README.md
@@ -14,7 +14,14 @@ A self-hosted microblogging server with full ActivityPub federation. Write short
|
|||||||
- JWT authentication (Bearer token) with API key support for third-party clients
|
- JWT authentication (Bearer token) with API key support for third-party clients
|
||||||
- OpenAPI documentation at `/docs` (Swagger UI) and `/scalar` (Scalar)
|
- OpenAPI documentation at `/docs` (Swagger UI) and `/scalar` (Scalar)
|
||||||
- Full-text search over thoughts and users via PostgreSQL trigram indexes
|
- Full-text search over thoughts and users via PostgreSQL trigram indexes
|
||||||
- Top friends — pin up to 5 users as highlighted contacts
|
- **Profile fields** — up to 4 custom key/value fields (Website, Pronouns, etc.), federated as AP `PropertyValue` attachment
|
||||||
|
- **Custom CSS** — per-user stylesheet applied to their profile page
|
||||||
|
- **Visibility levels** — public, followers-only, unlisted, and direct posts
|
||||||
|
- **Content warnings** — optional CW label and sensitive flag on posts
|
||||||
|
- **Feed controls** — sort by newest, oldest, most liked, most boosted, or most discussed; filter to originals only, replies only, local only, or hide sensitive
|
||||||
|
- **Popular tags** — trending hashtag discovery
|
||||||
|
- Top friends — pin up to 8 users as highlighted contacts
|
||||||
|
- Account migration — set `alsoKnownAs` for Fediverse actor moves
|
||||||
- Home feed, public feed, and per-user thought timelines
|
- Home feed, public feed, and per-user thought timelines
|
||||||
- Rate limiting and registration control
|
- Rate limiting and registration control
|
||||||
|
|
||||||
@@ -108,7 +115,7 @@ Copy `.env.example` to `.env` and fill in your values.
|
|||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `HOST` | `0.0.0.0` | Interface to bind |
|
| `HOST` | `0.0.0.0` | Interface to bind |
|
||||||
| `PORT` | `3000` | Port to listen on |
|
| `PORT` | `8000` | Port to listen on |
|
||||||
| `NATS_URL` | — | NATS connection string. If unset, a no-op publisher is used and events are not delivered to the worker |
|
| `NATS_URL` | — | NATS connection string. If unset, a no-op publisher is used and events are not delivered to the worker |
|
||||||
| `CORS_ORIGINS` | `*` | Comma-separated allowed origins for CORS, e.g. `https://app.example.com` |
|
| `CORS_ORIGINS` | `*` | Comma-separated allowed origins for CORS, e.g. `https://app.example.com` |
|
||||||
| `RATE_LIMIT` | disabled | Max requests per minute per IP |
|
| `RATE_LIMIT` | disabled | Max requests per minute per IP |
|
||||||
@@ -201,18 +208,7 @@ Interactive API documentation is available at runtime:
|
|||||||
|
|
||||||
## Frontend
|
## Frontend
|
||||||
|
|
||||||
The Next.js frontend lives in `thoughts-frontend/`. It requires two environment variables:
|
The Next.js frontend lives in `thoughts-frontend/`. See [Frontend environment](#frontend-environment) for required env vars, or follow the [local development](#local-development-recommended) steps above.
|
||||||
|
|
||||||
```env
|
|
||||||
NEXT_PUBLIC_API_URL=http://localhost:8000 # client-side requests
|
|
||||||
NEXT_PUBLIC_SERVER_SIDE_API_URL=http://localhost:8000 # SSR requests
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd thoughts-frontend
|
|
||||||
bun install
|
|
||||||
bun run dev # http://localhost:3000
|
|
||||||
```
|
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
@@ -270,7 +266,7 @@ Services:
|
|||||||
|
|
||||||
Contributions are welcome. A few guidelines:
|
Contributions are welcome. A few guidelines:
|
||||||
|
|
||||||
- **Run tests before opening a PR.** At minimum: `cargo test -p application` (no database needed). For adapter changes: `cargo test --workspace` with a live database.
|
- **Run tests before opening a PR.** At minimum: `make test-unit` (no database needed). For adapter changes: `make test-integration` with a live database. `make check` runs the full suite (fmt + clippy + tests).
|
||||||
- **Keep the hexagonal boundary.** `domain` and `application` must not import any adapter crate. Use `&dyn Port` traits for all I/O.
|
- **Keep the hexagonal boundary.** `domain` and `application` must not import any adapter crate. Use `&dyn Port` traits for all I/O.
|
||||||
- **No ORM.** The project uses raw `sqlx`. Keep it that way.
|
- **No ORM.** The project uses raw `sqlx`. Keep it that way.
|
||||||
- **ActivityPub changes** — test against a live Mastodon instance if possible, or use the AP debug logs (`RUST_ENV=development`).
|
- **ActivityPub changes** — test against a live Mastodon instance if possible, or use the AP debug logs (`RUST_ENV=development`).
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ impl Config {
|
|||||||
Self {
|
Self {
|
||||||
database_url: std::env::var("DATABASE_URL").expect("DATABASE_URL is required"),
|
database_url: std::env::var("DATABASE_URL").expect("DATABASE_URL is required"),
|
||||||
jwt_secret: std::env::var("JWT_SECRET").expect("JWT_SECRET is required"),
|
jwt_secret: std::env::var("JWT_SECRET").expect("JWT_SECRET is required"),
|
||||||
base_url: std::env::var("BASE_URL").unwrap_or_else(|_| "http://localhost:3000".into()),
|
base_url: std::env::var("BASE_URL").unwrap_or_else(|_| "http://localhost:8000".into()),
|
||||||
nats_url: std::env::var("NATS_URL").ok(),
|
nats_url: std::env::var("NATS_URL").ok(),
|
||||||
port: std::env::var("PORT")
|
port: std::env::var("PORT")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(3000),
|
.unwrap_or(8000),
|
||||||
allow_registration: std::env::var("ALLOW_REGISTRATION")
|
allow_registration: std::env::var("ALLOW_REGISTRATION")
|
||||||
.map(|v| v == "true")
|
.map(|v| v == "true")
|
||||||
.unwrap_or(true),
|
.unwrap_or(true),
|
||||||
|
|||||||
Reference in New Issue
Block a user