From 565026d24c58e2d8f096394e2f28c2639947494f Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 11:09:19 -0500 Subject: [PATCH 1/7] Docs: add "Developing a backend" --- docs/development/developing-backend.md | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/development/developing-backend.md diff --git a/docs/development/developing-backend.md b/docs/development/developing-backend.md new file mode 100644 index 000000000..af4400e9f --- /dev/null +++ b/docs/development/developing-backend.md @@ -0,0 +1,76 @@ +# Developing a backend + +Soapbox expects backends to implement the [Mastodon API](https://docs.joinmastodon.org/methods/). + +At the very least: + +- [instance](https://docs.joinmastodon.org/methods/instance/) +- [apps](https://docs.joinmastodon.org/methods/apps/) +- [oauth](https://docs.joinmastodon.org/methods/apps/oauth/) +- [accounts](https://docs.joinmastodon.org/methods/accounts/) +- [statuses](https://docs.joinmastodon.org/methods/statuses/) + +Soapbox uses feature-detection on the instance to determine which features to show. +By default, a minimal featureset is used. + +## Feature detection + +First thing, Soapbox fetches GET `/api/v1/instance` to identify the backend. +The instance should respond with a `version` string: + +```js +{ + "title": "Soapbox", + "short_description": "hello world!", + // ... + "version": "2.7.2 (compatible; Pleroma 2.4.52+soapbox)" +} +``` + +The version string should match this format: + +``` +COMPAT_VERSION (compatible; BACKEND_NAME VERSION) +``` + +The Regex used to parse it: + +```js +/^([\w+.]*)(?: \(compatible; ([\w]*) (.*)\))?$/ +``` + +- `COMPAT_VERSION` - The highest Mastodon API version this backend is compatible with. If you're not sure, use a lower version like `2.7.2`. It MUST follow [semver](https://semver.org/). +- `BACKEND_NAME` - Human-readable name of the backend. No spaces! +- `VERSION` - The actual version of the backend. It MUST follow [semver](https://semver.org/). + +Typically checks are done against `BACKEND_NAME` and `VERSION`. + +The version string is similar in purpose to a [User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) string. +The format was first invented by Pleroma, but is now widely used, including by Pixelfed, Mitra, and Soapbox BE. + +See [`features.ts`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/app/soapbox/utils/features.ts) for the complete list of features. + +## Forks of other software + +If your software is a fork of another software, the version string should indicate that. +Otherwise, Soapbox will use the minimal featureset. + +### Forks of Mastodon + +Mastodon forks do not need the compat section, and can simply append `+[NAME]` to the version string (eg Glitch Social): + +``` +3.2.0+glitch +``` + +### Forks of Pleroma + +For Pleroma forks, the fork name should be in the compat section (eg Soapbox BE): + +``` +2.7.2 (compatible; Pleroma 2.4.52+soapbox) +``` + +## Adding support for a new backend + +If the backend conforms to the above format, please modify [`features.ts`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/app/soapbox/utils/features.ts) and submit a merge request to enable features for your backend! From 517e9f088c54dc27db8e9a4944dd809573d254a0 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 11:28:29 -0500 Subject: [PATCH 2/7] Improve README explanation and local dev instructions --- README.md | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 0422c88d5..53bfeb8f9 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ It's not necessary to restart the Pleroma service. To remove Soapbox FE and revert to the default pleroma-fe, simply `rm /opt/pleroma/instance/static/index.html` (you can delete other stuff in there too, but be careful not to delete your own HTML files). +## :elephant: Deploy on Mastodon + +See [Installing Soapbox over Mastodon](https://docs.soapbox.pub/frontend/administration/mastodon/). + ## How does it work? Soapbox FE is a [single-page application (SPA)](https://en.wikipedia.org/wiki/Single-page_application) that runs entirely in the browser with JavaScript. @@ -38,7 +42,23 @@ Soapbox FE is a [single-page application (SPA)](https://en.wikipedia.org/wiki/Si It has a single HTML file, `index.html`, responsible only for loading the required JavaScript and CSS. It interacts with the backend through [XMLHttpRequest (XHR)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). -It incorporates much of the [Mastodon API](https://docs.joinmastodon.org/methods/) used by Pleroma and Mastodon, but requires many [Pleroma-specific features](https://docs.pleroma.social/backend/development/API/differences_in_mastoapi_responses/) in order to function. +Here is a simplified example with Nginx: + +```nginx +location /api { + proxy_pass http://backend; +} + +location / { + root /opt/soapbox; + try_files $uri index.html; +} +``` + +(See [`mastodon.conf`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/installation/mastodon.conf) for a full example.) + +Soapbox incorporates much of the [Mastodon API](https://docs.joinmastodon.org/methods/), [Pleroma API](https://api.pleroma.social/), and more. +It detects features supported by the backend to provide the right experience for the backend. # Running locally @@ -65,8 +85,9 @@ yarn dev It will serve at `http://localhost:3036` by default. -It will proxy requests to the backend for you. -For Pleroma running on `localhost:4000` (the default) no other changes are required, just start a local Pleroma server and it should begin working. +You should see an input box - just enter the domain name of your instance to log in. + +Tip: you can even enter a local instance like `http://localhost:3000`! ### Troubleshooting: `ERROR: NODE_ENV must be set` @@ -79,26 +100,10 @@ cp .env.example .env And ensure that it contains `NODE_ENV=development`. Try again. -## Developing against a live backend +### Troubleshooting: it's not working! -You can also run Soapbox FE locally with a live production server as the backend. - -> **Note:** Whether or not this works depends on your production server. It does not seem to work with Cloudflare or VanwaNet. - -To do so, just copy the env file: - -```sh -cp .env.example .env -``` - -And edit `.env`, setting the configuration like this: - -```sh -BACKEND_URL="https://pleroma.example.com" -PROXY_HTTPS_INSECURE=true -``` - -You will need to restart the local development server for the changes to take effect. +Run `node -V` and compare your Node.js version with the version in [`.tool-versions`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/.tool-versions). +If they don't match, try installing [asdf](https://asdf-vm.com/). ## Local Dev Configuration From 796cbcbc150706360ac3fdce5b8040392bfb9c7c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 11:46:49 -0500 Subject: [PATCH 3/7] Add VSCode recommended extensions --- .vscode/extensions.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..ed8d35343 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", + "bradlc.vscode-tailwindcss", + "stylelint.vscode-stylelint" + ] +} From 3de03d9d56e0df1c5b02234060edfd61b00d1c6c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 11:46:59 -0500 Subject: [PATCH 4/7] Rewrite contributing docs --- docs/contributing.md | 63 +++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index ba2fa09ac..47a7b747d 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,55 +1,34 @@ # Contributing to Soapbox -When contributing to Soapbox, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. +Thank you for your interest in Soapbox! -## Project Contribution Flow +When contributing to Soapbox, please first discuss the change you wish to make by [opening an issue](https://gitlab.com/soapbox-pub/soapbox-fe/-/issues). -It is recommended that you use the following guidelines to contribute to the Soapbox project: +## Opening an MR (merge request) -* Understand recommended [GitLab Flow](https://www.youtube.com/watch?v=InKNIvky2KE) methods on branch management -* Use the following branch management process: - * Pull a fork - * Mirror the fork against the original repository, setting the mirror to only mirror to protected branches - * Set the master branch in your fork to Protected - * Never modify the master branch in your fork, so that your fork mirroring does not break - * Pull branches in your fork to solve specific issues - * Do merge requests only to the original repository master branch, so that your fork mirroring does not break -* If you don't use the above policy, when your mirrored fork breaks mirroring, you can force your fork to back to successful mirroring using the following process: - * Unprotect the master branch of your fork from force push - * Use the following git commands from the cmd line of your local copy of your fork's master branch - ``` - git remote add upstream /url/to/original/repo - git fetch upstream - git checkout master - git reset --hard upstream/master - git push origin master --force - ``` - * Re-protect the master branch of your fork from force push +1. Smash that "fork" button on GitLab to make a copy of the repo. +2. Clone the repo locally, then begin work on a new branch (eg not `develop`). +3. Push your branch to your fork. +4. Once pushed, GitLab should provide you with a URL to open a new merge request right in your terminal. If not, do it [manually](https://gitlab.com/soapbox-pub/soapbox-fe/-/merge_requests/new). -## Pull Request Process +### Ensuring the CI pipeline succeeds -1. Ensure any install or build dependencies are removed before the end of the layer when doing a - build. -2. Update the README.md with details of changes to the interface, this includes new environment - variables, exposed ports, useful file locations and container parameters. -3. Increase the version numbers in any examples files and the README.md to the new version that this - Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). -4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you - do not have permission to do that, you may request the second reviewer to merge it for you. +When you push to a branch, the CI pipeline will run. -## Text Editor Tools +[Soapbox uses GitLab CI](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/.gitlab-ci.yml) to lint, run tests, and verify changes. +It's important this pipeline passes, otherwise we cannot merge the change. -If you're using a text editor like [Atom](https://atom.io/) or [Visual Studio Code](https://code.visualstudio.com/), you can install tools to help you get linter feedback while you write code for the Soapbox project. +New users of gitlab.com may see a "detatched pipeline" error. +If so, please check the following: -For Atom, you can install the following packages: +1. Your GitLab email address is confirmed. +2. You may have to have a credit card on file before the CI job will run. -* [linter](https://atom.io/packages/linter) -* [linter-ui-default](https://atom.io/packages/linter-ui-default) -* [linter-eslint](https://atom.io/packages/linter-eslint) -* [linter-stylelint](https://atom.io/packages/linter-stylelint) +## Text editor -For Visual Studio Code, you can install the following extensions: +We recommend developing Soapbox with [VSCodium](https://vscodium.com/) (or its proprietary ancestor, [VS Code](https://code.visualstudio.com/)). -* [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) -* [vscode-stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) +This will help give you feedback about your changes _in the editor itself_ before GitLab CI performs linting, etc. + +When this project is opened in Code it will automatically recommend extensions. +See [`.vscode/extensions.json`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/.vscode/extensions.json) for the full list. From 2e0a8e864e55d9133268fe72fbf04c88dba295e4 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 11:48:55 -0500 Subject: [PATCH 5/7] Remove outdated Redux store docs --- README.md | 7 +- docs/store.md | 930 -------------------------------------------------- 2 files changed, 2 insertions(+), 935 deletions(-) delete mode 100644 docs/store.md diff --git a/README.md b/README.md index 53bfeb8f9..3afa9d04f 100644 --- a/README.md +++ b/README.md @@ -170,11 +170,8 @@ NODE_ENV=development # Contributing -We welcome contributions to this project. To contribute, first review the [Contributing doc](docs/contributing.md) - -Additional supporting documents include: -* [Soapbox History](docs/history.md) -* [Redux Store Map](docs/history.md) +We welcome contributions to this project. +To contribute, see [Contributing to Soapbox](docs/contributing.md). # Customization diff --git a/docs/store.md b/docs/store.md deleted file mode 100644 index 994059c22..000000000 --- a/docs/store.md +++ /dev/null @@ -1,930 +0,0 @@ -# Redux Store Map - -A big part of what makes soapbox-fe function is the [Redux](https://redux.js.org/) store. -Redux is basically a database of everything your frontend needs to know about in the form of a giant JSON object. - -To work with Redux, you will want to install the [Redux browser extension](https://extension.remotedev.io/). -This will allow you to see the full Redux store when working in development. - -Due to the large size of the Redux store in soapbox-fe, it's worth documenting the purpose of each path. - -If it's not documented, it's because I inherited it from Mastodon and I don't know what it does yet. - -- `dropdown_menu` - - Sample: - ``` - dropdown_menu: { - openId: null, - placement: null, - keyboard: false - } - ``` - -- `timelines` - - Sample: - ``` - timelines: { - home: { - items: [ - '9uiMtlRMLHBnRg8tMG', - '9uiLe5Q6Bsb8p8VslU', - '9uiLMqdbtfE03Tc4uW', - '9uiLEal13YvYUB8lN2', - '9uiKwwSPdc0iZg1SUK', - '9uiKq5TRiRJGVoEmau', - '9uiKbTN4aHsmHgHtsO', - '9ugVkEfNKtvGSpJGLI' - ], - totalQueuedItemsCount: 0, - queuedItems: [], - hasMore: true, - unread: 0, - isLoading: false, - online: true, - top: true, - isPartial: false - } - } - ``` - -- `meta` - User-specific data that is _not_ a frontend setting (see: `settings`). - - Sample: - ``` - meta: { - pleroma: { - unread_conversation_count: 0, - hide_follows: false, - hide_followers_count: false, - background_image: 'https://dev.teci.world/media/74644a40461bb85fa41db02547b656fa382e0e2ada29021059ff2a2956c1bbab.jpg', - confirmation_pending: false, - is_moderator: false, - deactivated: false, - chat_token: 'SFMyNTY.g3QAAAACZAAEZGF0YW0AAAASOXRvMU5QeVM5OEo4Y2RpY1JFZAAGc2lnbmVkbgYAcH3yxnEB.qD9qQzEfRH4sfJQfPCJQKHayVUQ6_1m6t5iqE7jB17Q', - allow_following_move: true, - hide_follows_count: false, - notification_settings: { - followers: true, - follows: true, - non_followers: true, - non_follows: true, - privacy_option: false - }, - hide_followers: false, - relationship: { - showing_reblogs: true, - followed_by: false, - subscribing: false, - blocked_by: false, - requested: false, - domain_blocking: false, - following: false, - endorsed: false, - blocking: false, - muting: false, - id: '9to1NPyS98J8cdicRE', - muting_notifications: false - }, - tags: [], - hide_favorites: true, - is_admin: true, - skip_thread_containment: false - } - } - ``` - -- `pleroma` - Pleroma specific metadata about the user pulled from `/api/v1/accounts/verify_credentials` (excluding the pleroma_settings_store) - -- `alerts` - - Sample: - ``` - alerts: [] - ``` - -- `modal` - - Sample: - ``` - modal: { - modalType: null, - modalProps: {} - } - ``` -- `user_lists` - - Sample: - ``` - user_lists: { - reblogged_by: {}, - blocks: {}, - groups_removed_accounts: {}, - following: {}, - follow_requests: {}, - groups: {}, - followers: {}, - mutes: {}, - favourited_by: {}, - birthday_reminders: {} - } - ``` - -- `domain_lists` - - Sample: - ``` - domain_lists: { - blocks: { - items: [] - } - } - ``` - -- `status_lists` - - Sample: - ``` - status_lists: { - favourites: { - next: null, - loaded: false, - items: [ - '9uh7FiM4hViVp59hSa', - '9uhsxmGKEMBkWoykng' - ] - }, - pins: { - next: null, - loaded: false, - items: [] - } - } - ``` -- `accounts` - Data for all accounts you've viewed since launching the page, so they don't have to be downloaded twice. - - Sample: - ``` - accounts: { - '9to1NPyS98J8cdicRE': { - header_static: 'https://dev.teci.world/media/27272c6f53a8a535d2c11a98d3b3473833bf80192e82347548b9f1b6dc4027ab.jpg', - display_name_html: 'crockwave', - follow_requests_count: 0, - bot: false, - display_name: 'crockwave', - created_at: '2020-04-07T16:29:04.000Z', - locked: false, - emojis: [], - header: 'https://dev.teci.world/media/27272c6f53a8a535d2c11a98d3b3473833bf80192e82347548b9f1b6dc4027ab.jpg', - url: 'https://dev.teci.world/users/curtis', - note: '', - acct: 'curtis', - avatar_static: 'https://dev.teci.world/media/3e41f0e4e0b7e673959061f90c69a57ff547bd48ccca90df5d46be87a874febd.png', - username: 'curtis', - avatar: 'https://dev.teci.world/media/3e41f0e4e0b7e673959061f90c69a57ff547bd48ccca90df5d46be87a874febd.png', - fields: [], - pleroma: { - unread_conversation_count: 0, - hide_follows: false, - hide_followers_count: false, - background_image: 'https://dev.teci.world/media/74644a40461bb85fa41db02547b656fa382e0e2ada29021059ff2a2956c1bbab.jpg', - confirmation_pending: false, - is_moderator: false, - deactivated: false, - allow_following_move: true, - hide_follows_count: false, - notification_settings: { - followers: true, - follows: true, - non_followers: true, - non_follows: true, - privacy_option: false - }, - hide_followers: false, - relationship: { - showing_reblogs: true, - followed_by: false, - subscribing: false, - blocked_by: false, - requested: false, - domain_blocking: false, - following: false, - endorsed: false, - blocking: false, - muting: false, - id: '9to1NPyS98J8cdicRE', - muting_notifications: false - }, - tags: [], - hide_favorites: true, - is_admin: true, - skip_thread_containment: false - }, - source: { - fields: [], - note: '', - pleroma: { - actor_type: 'Person', - discoverable: false, - no_rich_text: false, - show_role: true - }, - privacy: 'public', - sensitive: false - }, - id: '9to1NPyS98J8cdicRE', - note_emojified: '' - } - } - ``` - -- `accounts_counters` - - Sample: - ``` - accounts_counters: { - '9tyANut1gDEkHqrvo8': { - followers_count: 0, - following_count: 0, - statuses_count: 11 - }, - '9toQ7nsnbhnTcNVBxI': { - followers_count: 342, - following_count: 800, - statuses_count: 721 - }, - '9tqzs9mEQIBxYPBk0G': { - followers_count: 0, - following_count: 0, - statuses_count: 48 - } - } - ``` - -- `statuses` - Data for all statuses you've viewed since launching the page, so they don't have to be downloaded twice. - - Sample: - ``` - statuses: { - '9uVxGSYFo6ooon0ebQ': { - in_reply_to_account_id: null, - contentHtml: '

