• Basic features

  • Isomorphic

  • ActivityPub

  • Build a personal blog that federates with Mastodon.

    • Search for lumen@lumenwrites.com on Mastodon.
    • See my profile and avatar. When someone clicks on my avatar, they are directed to my blog.
    • Subscribe to my posts.
    • PuSH updates in realtime into the home feed.

    Result:
    Users can subscribe to my posts on Mastodon.

  • Receiving likes/reshares/comments info.

    • Receive the comments, upvotes, and reblogs from Mastodon.
    • ++ Threaded comments
  • Sending likes/reshares/comments.

    • Follow me by clicking a button on my site(“Remote follow”).
    • Favorite, reblog, and comment by using buttons on my site.
    • Can reply to comments.
  • Home feed

    • Can subscribe to other blogs and see them in my home feed.
    • ++ Rankable
  • Nexy
    Nexy.io is a “federated” feed of all blogs, rankable, like reddit.

    • Discover blogs to federate with.
    • Fetch and receive all of the updates.
    • Filter/Rank.
    • ++ “Upvote” buttons work the same way as on blog/mastodon.

    Nexy is the reddit, but it’s not “centralized” — it is open source, anyone can launch their own instance, and discover all the blogs.

  • Hosting
    That would truly work like an email.

    • Nexy.io. Come in, get free address, like gmail. rayalez@nexy.io
      Or buy a domain — lumen@lumenwrites.io
    • At any point export your data, and redirect requests to new domain.
  • Monetize
    Hosting vertices— for your own domain or traffic or something.

  • OStatus

  • Small

  • Next up

  • After that:

    • I create a webfinger file for my site.
    • It redirects to the webfinger I have made for my user.
    • Which redirects to the stream of posts.

    In JSON - I know from commit

    Optional:

    Don’t understand:

  • Resources
    Activity streams implementation in python:
    https://github.com/w3c-social/activipy
    Activipy tutorial:
    http://activipy.readthedocs.io/en/latest/tutorial.html
    Python federation protocol:
    http://federation.readthedocs.io/en/latest/

  • We need to have ActivityStreams feeds for OStatus. Fortunately,
    ActivityStreams has default behaviour defined for plain-old RSS 2.0 and
    Atom feeds, so the feeds you have now are probably fine. Ideally you should have a
    single feed for each person. You should
    define an author element at the feed level. Author elements should always
    have a URI element that uniquely identifies the author. Your feed should
    be discoverable with a from the person’s HTML profile page.
    Optional: use Activity Streams. Enhancing your feeds with ActivityStreams
    data like a verb and object can make the information much richer. Adding

    elements with rel=”avatar” will make the user’s avatar available.
    Optional: use Portable Contacts. You can add Portable Contacts elements as
    extensions to the element. Important elements include

    , , , and .

  • PubSubHubbub (“PuSH”) makes real-time updates to
    feed subscribers possible. Your user feeds should be PuSH-enabled. This
    requires two steps: first, adding the declaration of a hub in the Atom or
    RSS 2.0 feed. Second, sending a new-content update to the hub when
    there’s new content.

  • Model remote users. This can be the trickiest part of implementing
    OStatus. You’ll need to allow for authors of comments, “favorites”, and
    so on to be people who don’t have accounts on your local system. One
    typical way to do this is to have a superclass, Author, with subclasses
    User and RemoteAuthor (or something similar). Be careful about modeling
    identifiers; typically usernames are unique for Users but not for
    RemoteAuthors. Another option is to model remote users as a user role
    with the absolute minimum permissions.

  • Accept Salmon for comments. OStatus servers will try to send a Salmon slap
    when a remote user comments on or replies to an activity by one of your
    users. Ideally, you should accept these Salmon messages, display them,
    and notify the user. Note that typical precautions about comment spam
    apply here.

  • Accept Salmon for social activities. OStatus servers will also send Salmon
    slaps containing ActivityStreams representations of social activities
    involving your users when those activities happen remotely. If you keep a
    record of “followers” for a user, the Follow verb can be useful. Also
    important are the Like (or “Fave”) and Share verbs. If you cache remote
    users’ profile data on your server, you should also handle the
    ProfileChange verb (custom for OStatus).

  • If your user replies to, or comments on, a remote activity, send a Salmon slap to the remote user. This will require
    discovering the remote user’s Salmon endpoint and posting a reply to it.

  • You can help remote users track
    popularity and reach by posting ActivityStreams representations of your
    users’ interactions with their feeds. The Follow verb helps them keep a
    list of followers. If you send the Follow verb, make sure to send
    ProfileUpdate activities so that the social graph on the remote user’s
    site stays in synch. Like and Share are also useful for remote users to
    track. Finally, the corresponding verbs (Unlike, Unshare, Unfollow) can
    help keep the state synchronized.

  • You can implement the more complex
    subscriber role in PuSH. Note that there’s a user-interface issue here;
    your users will have to tell you which remote user feeds they want to
    subscribe to. You should allow discovery using WebFinger and the
    “updates-from” relationship; also with a profile page, digging for the
    element that points to an Atom feed.
    Optional: implement OStatus subscribe link. Some OStatus systems (like
    StatusNet) let a browsing user provide a WebFinger identity to initiate
    subscription from the publisher’s Web interface. To make this work,
    you’ll need to implement the http://ostatus.org/schema/1.0/subscribe
    WebFinger relationship (described in the OStatus protocol documents).
    Optional: extract Portable Contacts profile information. You can get
    richer representations of remote users’ profiles by extracting the
    Portable Contacts data from the elements in feeds. You can also
    watch for profile update activities to come through the PuSH-enabled
    feed.

