{"id":13394146,"url":"https://github.com/200ok-ch/organice","last_synced_at":"2026-01-07T17:28:10.900Z","repository":{"id":37406239,"uuid":"203938031","full_name":"200ok-ch/organice","owner":"200ok-ch","description":"An implementation of Org mode without the dependency of Emacs - built for mobile and desktop browsers","archived":false,"fork":false,"pushed_at":"2025-05-06T09:49:22.000Z","size":12101,"stargazers_count":2507,"open_issues_count":115,"forks_count":158,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-06T10:29:01.959Z","etag":null,"topics":["emacs","org-mode","productivity","progressive-web-app","project-management"],"latest_commit_sha":null,"homepage":"https://organice.200ok.ch/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/200ok-ch.png","metadata":{"files":{"readme":"README.org","changelog":"changelog.org","contributing":"CONTRIBUTING.org","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["200ok-ch"],"patreon":["200ok"]}},"created_at":"2019-08-23T06:30:56.000Z","updated_at":"2025-05-06T09:40:31.000Z","dependencies_parsed_at":"2024-12-05T02:02:43.316Z","dependency_job_id":"bad30dfb-e574-4d23-b9ca-bb982f4ce718","html_url":"https://github.com/200ok-ch/organice","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/200ok-ch%2Forganice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/200ok-ch%2Forganice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/200ok-ch%2Forganice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/200ok-ch%2Forganice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/200ok-ch","download_url":"https://codeload.github.com/200ok-ch/organice/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052692,"owners_count":22006716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["emacs","org-mode","productivity","progressive-web-app","project-management"],"created_at":"2024-07-30T17:01:10.455Z","updated_at":"2026-01-07T17:28:10.887Z","avatar_url":"https://github.com/200ok-ch.png","language":"JavaScript","funding_links":["https://github.com/sponsors/200ok-ch","https://patreon.com/[\"200ok\"]","https://www.patreon.com/200ok"],"categories":["JavaScript","HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"# -*- org-adapt-indentation: nil; fill-column: 70; -*-\n#+title: organice documentation\n\n#+html: \u003ch1 align=\"center\"\u003eorganice - /'ɔ:gənaɪz/\u003c/h1\u003e\n\n#+html: \u003cp align=\"center\"\u003e\u003cb\u003eorganice organizes Org files nicely!\u003c/b\u003e\u003c/p\u003e\n\n#+html: \u003cp align=\"center\"\u003e \u003cimg src=\"https://raw.githubusercontent.com/200ok-ch/organice/master/public/organice-small.png\"/\u003e \u003c/p\u003e\n\n* General\n  :PROPERTIES:\n  :CUSTOM_ID: general\n  :END:\n\n** Code\n\n# REPO_PLACEHOLDER\n\n# INFO: We're using inline =#+HTML= notation in favor of the much more\n# readable =#+BEGIN_EXPORT html= notation, because GitHub uses legacy\n# Org parsers and wouldn't render the latter. GitHub would render\n# the legacy notation =#+BEGIN_HTML= which will not be properly\n# exported from Emacs, because it's legacy. Hence the glorious\n# solution: Write all HTML in one line.\n\n#+HTML: \u003cp\u003e \u003ca href=\"https://app.circleci.com/pipelines/github/200ok-ch/organice\"\u003e \u003cimg src=\"https://badgen.net/circleci/github/200ok-ch/organice?label=circleci%20master\" /\u003e \u003c/a\u003e \u003ca href='#'\u003e \u003cimg src=\"https://uptimekuma.twohundredok.com/api/badge/15/uptime/720?label=30d\" /\u003e \u003c/a\u003e \u003ca href=\"https://matrix.to/#/#organice:matrix.org\"\u003e \u003cimg src=\"https://img.shields.io/matrix/organice:matrix.org?label=%23organice%3Amatrix.org\" /\u003e \u003c/a\u003e \u003c/p\u003e\n\n** Getting started\n:PROPERTIES:\n:CUSTOM_ID: getting_started\n:END:\n\nTo get you started, we have two kinds of documentation:\n\n1. [[https://organice.200ok.ch/sample][Interactive Tutorial]]\n2. [[https://organice.200ok.ch/documentation.html][Documentation (User manual and developer guide)]]\n\nThe [[https://organice.200ok.ch/sample][interactive tutorial]] allows users to explore and experiment with\nvarious org-mode functionalities directly within the application. It\nprovides hands-on examples of tasks, tables, timestamps, and (most)\nother features.\n\nOn the other hand, the [[https://organice.200ok.ch/documentation.html][documentation]] contains more comprehensive and\nformal documentation, including installation instructions, deployment\nguides, contribution guidelines, and technical details about the\nproject's architecture and development process. This file is aimed at\nboth users seeking in-depth information and developers interested in\ncontributing to the project.\n\n** Community chat\n\nCommunity chat:\n- #organice on IRC [[https://libera.chat/][Libera.Chat]]\n- [[https://matrix.to/#/#organice:matrix.org][#organice:matrix.org]] on Matrix\n\n\n** Sponsors\n\nCreating and maintaining organice is made possible by all the\nvolunteering [[https://github.com/200ok-ch/organice/graphs/contributors][contributors]] and [[https://github.com/sponsors/200ok-ch][sponsors]]. If you enjoy using organice,\nand want to sponsor the development of Free and Open Source software,\nyou can do so with [[https://github.com/sponsors/200ok-ch][Github Sponsors]] and [[https://www.patreon.com/200ok][Patreon]].🙏\n\n#+HTML: \u003cp align=\"center\"\u003e \u003ca href=\"https://github.com/mxparker\"\u003e \u003cimg src=\"https://github.com/mxparker.png\" width=\"50px\" alt=\"@mxparker\"/\u003e \u003c/a\u003e \u003ca href=\"https://github.com/nuts4nuts4nuts\"\u003e \u003cimg src=\"https://github.com/nuts4nuts4nuts.png\" width=\"50px\" alt=\"@nuts4nuts4nuts\"/\u003e\u003c/a\u003e \u003c/p\u003e\n\nAnd one *huge* anonymous sponsor.\n\n** What does this project do?\n   :PROPERTIES:\n   :CUSTOM_ID: what-does-this-project-do\n   :END:\n\norganice is an implementation of [[http://orgmode.org/][Org mode]] without the dependency of\n[[https://www.gnu.org/software/emacs/][Emacs]]. It is built for mobile and desktop browsers and syncs with\n[[https://www.dropbox.com/][Dropbox]], [[https://gitlab.com/][GitLab]], and [[https://en.wikipedia.org/wiki/WebDAV][WebDAV]].\n\nAt [[https://200ok.ch/][200ok]], we run an instance of organice at https://organice.200ok.ch,\nwhich is open for anyone to use! organice does not have a back-end\n(it's just a front-end application, which uses different back-end\nstorage providers). We don't store any kind of data on our servers -\nwe also don't use analytics on organice.200ok.ch.\n\n[[https://raw.githubusercontent.com/200ok-ch/organice/master/images/screenshot-overview.png]]\n\n** Why is this project useful\n\nEmacs is great, but it's desktop software. For users who want to\naccess or edit their Org mode files whilst on the go, organice is a\ngreat choice.\n\n** Introduction\n\nIf you prefer a video to some text, we've got you covered! For\n[[https://emacsconf.org/2019/][EmacsConf 2019]], we've created a 10 minute introductory video into the\nrationale and usability of organice.\n\n#+html: \u003cp align=\"center\"\u003e\u003ca href=\"https://www.youtube.com/watch?v=aQKc0hcFXCk\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/200ok-ch/organice/master/images/screenshot-introduction.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\n\nYou can watch it on:\n\n- [[https://www.youtube.com/watch?v=aQKc0hcFXCk][Youtube]]\n- [[https://media.emacsconf.org/2019/05.html][emacsconf.org]]\n\n* Installation\n  :PROPERTIES:\n  :CUSTOM_ID: installation\n  :END:\n\norganice is a web application. You can use it from any browser. On iOS\nand Android, you can install organice to your homescreen. When started\nfrom there, it will run in full-screen as a Progressive Web\nApplication (PWA) which will add offline capabilities (see chapters\n[[#progressive_web_app][progressive web app]] and [[#offline_support][offline support]]).\n\nTo install organice to the homescreen follow these platform specific\ninstructions:\n\n- *iOS:*\n\n  Open organice in Mobile Safari. Tap the \"share\" button and select\n  \"Add to Home Screen\".\n\n- *Android:*\n\n  The exact procedure may differ depending on your browser and Android\n  version.  If you discover improvements to the following procedure,\n  please [[https://organice.200ok.ch/documentation.html#contributing][let us know]]!\n\n  First open the organice web page in your mobile browser.\n\n  - On Chrome, tap the \"menu\" button (three vertically stacked dots)\n    and select \"Add to homescreen\".\n\n  - On Firefox, \"menu\" button (three vertically stacked dots)\n    and select \"Install\". If you don't have that option, you may have\n    one to tap the home icon with the plus sign inside it which\n    is immediately to the right of the URL in the address bar.\n\n  - Other browsers may have a similar procedure to one of these.\n\n  At this point, most browsers will present a popup banner with the\n  option to \"Add to homescreen\" or \"Install\".\n\nBy default, when you start organice, it will display your root file\ndirectory. If you prefer to display a specific Org file instead, you\ncan select it in the [[https://organice.200ok.ch/settings][file settings]].\n\n* Usage\n  :PROPERTIES:\n  :CUSTOM_ID: usage\n  :END:\n** Current restrictions/expectations of organice\n\n\"Current\" means we're working hard on removing the following\nrestrictions and expectations.\n\n- organice understands only a few in-buffer settings (see [[#in_buffer_settings][Supported\n  in-buffer configuration]])\n  - Other in-buffer settings are imported and re-exported but are not\n    editable with organice.\n- Other content before the first headline is imported and re-exported,\n  but invisible and currently not editable with organice.\n- After potential in-buffer settings, your Org file _has to_ begin\n  with a headline.\n\nApart from these restrictions, organice is very robust in reading and\nediting your Org file and not breaking any of it. We're having users\nwith 10'000 lines in their files including all kinds of native Org\nfunctionality - and even these files work just fine in organice!\n\nGenerally, when working with distributed Org files, we're recommending\nto put them under version control and to check for bugs and racing\nconditions between clients.\n\nPlease [[https://github.com/200ok-ch/organice/issues/new][file an issue]] if you find additional restrictions, expectations\nor bugs that you wouldn’t have expected.\n\n*** Background information\n    :PROPERTIES:\n    :CUSTOM_ID: background-information\n    :END:\n\norganice has [[https://github.com/200ok-ch/organice/blob/master/src/lib/parse_org.js][a custom parser]] for Org files. It works quite fine and\nhas unit tests to prove it. One of the quality goals for the parser is\nthat when it parses and re-exports an Org file, it should not change\nthe original file. Not seeing unrelated diffs is important for the\nproductivity of the user. It sounds trivial, but lots of alternative\nproducts do not live up to this expectation.\n\nWriting a parser for a complex syntax like Org mode in custom code is\nhard. Therefore, we are in the process of implementing a proper EBNF\nbased parser and a set of tests behind that. If you're interested,\nplease check it out: [[https://github.com/200ok-ch/org-parser]]\n\nThe strategy we're using with regard to the parser is this:\n\n- Keep improving the existing custom parser for new features and make\n  bug fixes as long as the new one isn't ready.\n- In parallel, work on the new one until there is feature parity\n  between both parsers.\n- When the new one is finished, integrate it into organice.\n\n** Progressive Web App\n   :PROPERTIES:\n   :CUSTOM_ID: progressive_web_app\n   :END:\n\norganice can run as a PWA (Progressive Web App) - see the\n[[#installation][installation instructions]] and does have offline\nsupport. From your home screen, organice will start up in full screen\nand it will use a [[https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API][Service Worker]] to cache the application. On a\ndesktop browser, the Service Worker will be used automatically. This\nis generally managed through the build process with Parcel and service\nworker configurations, enabling the following features:\n\n- All static assets are cached so that organice loads fast on\n  subsequent visits, regardless of network connectivity.\n- Updates are downloaded in the background.\n- organice works regardless of network state, even if offline.\n- On mobile devices, organice can be added directly to the user's home\n  screen, app icon and all.\n\nFollowing that, if you start modifying your Org file when offline,\norganice will recognize that you are offline and queue up the\nsynchronization until you are online again.\n\norganice also understands when it's local Org file is outdated\ncompared to the upstream file and will ask you what you want to do -\npull the one from the synchronization back-end, push the one from\norganice or cancel. This happens when you made changes to your file on\nat least two machines at the same time without synchronizing them in\nthe meantime. For this, we recommend putting your Org file under\nversion control which is the idiomatic solution for changing text\nbased files on multiple machines in parallel.\n\n** Offline Support\n   :PROPERTIES:\n   :CUSTOM_ID: offline_support\n   :END:\n\nAdditionally to the offline support provided through implementing\norganice as a [[#progressive_web_app][progressive web app]] (see above) organice has the\nfollowing offline capabilities:\n\n- Every file opened in organice will automatically be cached on your\n  device (through =localStorage=).\n- When visiting the file, again, it will immediately be loaded from\n  the local storage and then loaded from the remote back-end.\n- That makes loading and switching between files instant _and_ gives\n  you the ability to work on multiple files when being offline.\n\n** Multi file support\n   :PROPERTIES:\n   :CUSTOM_ID: multi_file_support\n   :END:\n\nAgenda, Search, Task List, Refile and Capture Templates have the\nability to work on multiple files. You can adjust the behavior for\nthese on a file per file basis by creating \"file settings\" in the\nsettings menu. Multi file support works well with the offline\ncapabilities documented in [[#progressive_web_app][progressive web app]] and [[#offline_support][offline support]].\n\n* Customization\n  :PROPERTIES:\n  :CUSTOM_ID: customization\n  :END:\n\n** General\n\nSince organice implements Org mode, one might wonder if we plan to\nduplicate the Emacs configuration strategy. In Emacs Org mode, there's\nmore than [[https://orgmode.org/worg/org-tutorials/org-customize.html][650 variables for customization]] - and on top of that,\nthere's often two ways to configure things:\n\n1. Using elisp\n2. Using [[https://orgmode.org/manual/In_002dbuffer-settings.html][in-buffer settings]]\n\nModifying Org behavior using elisp (variables) is certainly mighty and\npowerful. However, the goal of organice is not to clone Emacs in full.\nIn fact, it could be argued that this is not possible. Emacs being a\nLISP machine has inherent power that cannot be brought to a web\napplication. Instead, the goal is to make Org mode accessible on\nsmartphones and for non-Emacs users. For both use-cases, elisp\nvariable configuration is not an idiomatic or ergonomic option.\n\norganice implements this customization strategy:\n\n- Use in-buffer settings where appropriate\n- Build custom and mobile friendly user interfaces where appropriate\n  - For example [[#capture_templates][capture templates]]\n\n** Supported in-buffer configuration\n   :PROPERTIES:\n   :CUSTOM_ID: in_buffer_settings\n   :END:\n\n*** In-buffer settings\n\n- =#+TODO=\n- =#+TYP_TODO=\n- =#+SEQ_TODO=\n\n*** =#+STARTUP:= options\n\n- =nologrepeat=: Do not record when reinstating repeating item\n\n*** Drawer properties\n    :PROPERTIES:\n    :END:\n\n- =logrepeat= and =nologrepeat=: Whether to record when reinstating repeating item\n\n#+BEGIN_EXAMPLE\n   :PROPERTIES:\n   :LOGGING:  logrepeat\n   :END:\n#+END_EXAMPLE\n\n\n** Themes / Color scheme / Dark Mode / Light Mode\n   :PROPERTIES:\n   :CUSTOM_ID: themes\n   :END:\n\norganice bundles several popular color themes, each in =light mode=\nand =dark mode=.\n\nIf you've set up a color scheme preference in your operating system,\norganice will honor this preference. It uses the\n=prefers-color-scheme= media query for this. Here, you can see if your\nbrowser supports this media query: https://caniuse.com/?search=prefers-color-scheme\n\nIf you change your color scheme preference directly within organice,\nthis naturally overrides your operating system preference. The color\nschemes in organice are implemented in a strategy pattern, so that\nadding new themes is quite easy.\n\nThese themes come bundled with organice:\n\n*** Solarized\n\n#+html: \u003cp align=\"center\"\u003e\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/solarized_light.png\"/\u003e\n#+html: \u0026nbsp;\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/solarized_dark.png\"/\u003e\n#+html: \u003c/p\u003e\n\n*** One\n\n#+html: \u003cp align=\"center\"\u003e\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/one_light.png\"/\u003e\n#+html: \u0026nbsp;\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/one_dark.png\"/\u003e\n#+html: \u003c/p\u003e\n\n*** Gruvbox\n#+html: \u003cp align=\"center\"\u003e\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/gruvbox_light.png\"/\u003e\n#+html: \u0026nbsp;\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/gruvbox_dark.png\"/\u003e\n#+html: \u003c/p\u003e\n\n*** Smyck\n#+html: \u003cp align=\"center\"\u003e\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/smyck_light.png\"/\u003e\n#+html: \u0026nbsp;\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/smyck_dark.png\"/\u003e\n#+html: \u003c/p\u003e\n\n*** Code\n#+html: \u003cp align=\"center\"\u003e\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/one_light.png\"/\u003e\n#+html: \u0026nbsp;\n#+html: \u003cimg style=\"height: 30em;\"src=\"https://github.com/200ok-ch/organice/wiki/images/themes/one_dark.png\"/\u003e\n#+html: \u003c/p\u003e\n\n** Other customizations\n\nFor some customizations, organice exposes a mobile friendly user\ninterface. Please find them in the 'settings' view (cogs icon in the\nheader on the right).\n\n[[https://raw.githubusercontent.com/200ok-ch/organice/master/images/screenshot-settings.png]]\n\n* Development\n  :PROPERTIES:\n  :CUSTOM_ID: development\n  :END:\n\norganice is built with [[https://reactjs.org/][React]] and [[https://redux.js.org/][Redux]]. It was bootstrapped with\n[[https://parceljs.org/][Parcel]] as its build tool. The tests are written with [[https://testing-library.com/docs/react-testing-library/intro][React Testing Library]].\nThe internal data structures are written as immutable persistent\ndata collections with the [[https://github.com/immutable-js/immutable-js][Immutable]] library.\n\n** Prerequisites\n\nYou will need a version of the Node.js engine installed which fulfills\nthe requirement stated in =package.json=. If you don't already have\nthis installed, it is recommended to install it via [[https://github.com/nvm-sh/nvm][nvm]]. The organice\nrepository already contains an =.nvmrc= file, so once you have nvm\ninstalled, the following commands should be sufficient:\n\n#+BEGIN_SRC shell\nnvm install\nnvm use\n#+END_SRC\n\nIf you have the [[https://nixos.org/][Nix package manager]] installed, just type:\n\n: nix develop\n\n** Setup\n\n*** Installation of packages\n\nTo install the necessary packages, run:\n\n#+BEGIN_SRC shell\nyarn install --production=false\n#+END_SRC\n\n*** Setup any of the synchronization back-ends\n\norganice can sync your Org files using Dropbox, GitLab, and WebDAV as\nback-ends.\n\nIf you want to develop a feature that needs synchronization, then you\nwill have to set up any of those options. If you want to work on a\nfeature that does not need synchronization, you can skip this step.\n\n**** WebDAV\n\norganice has support for WebDAV and ships with a Docker container with\na WebDAV server based on Apache. You can make use of that and use this\nWebDAV back-end for local development.\n\nHaving said that, if you're a Dropbox user, then it's convenient to have a\nworking setup for it if you want to test on files that are already in\nthose back-ends. But it doesn't have to be a barrier, just to get\nstarted. And maybe you don't want to host your files with either of\nthem anyway and use WebDAV all the way.\n\nIn any case, [[https://organice.200ok.ch/documentation.html#faq_webdav][here's how to get running locally with a WebDAV setup]].\n\n**** Dropbox or GitLab\n\nTo test against your own Dropbox or GitLab application, you'll need to create a\n~.env~ file by copying [[https://github.com/200ok-ch/organice/blob/master/.env.sample][.env.sample]] to just ~.env~.\n\n#+BEGIN_SRC shell\ncp .env.sample .env\n#+END_SRC\n\nThen, fill in the blanks in ~.env~ with your Dropbox or GitLab\ncredentials. More information about that is in the section\n[[https://organice.200ok.ch/documentation.html#synchronization_back_ends][Synchronization back-ends]].\n\n*** Running the application\n\n#+BEGIN_SRC shell\nyarn start\n#+END_SRC\n\n*** Running the tests:\n\n#+BEGIN_SRC shell\nyarn test\n#+END_SRC\n\n*** Search\n:PROPERTIES:\n:CUSTOM_ID: search_grammar\n:END:\n\nFor searching the Org file, there's a [[https://github.com/200ok-ch/organice/blob/master/src/lib/headline_filter_parser.grammar.pegjs][grammar]] for the search\nclause. It's written in [[https://pegjs.org/][pegjs]]. Generating the parser code happens\nautomatically on =yarn start|build|test=. When working on the parser,\nyou can manually generate it with:\n\n#+BEGIN_SRC shell\n./bin/compile_search_parser.sh\n#+END_SRC\n\n** Testing\n\nWhen you're developing a new feature and you want to manually test it,\nit's best to check it out in a Desktop browser and on your smartphone.\nThis is how you do that:\n\n*** Desktop\n\nRun the application with =yarn start= which will open organice in your\nconfigured default browser. Alternatively, visit\n=http://localhost:3000= in the browser of your choice.\n\n*** Smartphone\n\nThere are multiple options on how you can connect from your smartphone\nto your computer running organice.\n\nWhen running organice with =yarn start=, it will show you all the IPs\nthat the application server is bound to. One will be local to your\ncomputer, one will be on your network (if you're connected to a LAN or\nWifi, that is).\n\nIf your smartphone has access to the same network, you can access it\nwith the given IP address and port number.\n\nIf your new feature doesn't require a synchronization back-end, just\nopen the =sample.org= file which doesn't require a login. You're good\nto go.\n\n*Synchronizing with Dropbox or GitLab*\n\nIf your new feature does require the Dropbox or GitLab synchronization\nback-end, there's an extra step you need to perform.\n\nBoth Dropbox and GitLab require a whitelist of domains that they\ncan be synchronized from. The whitelist for local domains is\nexclusively short: =http://localhost:3000=.\n\nHence, to be able to login from your phone to your dev instance of\norganice, you'll need to set up [[https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding][port forwarding]]. If you have a shell\non your phone and an ssh client, you can do that with the following\ncommand:\n\n#+BEGIN_SRC shell\nssh -L 3000:localhost:3000 user-dev-machine\n#+END_SRC\n\nIf you don't have a shell on your phone, you can use a dedicated SSH\napplication (like [[https://www.termius.com/][Termius]]).\n\n** Debugging Tests\n\nApart from the popular choice of =console.log=-debugging, it's easy to\nuse Chrome or Chromium for debugging tests.\n\nPlace a =debugger;= statement in any test, then run:\n\n#+begin_src shell\nyarn test:dbg\n#+end_src\n\nThis will start running your Jest tests, but pause before executing to\nallow a debugger to attach to the process.\n\nOpen the following in Chrome:\n\n#+begin_example\nabout:inspect\n#+end_example\n\nAfter opening that link, the Chrome Developer Tools will be displayed.\nSelect inspect on your process and a breakpoint will be set at the\nfirst line of the test script (this is done to give you time to open the\ndeveloper tools and to prevent Jest from executing before you have time\nto do so). Click the button that looks like a \"play\" button in the\nupper right hand side of the screen to continue execution. When\nJest executes the test that contains the debugger statement, execution\nwill pause and you can examine the current scope and call stack.\n\nFor more details on test configuration after migrating from Create React App,\nsee the Parcel migration guide:\nhttps://parceljs.org/migration/cra/#6.-migrate-tests\n\n** Automatic deployments of reference instance\n\nThe productive reference instance of organice is deployed to\nhttps://organice.200ok.ch/. On merging a pull request to =master=,\ncode and documentation are automatically deployed to production.\n\nFor more complicated features (aka epics) that require more than one\npull request, there is a reference stage instance on\n[[https://staging.organice.200ok.ch/]]. When working on epics, we follow\nthe popular [[https://nvie.com/posts/a-successful-git-branching-model/][nvie git branching model]] in that we successively create\nfeature branches against =develop= until the epic is finished. On\nmerging a pull request to =develop=, code and documentation are\nautomatically deployed to stage.\n\n** Contributions\n\nPlease see our [[https://github.com/200ok-ch/organice/blob/master/CONTRIBUTING.org][contributor guidelines]] and our [[https://github.com/200ok-ch/organice/blob/master/CODE_OF_CONDUCT.md][code of conduct]].\n\n** Mockups\n   :PROPERTIES:\n   :CUSTOM_ID: mockups\n   :END:\n\nWhen discussing new UX, it is often helpful to add a mockup to the\ndiscussion to ensure that everyone is on the same page. When a new\ncontributor suggests a UX change and it's not trivial, we will ask to\ninclude a mockup to the issue.\n\nOf course, you're completely free to create such a mockup with\nwhatever tool you feel comfortable with. A scan of a pen and paper\nwill do, using [[https://inkscape.org/][Inkscape]] or Illustrator is nice and so on. If you don't\nhave a personal preference, and want to get going quickly, you can use\nthe mockup included in this repository. Find the file\n/[[https://github.com/200ok-ch/organice/blob/master/doc/mockups/organice-mockup.excalidraw][doc/mockups/organice-mockup.excalidraw]] and upload it to the open\nsource sketching tool [[https://excalidraw.com/][excalidraw.com]]. There, make any changes you\nlike, and export the result as either .png or .excalidraw and attach\nit to the original issue.\n\nNB: The .excalidraw file can also be opened by any SVG capable tool\nlike [[https://inkscape.org/][Inkscape]].\n\n* Deployment\n  :PROPERTIES:\n  :CUSTOM_ID: deployment\n  :END:\n\nSince organice is a front-end only application, it can easily be\ndeployed to any server capable of serving a static application.\n\nPlease note: If you want the hosted application to connect to Dropbox,\nGitLab or WebDAV, please read the section on [[https://organice.200ok.ch/documentation.html#synchronization_back_ends][Synchronization\nback-ends]].\n\n** FTP\n\nFirst create the production build locally: =yarn run build=\nNote: Creating a build will actually make your =REACT_APP_*= variables\nfrom the =.env= file available under =process.env= even though it'll\nbe a front-end application.\n\nAnd then upload to your web-server. Here's a sample script for your\nconvenience:\n\n#+BEGIN_SRC shell\nHOST='your_ftp_server_host'\nUSER='ftp_user'\nPASSWD='ftp_password'\n\nlftp $HOST \u003c\u003cEND_SCRIPT\nuser $USER $PASSWD\nmirror -R build/\nquit\nEND_SCRIPT\nexit 0\n#+END_SRC\n\nThe reference instance (https://organice.200ok.ch), for example, is\ndeployed via FTP. The full build script is in\n[[https://github.com/200ok-ch/organice/blob/master/bin/compile_and_upload.sh][bin/compile\\_and\\_upload.sh]].\n\n** Docker\n   :PROPERTIES:\n   :CUSTOM_ID: docker\n   :END:\n\norganice is also available as a Docker image.\n\nThe docker image recognizes a couple of environment variables. For\nexample =REACT_APP_WEBDAV_URL= prefills the URL field in the WebDAV\nsignin form. See [[https://github.com/200ok-ch/organice/blob/master/docker-compose.yml][docker-compose.yml]] for an example how to use it.\n\nA full list of such environment variables can be found in [[https://github.com/200ok-ch/organice/blob/master/.env.sample][.env.sample]].\nThe prefix =REACT_APP_= has to be replaced with =ORGANICE_=. The\nnaming should be pretty self explanatory.\n\n*** With =docker-compose=\n\nOrganice provides a unified =docker-compose.yml= file that supports both production and development environments using profiles.\n\n**** Production\n\nTo download and run the latest production-ready image (or build it locally if not available). This uses the =organice= service defined in the =docker-compose.yml= file:\n\n#+BEGIN_SRC shell\ndocker compose --profile prod up -d organice\n#+END_SRC\n\nThe webserver will be listening on port 5000 by default: http://localhost:5000\n\nTo build the production image yourself and run it:\n#+BEGIN_SRC shell\ndocker compose --profile prod build organice\ndocker compose --profile prod up -d organice\n#+END_SRC\n\nThe production image is optimized for size and contains only the necessary files to run organice.\n\n**** Development\n\nTo set up a development environment with the source code mounted for hot-reloading. This uses the =organice-dev= service:\n\n#+BEGIN_SRC shell\ndocker compose --profile dev up -d organice-dev\n#+END_SRC\n\nThis starts a container running a bash shell (via =tail -f /dev/null= to keep it alive). You can then execute commands inside it:\n\n#+BEGIN_SRC shell\n# Start the development server (Parcel)\ndocker compose --profile dev exec organice-dev yarn start\n\n# Run tests\ndocker compose --profile dev exec organice-dev yarn test\n\n# Open an interactive shell in the container\ndocker compose --profile dev exec organice-dev bash\n#+END_SRC\n\nThe development server is typically available on port 3000: http://localhost:3000. Note that the =organice-dev= service in =docker-compose.yml= maps port 3000 on your host to port 3000 in the container.\n\n*** Without docker-compose (Running Production Image)\n\nIf you prefer to run the production image directly without docker-compose (after pulling it from Docker Hub or building it locally using =docker build --target production -t twohundredok/organice:latest .=):\n\n#+BEGIN_SRC shell\ndocker run -p 5000:5000 --name organice twohundredok/organice:latest\n#+END_SRC\n\nAgain the webserver is listening on port 5000 and can be reached here:\nhttp://localhost:5000\n** Heroku\nAssuming, you have an account and have installed the [[https://devcenter.heroku.com/articles/heroku-cli][command line\ntools]], deployment is as easy as:\n\n#+BEGIN_SRC shell\nheroku create\nheroku config:set ON_HEROKU=1\ngit push heroku master\n#+END_SRC\n\n** Synchronization back-ends\n   :PROPERTIES:\n   :CUSTOM_ID: synchronization_back_ends\n   :END:\n\n*** Dropbox\n    :PROPERTIES:\n    :CUSTOM_ID: dropbox\n    :END:\n\nTo configure your own instance of organice for Dropbox, please go [[https://www.dropbox.com/developers/apps/][to\nthe Dropbox developer console]], create a new app and configure the\nresulting =clientId= in a newly created ~.env~ file (analogous to\n~.env.sample~) as the value of the key =REACT_APP_DROPBOX_CLIENT_ID=.\n\nMake sure to add your own host URL (or ~http://localhost:3000/~ for local development) as =Redirect URI=.\nYour dropbox app needs permission to read and write files.\n\n*** WebDAV\n    :PROPERTIES:\n    :CUSTOM_ID: webdav\n    :END:\n\n**** General\n\nWith WebDAV support, organice can potentially be used with a multitude\nof synchronization back-ends: Client/Server services [[https://doc.owncloud.com/server/user_manual/files/access_webdav.html][ownCloud]],\n[[https://docs.nextcloud.com/server/latest/user_manual/en/files/access_webdav.html][Nextcloud]] and [[https://manual.seafile.com/extension/webdav/][Seafile]], but also self hosted dedicated WebDAV servers\nlike [[https://httpd.apache.org/docs/2.4/mod/mod_dav.html][Apache]] or [[https://nginx.org/en/docs/http/ngx_http_dav_module.html][Nginx]].\n\n**** More information\n\nIn the [[https://organice.200ok.ch/documentation.html#faq_webdav][WebDAV FAQ]], you'll find lots more information regarding WebDAV:\n\n  - A screencast of how organice works when logging in to a WebDAV\n    server\n  - Documentation how on to setup your own WebDAV Server with Apache2\n    on Debian\n  - Documentation how to configure Nextcloud behind haproxy to allow\n    WebDAV\n  - Documentation on Nextcloud sharing\n\n*** GitLab\n    :PROPERTIES:\n    :CUSTOM_ID: gitlab\n    :END:\n\nTo configure your own instance of organice for GitLab, please create\nan OAuth application by going to [[https://gitlab.com/-/profile/applications][GitLab's application settings for\nyour profile]] and filling out the form with the following details:\n\n- Name: \"organice test\" (or whatever you prefer)\n- Redirect URI: ~http://localhost:3000/~ for local development, or\n  whatever domain you are hosting it with.\n- Confidential: /uncheck/ this\n- Expire access tokens: leave checked\n- Scopes: =api= only\n\nOnce filled out, click \"save application\" and keep this page open.\nThen, create a new ~.env~ file (analogous to ~.env.sample~) and set\nthe following variables:\n\n- =REACT_APP_GITLAB_CLIENT_ID=: The value that GitLab provides for\n  =Application ID=\n- =REACT_APP_GITLAB_SECRET=: The value that GitLab provides for =Secret=.\n\nYou may also refer to [[https://docs.gitlab.com/ee/integration/oauth_provider.html#user-owned-applications][GitLab's documentation]] for more information\nregarding OAuth applications, if interested.\n\n*** Encryption\n    :PROPERTIES:\n    :CUSTOM_ID: encryption\n    :END:\n\nIf you do not trust your data with third parties like Dropbox, you are\nfree to use Gitlab ([[https://about.gitlab.com/solutions/open-source/][which is open-source]]) or host your own [[https://organice.200ok.ch/documentation.html#webdav][WebDAV]]\nserver and take any number of precautionary measures.\n\nFor example, you can encrypt your data on disk. organice itself is\njust a front-end application, requires no server and has no tracking\nsystem. Therefore, the data within any organice instance (self hosted\nor not) is already only accessible to you, your browser and the\nnetwork between your browser and your chosen back-end. Therefore, if you\nhave a strong SSL certificate configured on your WebDAV server and\norganice instance, then organice will communicate securely via HTTPS\nto your server where your data is as secure as you make it. Then, your\ndata will be encrypted and inaccessible to any third party.\n\nOf course, security is hard. So the above statement is not a\nguarantee, but a guideline. You're responsible to ensure that the\ntechnologies employed (HTTPS, SSL, WebDAV, Browser, etc) are up to\ndate and secure.\n\n** Routing\n   :PROPERTIES:\n   :CUSTOM_ID: routing\n   :END:\n\nWhilst organice is a true [[https://developer.mozilla.org/en-US/docs/Glossary/SPA][Single Page Application]] (SPA) and therefore\nhas no back-end whatsoever, this does have an implication for\ndeployment with regard to routing. For routes like =example.com/foo=\nto work, we need a little something extra. Within the context of a\nrunning SPA, =/foo= would be matched by the React Router and the\nproper page would be rendered by JavaScript. When initially requesting\na route like that from the web server itself, the SPA is not running\nyet and the web server itself wouldn't find a file called =/foo=. It\nwould return a 404. The whole topic is explained in depth in this SO\nanswer: https://stackoverflow.com/a/36623117\n\nFor https://organice.200ok.ch we've opted to:\n\n- Use the modern HTML5 history API with [[https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/BrowserRouter.md][BrowserRouter]]\n- Not configure a back-end for isomorphic routing, because it would\n  complicate application and deployment unnecessarily (SEO is a\n  non-issue for organice)\n- Use good old [[https://httpd.apache.org/][Apache Webserver]] for hosting the compiled static assets\n\nTherefore configuring a catchall is as easy as setting up a\n=.htaccess= file in the root of the organice folder containing:\n\n#+BEGIN_EXAMPLE\nRewriteEngine On\nRewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]\nRewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d\nRewriteRule ^ - [L]\n\nRewriteRule ^ /index.html [L]\n#+END_EXAMPLE\n\nN.B.: If you're using WebDAV as a sync back-end, and the =RewriteRule= is\nallowed to apply to a WebDAV directory, it will break PUT requests to\nupload new files! [[https://organice.200ok.ch/documentation.html#webdav_apache_rewrite_engine][Here's documentation]] on how to configure both\nfeatures together correctly.\n\n* Contrib\n  :PROPERTIES:\n  :CUSTOM_ID: contrib\n  :END:\n\norganice aims to follow the 'batteries included' philosophy. For\nexample, the documentation is rather extensive and includes wider\ntopics than just its own functionality - for example it includes\ndocumentation on various tested [[https://organice.200ok.ch/documentation.html#deployment][deployment strategies]].\n\nHowever, the community regularly comes up with a whole range of\noptions on how to use organice more effectively for specific\nuse-cases. Sometimes, these options are generic enough so that the\nmaintainers take the functionality into core. Sometimes, it's not that\nwell suited to be added into core, but still is potentially very well\nsuited to a wider range of users. For that, organice follows the\n=contrib= model which many bigger projects use (i.e. [[https://orgmode.org/worg/org-contrib/][Org mode]]) for\nsuch contributions.\n\nPlease see the [[https://github.com/200ok-ch/organice/tree/master/contrib][contrib folder]] for details.\n\n* Capture templates\n  :PROPERTIES:\n  :CUSTOM_ID: capture_templates\n  :END:\n\norganice supports capture templates by implementing a flexible\nmechanism using URL parameters. These three of the following\nparameters are required and must be URL encoded:\n\n- ~captureTemplateName~: the name of the capture template to use. This\n  capture template must already exist in Settings \u003e Capture templates.\n- ~captureFile~: the =path= for Dropbox\n  of the file in which to execute the capture template.\n- ~captureContent~: the content you'd like to capture. This content\n  will be placed at the cursor position if specified in the capture\n  template (with ~%?~), or at the end of the template if it's not\n  specified.\n\nYou can also specify additional custom variables for use in your\ntemplates. They should be in the format ~captureVariable_\u003cyour custom\nvariable\u003e~, and should also be URL encoded. In your capture template\nthey'd show up as ~%\u003cyour custom variable\u003e~.\n\norganice allows you to specify where the captured content will be\ninserted, via a \"header path\" which is a list of headers to match.  If\nthe list is empty, the content will be inserted at the end of the\nfile, or the beginning if the prepend option is selected.\n\n** Examples\n*** Simple: Capture a string\n\nSay, you want to capture thoughts/todos as they occur to you. You\nmight want to have a capture template to just get these things out of\nyour head.\n\nThis makes for a good \"Inbox\" capture template:\n\n*Capture Template*\n\n#+BEGIN_EXAMPLE\n  ,* TODO %?\n  %U\n#+END_EXAMPLE\n\n*Example URL*\n\nhttps://organice.200ok.ch?captureTemplateName=Inbox\u0026captureContent=Read+up+on+capture+templates\u0026captureFile=/org/things.org\n\n*Result*\n\n#+BEGIN_EXAMPLE\n  ,* TODO Read up on capture templates\n  [2019-09-08 Sun 20:54]\n#+END_EXAMPLE\n\n*** With custom variable\n    :PROPERTIES:\n    :CUSTOM_ID: media_capture\n    :END:\n\nIf you want to add web pages to a reading queue (with a title, a\ncapture date and a URL), this would be a good starting point:\n\n*Capture Template*\n\n#+BEGIN_EXAMPLE\n  ,* %?\n  %u\n\n  - URL: %mediaURL\n#+END_EXAMPLE\n\n*Example URL*\n\nhttps://organice.200ok.ch?captureTemplateName=Media\u0026captureContent=Play+Emacs+like+an+instrument\u0026captureFile=/org/media.org\u0026captureVariable_mediaURL=https://200ok.ch/posts/2018-04-27_Play_Emacs_like_an_Instrument.html\n\n*Result*\n\n#+BEGIN_EXAMPLE\n  ,* Play Emacs like an instrument\n  [2019-09-08 Sun]\n\n  - URL: https://200ok.ch/posts/2018-04-27_Play_Emacs_like_an_Instrument.html\n#+END_EXAMPLE\n\n* Bookmarklets\n  :PROPERTIES:\n  :CUSTOM_ID: bookmarklets\n  :END:\n\nSince organice is a web application, you can use the capture templates\nfeature to create bookmarklets, of course! For example, if you want a\nbookmarklet to add the current page (title, capture date and URL) to\nyour reading queue using [[#media_capture][this capture template]], all you need is a\nlittle bit of JavaScript:\n\n#+BEGIN_SRC javascript\n  javascript:(function() {\n    const {title} = document;\n    const url = `https://organice.200ok.ch?captureTemplateName=Media\u0026captureContent=${title}\u0026captureFile=/org/media.org\u0026captureVariable_mediaURL=${window.location.href}`;\n    window.open(url, \"_blank\");\n  })()\n#+END_SRC\n\n** Bookmarklets Demo\n\n*** iOS\n\nThis is what using a bookmarklet to capture a website looks like in iOS:\n\n[[https://github.com/200ok-ch/organice/wiki/videos/demo-bookmarklet-iOS.gif]]\n\n* Siri integration\n  :PROPERTIES:\n  :CUSTOM_ID: siri_integration\n  :END:\n\nThe organice capture mechanism integrates very nicely with the\n[[https://support.apple.com/guide/shortcuts/welcome/ios][Siri\nShortcuts]] feature in iOS, allowing you to use Siri to execute\ncapture templates.\n\nYou can use [[https://www.icloud.com/shortcuts/14f91f8cf8f547a183a0734396240984][this sample Shortcut]] to get started with this right away\nin iOS 12 or newer. Open the link on your iOS device and click \"Get\nShortcut\". Then open up the Shortcuts app and edit the template by\nfollowing the directions in the comments. Then [[https://support.apple.com/en-us/HT209055][record a Siri trigger]]\nand you're good to go!\n\n* Comparison\n  :PROPERTIES:\n  :CUSTOM_ID: comparison\n  :END:\n\n** Beorg\n\nBefore starting work on organice, [[https://github.com/munen/][@munen]] (the original maintainer)\nused Beorg and donated to it multiple times, because he was very happy\nto have a good option to access Org files on my phone with it.\n\nThe important differences to him were:\n\n- organice is FOSS which is very much in the spirit of Org whilst\n  Beorg is proprietary\n- organice is web based, so there is no lock-in to a specific device\n  or OS\n\n** org-web\n\norganice has a shared history with [[https://github.com/DanielDe/org-web][org-web]]. In fact, it is a friendly\nfork. organice differs from org-web in that:\n\n- organice is a community driven project. See our\n  - [[https://github.com/200ok-ch/organice/blob/master/CODE_OF_CONDUCT.md][Code of conduct]]\n  - [[https://github.com/200ok-ch/organice/blob/master/CONTRIBUTING.org][Contributing guidelines]]\n  - Community chat: #organice on IRC [[https://libera.chat/][Libera.Chat]], or [[https://matrix.to/#/!DfVpGxoYxpbfAhuimY:matrix.org?via=matrix.org\u0026via=ungleich.ch][#organice:matrix.org]] on Matrix\n    on Matrix\n\n- organice has the commitment of a Swiss company (200ok llc: https://200ok.ch/)\n  behind it to continually work on it.\n  - 200ok has a strong track record in fostering Free and Open Source\n    Software (https://200ok.ch/floss.html) and has co-organized\n    [[https://200ok.ch/tags/emacsconf.html][EmacsConf 2019]].\n  - That's also why organice is Free Software (with the strong\n    [[https://github.com/200ok-ch/organice/blob/master/LICENSE][AGPL-3.0]] license) whereas org-web is Open Source (with [[https://github.com/DanielDe/org-web/blob/master/LICENSE][The\n    Unlicense]]).\n  - The continuous effort yields a certain power over time. At the\n    time of writing this, organice has many times more commits (~2400\n    vs ~600) and contributors (36 vs. 9). Of course, quantity doesn't\n    trump quality. However, many of the new contributors brought\n    significant features and improvements, not just tiny patches.\n\n- organice initially focused on becoming bug free - for example on\n  parsing and exporting org files correctly.\n- organice continues to evolve independently with its own feature\n  set. For example, it has [[https://organice.200ok.ch/documentation.html#faq_webdav][WebDAV support]]. For a list of all user\n  visible changes, please see [[https://github.com/200ok-ch/organice/blob/master/changelog.org][the changelog]].\n- organice is a project with equal focus on mobile as desktop\n  browsers.\n- org-web [[https://github.com/DanielDe/org-web/issues/75][tracks users]] with Google Analytics. organice [[https://github.com/200ok-ch/organice/issues/41][does not]].\n- organice has great documentation:\n  https://organice.200ok.ch/documentation.html\n\n\n*** What's new?\n\nTo see how organice differs from org-web, please consult the [[https://github.com/200ok-ch/organice/blob/master/changelog.org][changelog]]\nwhich contains the user visible changes since forking.\n\n*** Acknowledgment\n\nWe are extraordinarily grateful to DanielDe, the original creator!\n\nWe forked the project, because we have different visions on how to go\nforward. He envisions a mobile only solution, we think it's great to\nhave organice be available to any browser to enable anyone on the go\nor any non-Emacs user easy access to Org files. Also, DanielDe thinks\nof org-web as [[https://github.com/DanielDe/org-web//issues/72][his pet project]] whereas organice has the full power of\n[[https://200ok.ch][200ok llc]] behind it whilst building a strong self-sufficient community\naround it.\n\nThank you for all, DanielDe!🙏\n\n* Attributions\n  :PROPERTIES:\n  :CUSTOM_ID: attributions\n  :END:\n\n** Logo\n\nIllustration credit: [[https://www.vecteezy.com/][Vecteezy.com]]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F200ok-ch%2Forganice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F200ok-ch%2Forganice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F200ok-ch%2Forganice/lists"}