jpg test @curtis

', - mentions: [ - { - acct: 'curtis', - id: '9to1NPyS98J8cdicRE', - url: 'https://dev.teci.world/users/curtis', - username: 'curtis' - } - ], - created_at: '2020-04-28T21:10:16.000Z', - spoiler_text: '', - hidden: false, - muted: false, - uri: 'https://gleasonator.com/users/crockwave/statuses/104078260079111405', - spoilerHtml: '', - emojis: [], - account: '9toTIlRPKG2j5obki8', - reblogs_count: 0, - url: 'https://gleasonator.com/@crockwave/posts/104078260079111405', - application: { - name: 'Web', - website: null - }, - card: null, - in_reply_to_id: null, - reblogged: false, - visibility: 'public', - bookmarked: false, - reblog: null, - media_attachments: [ - { - description: null, - id: '1375732379', - pleroma: { - mime_type: 'image/jpeg' - }, - preview_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', - remote_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', - text_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', - type: 'image', - url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg' - } - ], - sensitive: false, - replies_count: 0, - language: null, - pinned: false, - tags: [], - content: '

jpg test @curtis

', - favourites_count: 0, - pleroma: { - direct_conversation_id: null, - spoiler_text: { - 'text/plain': '' - }, - local: false, - emoji_reactions: [], - thread_muted: false, - conversation_id: 1951, - content: { - 'text/plain': 'jpg test @curtis' - }, - in_reply_to_account_acct: null, - expires_at: null - }, - favourited: false, - id: '9uVxGSYFo6ooon0ebQ', - search_index: 'jpg test @curtis', - poll: null - } - } - ``` - -- `relationships` - - Sample: - ``` - relationships: {} - ``` - -- `settings` - Any frontend configuration values that should be persisted to the backend database. This includes user preferences as well as metadata such as emoji usage counters. It uses [`pleroma_settings_store`](https://docs-develop.pleroma.social/backend/API/differences_in_mastoapi_responses/#accounts) to do it if it's available. If there's some other endpoint that handles your value, it doesn't belong here. - - Sample: - ``` - settings: { - autoPlayGif: true, - displayMedia: 'default', - deleteModal: true, - unfollowModal: false, - frequentlyUsedEmojis: { - grinning: 1, - 'star-struck': 1 - }, - onboarded: false, - defaultPrivacy: 'private', - demetricator: false, - saved: true, - notifications: { - alerts: { - favourite: true, - follow: true, - mention: true, - poll: true, - reblog: true - }, - quickFilter: { - active: 'all', - advanced: false, - show: true - }, - shows: { - favourite: true, - follow: true, - mention: true, - poll: true, - reblog: true - }, - sounds: { - favourite: true, - follow: true, - mention: true, - poll: true, - reblog: true - }, - birthdays: { - show: true - } - }, - theme: 'azure', - 'public': { - other: { - onlyMedia: false - }, - regex: { - body: '' - } - }, - direct: { - regex: { - body: '' - } - }, - community: { - other: { - onlyMedia: false - }, - regex: { - body: '' - } - }, - boostModal: false, - dyslexicFont: false, - expandSpoilers: false, - skinTone: 1, - trends: { - show: true - }, - reduceMotion: false, - columns: [ - { - id: 'COMPOSE', - params: {}, - uuid: '8200299a-f689-45ad-ad33-c9eb20b6286c' - }, - { - id: 'HOME', - params: {}, - uuid: '1b1f69f4-d024-4d31-b5cd-b45fe77f4dc1' - }, - { - id: 'NOTIFICATIONS', - params: {}, - uuid: 'e8c3904c-bf54-4047-baaa-aa786afebb3b' - } - ], - systemFont: false, - underlineLinks: false, - home: { - regex: { - body: '' - }, - shows: { - reblog: true, - reply: true - } - } - } - ``` - -- `push_notifications` - - Sample: - ``` - push_notifications: { - subscription: null, - alerts: { - follow: false, - favourite: false, - reblog: false, - mention: false, - poll: false - }, - isSubscribed: false, - browserSupport: false - } - ``` -- `mutes` - - Sample: - ``` - mutes: { - 'new': { - isSubmitting: false, - account: null, - notifications: true - } - } - ``` - -- `reports` - - Sample: - ``` - reports: { - 'new': { - isSubmitting: false, - account_id: null, - status_ids: [], - comment: '', - forward: false - } - } - ``` - -- `contexts` - - Sample: - ``` - contexts: { - inReplyTos: { - '9uhsxm9adOniBvpNIm': '9uh7FiM4hViVp59hSa', - '9uiMtlRMLHBnRg8tMG': '9uiIk2f13yfg8mdfhg', - '9uiLe5Q6Bsb8p8VslU': '9uiIk2f13yfg8mdfhg', - '9uhBdzVeyImLnGTDZQ': '9uhB399i946ozmdRGC', - '9uiKLrbohWVWp5k0Su': '9uiJzdGZLWjBy9Ca24', - '9ui47WONBnvPhQalgu': '9ui47WHdaqXNMXROC0', - '9ui5t93pL19HC0FppI': '9ui5qe5DXbA8XQiFyS', - }, - replies: { - '9uhsxm9adOniBvpNIm': [ - '9uhsxmGKEMBkWoykng' - ], - '9ui8gFu0tBewVfD38y': [ - '9ui8gG1SRVc8skgzkO' - ], - '9uiIk2f13yfg8mdfhg': [ - '9uiJxjFm7BylxVvHPc', - '9uiJzdGZLWjBy9Ca24', - '9uiLe5Q6Bsb8p8VslU', - '9uiMtlRMLHBnRg8tMG' - ], - '9uiKLrbohWVWp5k0Su': [ - '9uiKbTN4aHsmHgHtsO' - ], - '9ui68mCA7SZwuSbfqi': [ - '9ui6Fz6cW4kGyiS3lo' - ] - } - } - ``` -- `compose` - - Sample: - ``` - compose: { - spoiler: false, - focusDate: null, - privacy: 'private', - spoiler_text: '', - in_reply_to: null, - default_privacy: 'private', - is_uploading: false, - caretPosition: null, - text: '', - preselectDate: null, - progress: 0, - idempotencyKey: '046ddfb7-ce76-4dbd-ae43-e6e8417947fd', - suggestions: [], - resetFileKey: 53748, - media_attachments: [], - sensitive: false, - default_sensitive: false, - mounted: 0, - is_composing: false, - tagHistory: [], - id: null, - is_submitting: false, - is_changing_upload: false, - suggestion_token: null, - poll: null - } - ``` - -- `search` - - Sample: - ``` - search: { - value: '', - submitted: false, - hidden: false, - results: {} - } - ``` -- `media_attachments` - - Sample: - ``` - media_attachments: { - accept_content_types: [ - '.jpg', - '.jpeg', - '.png', - '.gif', - '.webp', - '.webm', - '.mp4', - '.m4v', - '.mov', - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/webp', - 'video/webm', - 'video/mp4', - 'video/quicktime' - ] - } - ``` - -- `notifications` - - Sample: - ``` - notifications: { - items: [ - { - id: '27', - type: 'mention', - account: '9uXUwPp1pwGsA2Qh3A', - created_at: '2020-04-29T15:11:54.000Z', - status: '9uXVnHKu7Lu9BrXvCC' - }, - { - id: '8', - type: 'mention', - account: '9toQ7nsnbhnTcNVBxI', - created_at: '2020-04-27T19:16:44.000Z', - status: '9uTicLRt0ZoVX25ZvE' - }, - { - id: '7', - type: 'favourite', - account: '9toQ7nsnbhnTcNVBxI', - created_at: '2020-04-27T19:16:25.000Z', - status: '9uThsXbbTg6luknEmG' - } - ], - hasMore: true, - top: false, - unread: 0, - isLoading: false, - queuedNotifications: [], - totalQueuedNotificationsCount: 0, - lastRead: -1 - } - ``` - -- `height_cache` - - Sample: - ``` - height_cache: { - '9t06sd:home_timeline': { - '9uXhrY530I85jJvpwW': 164.171875, - '9uXVdgMQDqa1uGgESG': 300.140625, - '9uXWs4FmHnJW17zncW': 852.171875, - '9uXX4IfAXO0yBNhmQy': 166.171875, - '9uXXThi8XzE56gCtE0': 145.140625 - } - } - ``` - -- `custom_emojis` - - Sample: - ``` - custom_emojis: [ - { - category: 'Fun', - shortcode: 'blank', - static_url: 'https://dev.teci.world/emoji/blank.png', - tags: [ - 'Fun' - ], - url: 'https://dev.teci.world/emoji/blank.png', - visible_in_picker: true - }, - { - category: 'Gif,Fun', - shortcode: 'firefox', - static_url: 'https://dev.teci.world/emoji/Firefox.gif', - tags: [ - 'Gif', - 'Fun' - ], - url: 'https://dev.teci.world/emoji/Firefox.gif', - visible_in_picker: true - } - ] - ``` - -- `lists` - - Sample: - ``` - lists: {}, - ``` - -- `listEditor` - - Sample: - ``` - listEditor: { - listId: null, - isSubmitting: false, - isChanged: false, - title: '', - accounts: { - items: [], - loaded: false, - isLoading: false - }, - suggestions: { - value: '', - items: [] - } - } - ``` -- `listAdder` - - Sample: - ``` - listAdder: { - accountId: null, - lists: { - items: [], - loaded: false, - isLoading: false - } - } - ``` - -- `filters` - - Sample: - ``` - filters: [], - ``` - -- `conversations` - - Sample: - ``` - conversations: { - items: [], - isLoading: false, - hasMore: true, - mounted: false - } - ``` - -- `suggestions` - - Sample: - ``` - suggestions: { - items: [], - isLoading: false - }, - ``` - -- `polls` - - Sample: - ``` - polls: {} - ``` -- `trends` - - Sample: - ``` - trends: { - items: [], - isLoading: false - } - ``` - -- `groups` - - Sample: - ``` - groups: {} - ``` -- `group_relationships` - - Sample: - ``` - group_relationships: {} - ``` - -- `group_lists` - - Sample: - ``` - group_lists: { - featured: [], - member: [], - admin: [] - } - ``` - -- `group_editor` - - Sample: - ``` - group_editor: { - groupId: null, - isSubmitting: false, - isChanged: false, - title: '', - description: '', - coverImage: null - } - ``` - -- `sidebar` - - Sample: - ``` - sidebar: {} - ``` - -- `patron` - Data related to [soapbox-patron](https://gitlab.com/soapbox-pub/soapbox-patron) - - Sample: - ``` - patron: {} - ``` - -- `soapbox` - Soapbox specific configuration pulled from `/instance/soapbox.json`. The configuration file isn't required and this map can be empty. - - Sample: - ``` - soapbox: { - logo: 'https://support.wirelessmessaging.com/temp/tga/teci_social_logo.svg', - promoPanel: { - items: [ - { - icon: 'comment-o', - text: 'TECI blog', - url: 'https://www.teci.world/blog' - } - ] - }, - extensions: { - patron: false - } - } - ``` - -- `instance` - Instance data pulled from `/api/v1/instance` - - Sample: - ``` - instance: { - avatar_upload_limit: 2000000, - urls: { - streaming_api: 'wss://dev.teci.world' - }, - thumbnail: 'https://dev.teci.world/instance/thumbnail.jpeg', - uri: 'https://dev.teci.world', - background_upload_limit: 4000000, - banner_upload_limit: 4000000, - poll_limits: { - max_expiration: 31536000, - max_option_chars: 200, - max_options: 20, - min_expiration: 0 - }, - version: '2.7.2 (compatible; Pleroma 2.0.1)', - title: 'TECI Dev', - max_toot_chars: 5000, - registrations: true, - languages: [ - 'en' - ], - email: 'curtis.rock@gmail.com', - description: 'A Pleroma instance, an alternative fediverse server', - upload_limit: 16000000, - stats: { - domain_count: 161, - status_count: 1, - user_count: 5 - } - } - ``` - -- `me` - The account ID of the currently logged in user, 'null' if loading, and 'false' if no user is logged in. - - Sample: - ``` - me: '9to1NPyS98J8cdicRE' - ``` - -- `auth` - Data used for authentication - - Sample: - ``` - auth: { - app: { - vapid_key: 'BEm4LT3n_cxFsGIqI-iG-Uea0OXgnjTtQAa4sPhkguP2rCbFfqL6xHOzo-cS3j9G7kG9eQ3deIQdkXbvTwgcLAk', - token_type: 'Bearer', - client_secret: 'ZuCeHoYy43MGifOnZyjWn82Kuq1YkeVAlwlxqvnGR6Q', - redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', - created_at: 1587504650, - name: 'SoapboxFE_2020-04-21T21:30:45.889Z', - client_id: 'OyjobYI1RQcx3G6RIJ7brm2RmIy6M2hbme2oEwByjvI', - expires_in: 600, - scope: 'read write follow push admin', - refresh_token: 'TNFBq7Dp6ryLkUoHHbnUp3y5c-U6ya_c7DcSnfM86wo', - website: null, - id: '23', - access_token: 'aN65U4SXw2JjOeOyko1-w7KIxaJnOqtU-Z3izpdKqcg' - }, - user: { - access_token: 'UeWx_MgQckL993--BetNsJHcwxq1BVmtxc4qJtb-DM8', - created_at: 1588607387, - expires_in: 600, - me: 'https://dev.teci.world/users/curtis', - refresh_token: '2mbb3ZqZ9w8eeSiLRDC2SsQ86-UmVDrScmFXPx4opvw', - scope: 'read write follow push admin', - token_type: 'Bearer' - } - } - ``` -- `app` - Map containing the app used to make app requests such as register/login and its access token. - -- `user` - Map containing the access token of the logged in user. From 2f27d879cc43ee9ef17a0092ceea0f30bf76238a Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 12:12:50 -0500 Subject: [PATCH 6/7] Rewrite customization guide --- README.md | 25 ++++----- docs/customization.md | 116 ++++++------------------------------------ 2 files changed, 29 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 3afa9d04f..1027957d1 100644 --- a/README.md +++ b/README.md @@ -175,20 +175,21 @@ To contribute, see [Contributing to Soapbox](docs/contributing.md). # Customization -Soapbox supports customization of the user interface, to allow per instance branding and other features. Current customization features include: +Soapbox supports customization of the user interface, to allow per-instance branding and other features. +Some examples include: -* Instance name -* Site logo -* Favicon -* About page -* Terms of Service page -* Privacy Policy page -* Copyright Policy (DMCA) page -* Promo panel list items, e.g. blog site link -* Soapbox extensions, e.g. Patron module -* Default settings, e.g. default theme +- Instance name +- Site logo +- Favicon +- About page +- Terms of Service page +- Privacy Policy page +- Copyright Policy (DMCA) page +- Promo panel list items, e.g. blog site link +- Soapbox extensions, e.g. Patron module +- Default settings, e.g. default theme -Customization details can be found in the [Customization doc](docs/customization.md) +More details can be found in [Customizing Soapbox](docs/customization.md). # License & Credits diff --git a/docs/customization.md b/docs/customization.md index 9c0a31301..2b5b38276 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -1,110 +1,26 @@ # Customizing Soapbox -If you haven't already, [install Soapbox](../installing). But before you install soapbox, you should consider how Soapbox is installed, by default. +Soapbox uses your own site's name and branding throughout the interface. +This allows every Soapbox site to be different, and catered to a particular audience. +Unlike Mastodon, which uses the "Mastodon" branding on all instances, Soapbox does not refer to itself in the user interface. -Soapbox, by default, is installed to replace the default Pleroma front end. By extension, the Pleroma Masto front end continues to be available at the `/web` sub-URL, which you can reference, if you'd like, in the `promoPanel` section of `soapbox.json` +## Backend settings -There are two main places Soapbox gets its configuration: +The site's name and description are **configured in the backend itself.** +These are settings global to your website, and will also affect mobile apps and other frontends accessing your website. -- `/opt/pleroma/config/prod.secret.exs` +- On Mastodon, you can change it through the admin interface. +- On Pleroma, it can be edited through AdminFE, or by editing `config/prod.secret.exs` on the server. -- `/opt/pleroma/instance/static/instance/soapbox.json` +These settings are exposed through the API under GET `/api/v1/instance`. -Logos, branding, etc. take place in the `soapbox.json` file. -For example: +## Soapbox settings -```json -{ - "logo": "/instance/images/soapbox-logo.svg", - "brandColor": "#0482d8", - "promoPanel": { - "items": [{ - "icon": "area-chart", - "text": "Our Site stats", - "url": "https://fediverse.network/example.com" - }, { - "icon": "comment-o", - "text": "Our Site blog", - "url": "https://blog.example.com" - }] - }, - "extensions": { - "patron": false - }, - "defaultSettings": { - "autoPlayGif": false, - "themeMode": "light" - }, - "copyright": "♡2020. Copying is an act of love. Please copy and share.", - "customCss": [ - "/instance/static/your_file_here.css" - ], - "navlinks": { - "homeFooter": [ - { "title": "About", "url": "/about" }, - { "title": "Terms of Service", "url": "/about/tos" }, - { "title": "Privacy Policy", "url": "/about/privacy" }, - { "title": "DMCA", "url": "/about/dmca" }, - { "title": "Source Code", "url": "/about#opensource" } - ] - } -} -``` +Most settings are specific to your Soapbox installation and not the entire website. +That includes the logo, default theme, and more. -Customizable features include: +- On Pleroma, admins can edit these settings directly from Soapbox. Just click "Soapbox config" in the sidebar, or navigate directly to `/soapbox/config`. +- On Mastodon, admins need to upload a JSON file with the settings, and make it available at `https://yoursite.tld/instance/soapbox.json`. -* Instance name -* Site logo -* Promo panel list items, e.g. blog site link -* Favicon -* About pages -* Default user settings -* Cascadomg Style Sheets (CSS) - -## Instance Name -Instance name is edited during the Pleroma installation step or via AdminFE. - -## Instance Description -Instance description is edited during the Pleroma installation step or via AdminFE. - -## Captcha on Registration Page -Use of the Captcha feature on the registration page is configured during the Pleroma installation step or via AdminFE. - -## Site Logo, Brand Color, and Promo Panel List Items -The site logo, brand color, and promo panel list items are customized by copying `soapbox.example.json` in the `static/instance` folder to `soapbox.json` and editing that file. It is recommended that you test your edited soapbox.json file in a JSON validator, such as [JSONLint](https://jsonlint.com/), before using it. - -The icon names for the promo panel list items can be source from [Line Awesome](https://icons8.com/line-awesome). Note that you should hover over or click a selected icon to see what the icon's real name is, e.g. `world` - -The site logo, in SVG format, is rendered to be able to allow the site theme colors to appear in the less than 100% opaque sections of the logo. -The logo colors are rendered in a color that provides contrast for the site theme. - -The `navlinks` section of the `soapbox.json` file references the links that are displayed at the bottom of the Registration/Login, About, Terms of Service, Privacy Policy and Copyright Policy (DMCA) pages. - -The `brandColor` in `soapbox.json` refers to the main color upon which the look of soapbox-fe is defined. - -After editing your HTML files and folder names, save the file and refresh your browser. - -## Favicon -The favicon is customized by dropping a favicon.png file into the `/static` folder and refreshing your browser. - -## About Pages -Soapbox supports any number of custom HTML pages under `yoursite.com/about/:slug`. - -The finder will search `/opt/pleroma/instance/static/instance/about/:slug.html` to find your page. -Use the name `index.html` for the root page. - -Example templates are available for editing in the `static/instance/about.example` folder, such as: -* index.html -* tos.html -* privacy.html -* dmca.html - -Simply rename `about.example` to `about`, or create your own. - -The `soapbox.json` file navlinks section's default URL values are pointing to the above file location, when the `about.example` folder is renamed to `about` -These four template files have placeholders in them, e.g. "Your_Instance", that should be edited to match your Soapbox instance configuration, and will be meaningless to your users until you edit them. - -## Alternate Soapbox URL Root Location -If you want to install Soapbox at an alternate URL, allowing you to potentially run more than 2 front ends on a Pleroma server, you can consider deploying the Nginx config created by @a1batross, available [here](https://git.mentality.rip/a1batross/soapbox-nginx-config/src/branch/master/soapbox.nginx) - -Tech support is limited for this level of customization +If using Pleroma, these settings are exposed through the API under GET `/api/pleroma/frontend_configurations`. +Otherwise, the settings need to be uploaded manually and made available at GET `/instance/soapbox.json`. From 1f62b53da25e6fe55883674d143e03bf7261d6a8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 18 Jul 2022 12:16:11 -0500 Subject: [PATCH 7/7] Docs: update docs sections from README --- docs/development/how-it-works.md | 18 +++++++++++++++++- docs/development/live-backend.md | 20 -------------------- docs/development/running-locally.md | 12 +++++++++--- 3 files changed, 26 insertions(+), 24 deletions(-) delete mode 100644 docs/development/live-backend.md diff --git a/docs/development/how-it-works.md b/docs/development/how-it-works.md index d0fa66f01..e5c4c7bc4 100644 --- a/docs/development/how-it-works.md +++ b/docs/development/how-it-works.md @@ -5,4 +5,20 @@ Soapbox FE is a [single-page application (SPA)](https://en.wikipedia.org/wiki/Si It has a single HTML file, `index.html`, responsible only for loading the required JavaScript and CSS. It interacts with the backend through [XMLHttpRequest (XHR)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). -It incorporates much of the [Mastodon API](https://docs.joinmastodon.org/methods/) used by Pleroma and Mastodon, but requires many [Pleroma-specific features](https://docs-develop.pleroma.social/backend/API/differences_in_mastoapi_responses/) in order to function. +Here is a simplified example with Nginx: + +```nginx +location /api { + proxy_pass http://backend; +} + +location / { + root /opt/soapbox; + try_files $uri index.html; +} +``` + +(See [`mastodon.conf`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/installation/mastodon.conf) for a full example.) + +Soapbox incorporates much of the [Mastodon API](https://docs.joinmastodon.org/methods/), [Pleroma API](https://api.pleroma.social/), and more. +It detects features supported by the backend to provide the right experience for the backend. diff --git a/docs/development/live-backend.md b/docs/development/live-backend.md deleted file mode 100644 index 1857324db..000000000 --- a/docs/development/live-backend.md +++ /dev/null @@ -1,20 +0,0 @@ -# Developing against a live backend - -You can also run Soapbox FE locally with a live production server as the backend. - -> **Note:** Whether or not this works depends on your production server. It does not seem to work with Cloudflare or VanwaNet. - -To do so, just copy the env file: - -``` -cp .env.example .env -``` - -And edit `.env`, setting the configuration like this: - -``` -BACKEND_URL="https://pleroma.example.com" -PROXY_HTTPS_INSECURE=true -``` - -You will need to restart the local development server for the changes to take effect. diff --git a/docs/development/running-locally.md b/docs/development/running-locally.md index 8a8c655b2..d11c59396 100644 --- a/docs/development/running-locally.md +++ b/docs/development/running-locally.md @@ -23,16 +23,22 @@ yarn dev It will serve at `http://localhost:3036` by default. -It will proxy requests to the backend for you. -For Pleroma running on `localhost:4000` (the default) no other changes are required, just start a local Pleroma server and it should begin working. +You should see an input box - just enter the domain name of your instance to log in. + +Tip: you can even enter a local instance like `http://localhost:3000`! ## Troubleshooting: `ERROR: NODE_ENV must be set` Create a `.env` file if you haven't already. -``` +```sh cp .env.example .env ``` And ensure that it contains `NODE_ENV=development`. Try again. + +## Troubleshooting: it's not working! + +Run `node -V` and compare your Node.js version with the version in [`.tool-versions`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/.tool-versions). +If they don't match, try installing [asdf](https://asdf-vm.com/).