{"cards":[{"_id":"79695a8380fbd568a000005a","treeId":"79278034780d23b2d0000043","seq":10385826,"position":0.5,"parentId":null,"content":"# Basic features"},{"_id":"79c10e909f8d5c32d2000063","treeId":"79278034780d23b2d0000043","seq":10096450,"position":2,"parentId":"79695a8380fbd568a000005a","content":"# Small\n\n- [ ] Protected endpoints.\n- [ ] Atom feed filters published posts.\n- [ ] Title and Meta config.\n- [ ] Proper createsuperuser with username/pass as arguments\n- [ ] Analytics config\n- [ ] Subscriber source\n- [ ] Write a readme tutorial"},{"_id":"79c119e89f8d5c32d20000dc","treeId":"79278034780d23b2d0000043","seq":10096439,"position":3,"parentId":"79695a8380fbd568a000005a","content":"- [ ] Auth and advanced react courses."},{"_id":"79695afb80fbd568a000005b","treeId":"79278034780d23b2d0000043","seq":10096441,"position":1,"parentId":"79c119e89f8d5c32d20000dc","content":"- [ ] Enjoy following the node courses\n[Udemy](https://www.udemy.com/the-complete-nodejs-developer-course-2/)\n[Pluralsight REST](https://app.pluralsight.com/library/courses/node-js-express-rest-web-services/table-of-contents)"},{"_id":"79695cdb80fbd568a000005c","treeId":"79278034780d23b2d0000043","seq":10096442,"position":2,"parentId":"79c119e89f8d5c32d20000dc","content":"- [ ] Follow Stephen's Auth course again, understand it completely this time."},{"_id":"79c110719f8d5c32d2000064","treeId":"79278034780d23b2d0000043","seq":10096418,"position":0.75,"parentId":null,"content":"# Isomorphic"},{"_id":"58f9b4e32fa9185e3557960c","treeId":"79278034780d23b2d0000043","seq":10763306,"position":1,"parentId":"79c110719f8d5c32d2000064","content":"# Next up\n- [X] Create ejx template that works. It will simply load bundle.js, that's easy to undertand.\n Just like usual html.\n- [X] Render react component to string, insert it. \n That'll just prerender react on server.\n- [X] Then Im sending the usual html generated with template+react\nAnd I'm GOOD with basic rendering."},{"_id":"58f9b4e32fa9185e3557960d","treeId":"79278034780d23b2d0000043","seq":10096347,"position":1,"parentId":"58f9b4e32fa9185e3557960c","content":"# Tutorials\n\nhttps://www.youtube.com/watch?v=GChdQSTSnpU"},{"_id":"58f9b4fc2fa9185e35579655","treeId":"79278034780d23b2d0000043","seq":10114210,"position":2,"parentId":"79c110719f8d5c32d2000064","content":"# After that:\n- [X] Figure out routing.\n- [X] Figure out redux.\n- [X] Figure out compiling bundle.server.js"},{"_id":"58f9b4fc2fa9185e35579656","treeId":"79278034780d23b2d0000043","seq":10096405,"position":1,"parentId":"58f9b4fc2fa9185e35579655","content":"# Tutorials\n\nhttps://medium.com/@liheyse/react-server-side-rendering-ssr-with-express-and-css-modules-722ef0cc8fa0\n\nhttps://medium.com/@justinjung04/react-server-side-rendering-and-hot-reloading-ffb87ca81a89\n\nhttp://redux.js.org/docs/recipes/ServerRendering.html"},{"_id":"58f9b4fc2fa9185e35579657","treeId":"79278034780d23b2d0000043","seq":10096406,"position":2,"parentId":"58f9b4fc2fa9185e35579655","content":"# Examples\n\nMost recent SSR implemented:\n\nhttps://github.com/Alex-ray/v2-universal-js-hmr-ssr-react-redux\n\nMERN:\n\nhttps://github.com/Hashnode/mern-starter"},{"_id":"79281829ad3279816000004d","treeId":"79278034780d23b2d0000043","seq":10096433,"position":0.875,"parentId":null,"content":"# ActivityPub"},{"_id":"79b019ed67e4e6786f000060","treeId":"79278034780d23b2d0000043","seq":10085155,"position":0.25,"parentId":"79281829ad3279816000004d","content":"- [X] Actor url, return inbox/outbox links\n- [X] Inbox. When people .post() to it it creates posts.\n- [X] Outbox. Just a list of activities."},{"_id":"79b10a2867e4e6786f000061","treeId":"79278034780d23b2d0000043","seq":10114215,"position":0.375,"parentId":"79281829ad3279816000004d","content":"- [X] Following. Have a /follow route, that people can POST to, and save them in the collection of followers.\n- [X] When I create a post, blast it to followers inboxes."},{"_id":"79b10a3167e4e6786f000062","treeId":"79278034780d23b2d0000043","seq":10085161,"position":1,"parentId":"79b10a2867e4e6786f000061","content":""},{"_id":"795f7f87adc68bc23f00005a","treeId":"79278034780d23b2d0000043","seq":10114243,"position":0.5,"parentId":"79281829ad3279816000004d","content":"- The inbox is determined by first retrieving the target actor's JSON-LD representation and then looking up the inbox property. (Webfinger)\n- An activity is delivered to actors(users) by first looking up the their inboxes and then posting the activity to those inboxes.\n- Many users may have a common publicInbox(hub). You post to it once, and it notifies all the users that follow it.\n"},{"_id":"7952a7793bbc4ad9d5000055","treeId":"79278034780d23b2d0000043","seq":10109444,"position":1,"parentId":"79281829ad3279816000004d","content":"**Resources**\nMastodon issue and todo list:\nhttps://github.com/tootsuite/mastodon/issues/1557\nEssay on:\nhttps://groups.google.com/forum/#!topic/ostatus-discuss/fxXfMW1sFNM\nCurrent implementations:\nhttps://www.w3.org/wiki/Socialwg/ActivityPub_network\nMastodon hashtag:\nhttps://mastodon.social/tags/activitypub\nDiaspora issue:\nhttps://github.com/diaspora/diaspora/issues/7422\nTest suite:\nhttps://activitypub.rocks/test/\n-/-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[]5"},{"_id":"7952d0c13bbc4ad9d5000058","treeId":"79278034780d23b2d0000043","seq":10114264,"position":1,"parentId":"7952a7793bbc4ad9d5000055","content":"- [ ] Object id properties\n (Section 3.2 Retrieving objects)\n- [ ] Actor inboxes\n- [ ] Actor outboxes\n- [ ] Actor Following collections\n- [ ] Actor Followers collections\n- [ ] Actor Likes collections\n\nOptional:\n- [ ] Media uploads\n\nDon't understand:\n- [ ] The special Public collection?\n- [ ] Server-to-server Activity side effects, like Undo side effects?\n- [ ] Properly support Actor simplified login naming? (Section 4)\n- [ ] Deliver activities properly?\n- [ ] Implement authentication and authorization checks for server-to-server interactions?\n- [ ] Scrub Activities for cross-site scripting attacks?\n- [ ] Linked Data Notifications RDF representations (very optional)? (Section 8.1 Delivery)\n"},{"_id":"79278087780d23b2d0000046","treeId":"79278034780d23b2d0000043","seq":10039529,"position":1,"parentId":null,"content":"**Build a personal blog that federates with Mastodon.**\n- Search for lumen@lumenwrites.com on Mastodon.\n- See my profile and avatar. When someone clicks on my avatar, they are directed to my blog.\n- Subscribe to my posts.\n- PuSH updates in realtime into the home feed.\n\nResult:\n**Users can subscribe to my posts on Mastodon**."},{"_id":"79278285780d23b2d0000047","treeId":"79278034780d23b2d0000043","seq":10039481,"position":1,"parentId":"79278087780d23b2d0000046","content":"- [ ] **WebFinger** to fetch my info\n- I create a webfinger file for my site.\n- It redirects to the webfinger I have made for my user.\n- Which redirects to the stream of posts.\n\nIn JSON - I know from commit"},{"_id":"58ea75872fa9185e354f9f3d","treeId":"79278034780d23b2d0000043","seq":10010492,"position":0.5,"parentId":"79278285780d23b2d0000047","content":"- [X] Deploy the non-decentralized version."},{"_id":"792796c4780d23b2d000004d","treeId":"79278034780d23b2d0000043","seq":10010493,"position":1,"parentId":"79278285780d23b2d0000047","content":"- [X] Proxy the urls I need from nginx to django"},{"_id":"7927b9366c1d023e3e000045","treeId":"79278034780d23b2d0000043","seq":10010495,"position":1.5,"parentId":"79278285780d23b2d0000047","content":"- [X] Return simple hardcoded responses for host-meta and for one user\n"},{"_id":"79a3bbaf7444a7c23b000066","treeId":"79278034780d23b2d0000043","seq":10078840,"position":1.5625,"parentId":"79278285780d23b2d0000047","content":"- [ ] Figure out how to see ruby logs, so Mastodon would tell me what's wrong.\n- [ ] Look at the ruby code try to figure out what it does."},{"_id":"792797b9780d23b2d000004e","treeId":"79278034780d23b2d0000043","seq":10009130,"position":2,"parentId":"79278285780d23b2d0000047","content":"**Resources**\n\nSpec:\nhttps://tools.ietf.org/html/rfc7033\nTutorial:\nhttps://hueniverse.com/implementing-webfinger-fa94335311aa\nMy Medium notes:\nhttps://medium.com/p/eff6f8434c1a/edit"},{"_id":"7931a05c2b5edb4914000051","treeId":"79278034780d23b2d0000043","seq":10009165,"position":3,"parentId":"79278285780d23b2d0000047","content":"**Examples/Implementations**\nWebFinger client:\nhttps://github.com/jcarbaugh/python-webfinger\nDjango WebFinger server:\nhttps://github.com/jcarbaugh/django-webfinger\nWebFinger-unofficial:\nhttps://github.com/snarfed/webfinger-unofficial\nDiaspora WebFinger code:\nhttp://federation.readthedocs.io/en/latest/_modules/federation/hostmeta/generators.html"},{"_id":"7927834c780d23b2d0000048","treeId":"79278034780d23b2d0000043","seq":10039504,"position":2,"parentId":"79278087780d23b2d0000046","content":"- [ ] **ActivityStream** feed of posts"},{"_id":"793116a02b5edb4914000050","treeId":"79278034780d23b2d0000043","seq":10009364,"position":0.5,"parentId":"7927834c780d23b2d0000048","content":"**Resources**\nActivity streams implementation in python:\nhttps://github.com/w3c-social/activipy\nActivipy tutorial:\nhttp://activipy.readthedocs.io/en/latest/tutorial.html\nPython federation protocol:\nhttp://federation.readthedocs.io/en/latest/"},{"_id":"79279eb0780d23b2d000004f","treeId":"79278034780d23b2d0000043","seq":10008656,"position":1,"parentId":"7927834c780d23b2d0000048","content":"We need to have ActivityStreams feeds for OStatus. Fortunately,\nActivityStreams has default behaviour defined for plain-old RSS 2.0 and\nAtom feeds, so the feeds you have now are probably fine. Ideally you should have a\nsingle feed for each person. You should\ndefine an author element at the feed level. Author elements should always\nhave a URI element that uniquely identifies the author. Your feed should\nbe discoverable with a <link> from the person's HTML profile page.\nOptional: use Activity Streams. Enhancing your feeds with ActivityStreams\ndata like a verb and object can make the information much richer. Adding\n<link> elements with rel=”avatar” will make the user's avatar available.\nOptional: use Portable Contacts. You can add Portable Contacts elements as\nextensions to the <author> element. Important elements include\n<preferredUsername>, <displayName>, <note>, and <urls>."},{"_id":"79279587780d23b2d000004c","treeId":"79278034780d23b2d0000043","seq":10763299,"position":2.25,"parentId":"79278087780d23b2d0000046","content":"- [ ] **PuSH** to send in real time"},{"_id":"79279f66780d23b2d0000050","treeId":"79278034780d23b2d0000043","seq":10005426,"position":1,"parentId":"79279587780d23b2d000004c","content":" PubSubHubbub (“PuSH”) makes real-time updates to\nfeed subscribers possible. Your user feeds should be PuSH-enabled. This\nrequires two steps: first, adding the declaration of a hub in the Atom or\nRSS 2.0 feed. Second, sending a new-content update to the hub when\nthere's new content."},{"_id":"7927ef3c6c1d023e3e00004a","treeId":"79278034780d23b2d0000043","seq":10005808,"position":1.5,"parentId":null,"content":"**Receiving likes/reshares/comments info.**\n\n- Receive the comments, upvotes, and reblogs from Mastodon.\n- ++ Threaded comments"},{"_id":"7927955d780d23b2d000004b","treeId":"79278034780d23b2d0000043","seq":10763296,"position":1,"parentId":"7927ef3c6c1d023e3e00004a","content":"- [X] **Receive Salmon to receive upvotes**"},{"_id":"7927a3a4780d23b2d0000051","treeId":"79278034780d23b2d0000043","seq":10005443,"position":1,"parentId":"7927955d780d23b2d000004b","content":"Model remote users. This can be the trickiest part of implementing\nOStatus. You'll need to allow for authors of comments, “favorites”, and\nso on to be people who don't have accounts on your local system. One\ntypical way to do this is to have a superclass, Author, with subclasses\nUser and RemoteAuthor (or something similar). Be careful about modeling\nidentifiers; typically usernames are unique for Users but not for\nRemoteAuthors. Another option is to model remote users as a user role\nwith the absolute minimum permissions."},{"_id":"7927a434780d23b2d0000052","treeId":"79278034780d23b2d0000043","seq":10005449,"position":2,"parentId":"7927955d780d23b2d000004b","content":"**Accept Salmon for comments.** OStatus servers will try to send a Salmon slap\nwhen a remote user comments on or replies to an activity by one of your\nusers. Ideally, you should accept these Salmon messages, display them,\nand notify the user. Note that typical precautions about comment spam\napply here."},{"_id":"7927a8cf780d23b2d0000054","treeId":"79278034780d23b2d0000043","seq":10005450,"position":3,"parentId":"7927955d780d23b2d000004b","content":"**Accept Salmon for social activities. **OStatus servers will also send Salmon\nslaps containing ActivityStreams representations of social activities\ninvolving your users when those activities happen remotely. If you keep a\nrecord of “followers” for a user, the Follow verb can be useful. Also\nimportant are the Like (or “Fave”) and Share verbs. If you cache remote\nusers' profile data on your server, you should also handle the\nProfileChange verb (custom for OStatus)."},{"_id":"7927f6f16c1d023e3e00004b","treeId":"79278034780d23b2d0000043","seq":10114148,"position":1.75,"parentId":null,"content":"**Sending likes/reshares/comments.**\n- Follow me by clicking a button on my site(“Remote follow”).\n- Favorite, reblog, and comment by using buttons on my site.\n- Can reply to comments."},{"_id":"7927abc0780d23b2d000005a","treeId":"79278034780d23b2d0000043","seq":10763290,"position":1,"parentId":"7927f6f16c1d023e3e00004b","content":"- [X] **Send Salmon for comments.**"},{"_id":"7927abd2780d23b2d000005b","treeId":"79278034780d23b2d0000043","seq":10005870,"position":1,"parentId":"7927abc0780d23b2d000005a","content":"If your user replies to, or comments on, a remote activity, send a Salmon slap to the remote user. This will require\ndiscovering the remote user's Salmon endpoint and posting a reply to it."},{"_id":"7927ac98780d23b2d000005d","treeId":"79278034780d23b2d0000043","seq":10039510,"position":2,"parentId":"7927f6f16c1d023e3e00004b","content":"- [ ] **Send Salmon for likes/reblogs.**"},{"_id":"7927acc4780d23b2d000005e","treeId":"79278034780d23b2d0000043","seq":10005865,"position":1,"parentId":"7927ac98780d23b2d000005d","content":"You can help remote users track\npopularity and reach by posting ActivityStreams representations of your\nusers' interactions with their feeds. The Follow verb helps them keep a\nlist of followers. If you send the Follow verb, make sure to send\nProfileUpdate activities so that the social graph on the remote user's\nsite stays in synch. Like and Share are also useful for remote users to\ntrack. Finally, the corresponding verbs (Unlike, Unshare, Unfollow) can\nhelp keep the state synchronized."},{"_id":"7927fa666c1d023e3e00004c","treeId":"79278034780d23b2d0000043","seq":10114162,"position":1.875,"parentId":null,"content":"**Home feed**\n- Can subscribe to other blogs and see them in my home feed.\n- ++ Rankable"},{"_id":"7927aaac780d23b2d0000057","treeId":"79278034780d23b2d0000043","seq":10039527,"position":1,"parentId":"7927fa666c1d023e3e00004c","content":"- [ ] **PuSH hub that receives notifications.**\n- [ ] ActivityPub stream of likes?"},{"_id":"7927aad6780d23b2d0000058","treeId":"79278034780d23b2d0000043","seq":10005871,"position":1,"parentId":"7927aaac780d23b2d0000057","content":" You can implement the more complex\nsubscriber role in PuSH. Note that there's a user-interface issue here;\nyour users will have to tell you which remote user feeds they want to\nsubscribe to. You should allow discovery using WebFinger and the\n“updates-from” relationship; also with a profile page, digging for the\nelement that points to an Atom feed.\nOptional: implement OStatus subscribe link. Some OStatus systems (like\nStatusNet) let a browsing user provide a WebFinger identity to initiate\nsubscription from the publisher's Web interface. To make this work,\nyou'll need to implement the http://ostatus.org/schema/1.0/subscribe\nWebFinger relationship (described in the OStatus protocol documents).\nOptional: extract Portable Contacts profile information. You can get\nricher representations of remote users' profiles by extracting the\nPortable Contacts data from the <author> elements in feeds. You can also\nwatch for profile update activities to come through the PuSH-enabled\nfeed."},{"_id":"7927895f780d23b2d0000049","treeId":"79278034780d23b2d0000043","seq":10114167,"position":2,"parentId":null,"content":"**Nexy**\nNexy.io is a “federated” feed of all blogs, rankable, like reddit.\n\n- Discover blogs to federate with.\n- Fetch and receive all of the updates.\n- Filter/Rank.\n- ++ “Upvote” buttons work the same way as on blog/mastodon.\n\nNexy is the reddit, but it’s not “centralized” — it is open source, anyone can launch their own instance, and discover all the blogs."},{"_id":"7927fff76c1d023e3e00004d","treeId":"79278034780d23b2d0000043","seq":10005852,"position":2.5,"parentId":null,"content":"**Hosting**\nThat would truly work like an email.\n- Nexy.io. Come in, get free address, like gmail. rayalez@nexy.io \nOr buy a domain — lumen@lumenwrites.io\n- At any point export your data, and redirect requests to new domain."},{"_id":"792804f46c1d023e3e00004f","treeId":"79278034780d23b2d0000043","seq":10039497,"position":2.59375,"parentId":null,"content":"**Monetize** \nHosting vertices— for your own domain or traffic or something."},{"_id":"7952b2683bbc4ad9d5000056","treeId":"79278034780d23b2d0000043","seq":10039435,"position":2.6875,"parentId":null,"content":"**OStatus**"},{"_id":"7952b2a83bbc4ad9d5000057","treeId":"79278034780d23b2d0000043","seq":10039456,"position":1,"parentId":"7952b2683bbc4ad9d5000056","content":"Node ostatus!!\nhttps://github.com/eschnou/node-ostatus\npump.io\nhttps://github.com/pump-io/pump.io"},{"_id":"7931a3af2b5edb4914000053","treeId":"79278034780d23b2d0000043","seq":10039494,"position":2,"parentId":"7952b2683bbc4ad9d5000056","content":"**Implementations**\npy-ostatus\nhttps://github.com/cdent/py-ostatus/tree/master/ostatus\n\nostatus-unofficial\nhttps://github.com/snarfed/ostatus-unofficial"},{"_id":"79c112c19f8d5c32d20000da","treeId":"79278034780d23b2d0000043","seq":10385830,"position":2.9375,"parentId":null,"content":"<style>\n.card h1 {\n font-weight: bold;\n}\n</style>"}],"tree":{"_id":"79278034780d23b2d0000043","name":"Nexy","publicUrl":"nexy"}}