Files
plspace/README.md
T
2026-07-29 17:22:24 +09:00

122 lines
4.7 KiB
Markdown

# plspace
*It's always Pleroma.*
A static, client-side frontend for Pleroma that looks and behaves like MySpace
circa 2005.
This is a 100% Claude and ChatGPT vibe-coded application.
Point it at your server. It talks to that server's REST API directly from the
browser — there is no plspace backend, and `dist/` is a folder of static files
you can host anywhere.
## Repository
The canonical repository is hosted on Radicle:
`rad://z2gAKC6ESt5ZBV419uVPf2vFtEHCT`.
The backup mirror is
[`https://git.shipoclu.com/moon/plspace.git`](https://git.shipoclu.com/moon/plspace.git).
## What it looks like
| MySpace | plspace |
| --- | --- |
| Profile page: photo, headline, vitals, Contacting box, Interests table | `#/@user@server` |
| Latest Blog Entries with "(view more)" | Account statuses, headline list |
| Blurbs: "About me", "Who I'd like to meet" | The bio, split on a heading if you wrote one |
| Friend Space grid | Followers |
| Mail Center, Friend Request Manager | Notifications, follow requests |
| Bulletin Space | The local timeline |
| Kudos | Favourites |
| Custom profile layouts | CSS in a profile field named `css` |
## Running it
```bash
npm install && npm run dev
```
```bash
npm run build
```
`npm run build` type-checks and then bundles to `dist/`. Because routing is
hash-based, the output works from any path — a subdirectory, an S3 bucket,
GitHub Pages — with no server rewrite rules.
## Signing in
plspace registers itself as an OAuth app on your server the first time you sign
in there, then redirects you to that server's own consent screen. Your password
is never entered into plspace; it only ever receives an access token, which is
stored in `localStorage` and used directly from your browser.
PKCE is used where the server supports it, with an automatic fallback for
servers that don't.
You can also browse without signing in — click **Just look around**. Note that
many servers set `restrict_unauthenticated` and refuse timeline reads from
anonymous callers; the suggested servers on the sign-in page are ones verified
to allow it.
## Making it yours
Settings has a CSS editor, five starter layouts, and a full class reference.
Everything about the appearance is overridable — see
[`src/styles/README.md`](src/styles/README.md) for the contract. In short:
no CSS framework, no Svelte scoped styles, no hashed class names, every colour
and metric is a custom property, and user CSS is always last in the cascade so
plain single-class selectors win without `!important`.
There is no built-in dark mode. A dark theme is just token overrides, so it ships
as a preset (**Midnight**, **Terminal**) you can apply, edit or replace, rather
than as a toggle you can't.
To publish a layout other people see on your profile, put CSS in a profile field
named `css` on your server. It is scoped to your profile's subtree and filtered
before it is applied.
Your profile fields also drive the profile page: name one `Music`, `Movies`,
`Television`, `Books` or `Heroes` and it fills the Interests table; name one
`Mood`, `Location`, `Gender` or `Headline` and it fills the block beside your
photo.
## Layout
```
src/
lib/
api/ client (fetch, Link-header pagination), OAuth, endpoints, entity types
stores/ session, Feed (cursor pagination), theme (user + profile CSS)
util/ HTML sanitizing, 2005-flavoured date formats, account -> profile mapping
router.svelte.ts
themes.ts starter layouts, written only in terms of tokens
components/
chrome/ header, nav, footer
common/ Module, RichText, Avatar, Pager, TabBar
profile/ identity, contacting box, interests, details, friend space
blog/ entry, attachments, poll, preview card, composer
people/ person row and list
routes/ Home, Profile, Timeline, StatusPage, Mail, Browse, Search, Compose, Login, Settings
styles/ tokens, base, layout, chrome, module, profile, blog, forms
```
## Safety notes
All HTML from the API — post content, bios, profile field values — is sanitized
with DOMPurify before it reaches `{@html}`, in exactly one component
(`RichText.svelte`) plus the profile-field helper. Mention and hashtag links are
rewritten to in-app routes; every other link gets `target="_blank"` with
`rel="noopener noreferrer"`.
## Compatibility
Written against the standard `/api/v1` REST API and tested against live servers.
Anything implementations differ on degrades rather than fails: `/api/v2/instance`
falls back to v1, `/api/v1/accounts/lookup` falls back to search, pagination
falls back to the last item's id when a server drops the `Link` header, and
per-account privacy flags are read in both their spellings. Other software
speaking the same API therefore works, but Pleroma is what this targets.