Own Your Posts
Own Your Posts is not a feed client in the usual sense. It is an on-ramp: a Primal-facing migration tool and teaching page for creators who have public work on Instagram, TikTok, Twitter/X or RSS and need the first Nostr profile to feel less empty.
This is about the first scary step
The hardest moment in any migration is not the technology. It is the blank profile. You can explain Nostr beautifully, talk about keys, relays, censorship resistance and portable identity, and still lose a normal creator at the exact point where they open a new app and see nothing familiar. Years of work sit on Instagram, TikTok, Twitter/X or a newsletter archive. The new network may be better in theory, but the old one already contains proof that the person exists.
Own Your Posts is built around that very human problem. It does two things at once. The public page explains why Primal and Nostr are different from closed social platforms. The app code goes further: it gives creators a way to bring selected public posts, media or articles into a Nostr identity so the first Primal profile does not feel like a cold room. It is an onboarding tool, but not only a brochure. It is also a migration machine.
That matters because "own your content" is usually a slogan until a tool makes the move concrete. Own Your Posts asks for a handle, pulls public material from the old place, lets the user choose what to bring over, then posts that material into Nostr. The result is not a perfect copy of Instagram, and it should not pretend to be. The point is simpler: a creator can arrive on Nostr with a visible body of work, instead of asking followers to trust an empty account.
The tone of the official page is deliberately plain. It compares Primal with Instagram, X/Twitter, TikTok and Substack across ads, ownership, portability, direct earning and banning risk. It says Primal is built on Nostr. It points to beginner material, Primal app downloads and a migration button. You can read the site as persuasion, but the stronger reading is product psychology. It tries to remove the first objection before the user has to say it out loud: "I already posted my life somewhere else."
The migration is the hook
The central promise is not vague decentralization. It is the offer to bring content to Primal. The official page describes a three-step flow: enter a handle, pick favorites, then see them on a Primal profile. The visible demo is Instagram-first, but the repository is wider. The source tree includes Instagram, TikTok, Twitter/X and RSS routes. The backend has stream endpoints for Instagram, TikTok, Twitter and RSS/Atom feeds. The article path is there because newsletter and blog content need a different Nostr shape than photo posts.
This is the right design instinct. A creator's archive is not one kind of object. Instagram has images, reels and carousels. TikTok is video-first. Twitter/X has text, photos and video. RSS and Substack-style feeds can contain full articles. A serious importer cannot treat all of that as one blob. Own Your Posts separates media posts from long-form articles, then uses different Nostr event templates for each.
For short social posts with media, the code creates kind 1 events and attaches media through `imeta` tags. The content includes the caption and Blossom URLs. For long-form material, it creates NIP-23 kind 30023 events with a `d` tag, title, summary, image and published_at tag. For profile metadata, it can create kind 0 events. For follow packs, the signing utilities also include a kind 3 contact list event path. You can see a whole social migration vocabulary emerging from those few event kinds.
The hook is therefore not "Primal is better, trust us." It is "bring enough of yourself that Primal has something to work with." That is a more credible bridge. People do not join networks because protocols are elegant. They join when the first five minutes feel survivable.
What the code actually does
The public repository is `primalpaul1/instagram-to-nostr-v2`, described as "Bring your content to Nostr." At this research pass it has 323 commits, 5 stars, 0 forks and 0 open issues. The visible language mix is Svelte, TypeScript and Python. The frontend is a SvelteKit app using Svelte 5, TypeScript, Vite, `nostr-tools`, `@noble/secp256k1`, `@noble/hashes`, `better-sqlite3`, `qrcode` and `ws`. The backend is FastAPI with httpx, gallery-dl, feedparser, markdownify and BeautifulSoup. The worker is Python.
The architecture has three faces. The SvelteKit frontend runs the wizard, the Primal/Nostr connection screens, post selection, progress screens and API routes. The FastAPI backend fetches external social content and handles streaming upload work. The worker processes queued proposals, gifts and migrations, uploads media to Blossom and prepares assets for later signing flows. SQLite appears throughout the schema and server utilities, so this is closer to a practical small service than a purely static marketing page.
Instagram fetching uses the Instagram120 RapidAPI endpoint in the backend, with pagination and a configurable maximum of 100 posts. It extracts profile data, images, videos and carousel media. TikTok uses ScrapTik through RapidAPI, also capped at 100 posts. Twitter/X uses the Twitter API45 RapidAPI timeline endpoint and includes text-only tweets, photos and videos. RSS uses feedparser, converts HTML content to Markdown, and limits the feed path to 50 articles. Those limits are not arbitrary decoration; they are signs of an app designed around API cost, rate limits and reasonable import batches.
Media upload is built around Blossom. The client-side progress path downloads media through a proxy route, calculates SHA-256 in the browser, signs a Blossom auth event locally with a temporary keypair, then PUTs the media to `https://blossom.primal.net/upload`. The server upload path does a similar job with FastAPI: fetch the video, calculate SHA-256, send the authorized upload to Blossom, and return the final URL, hash, size and MIME type. The code uses Blossom auth kind 24242 with upload and hash tags, which keeps media authorization separate from the user's social identity.
That last sentence is important. The temporary Blossom key is not the same thing as your Nostr identity. The media is content-addressed; the post that points at it is signed later by the user's actual Nostr key or remote signer. It is a small but useful separation. Uploading a file and publishing a social event are not the same act, so the code treats them differently.
Signing: three doors, three risks
Own Your Posts has to solve the most sensitive problem in any Nostr importer: who signs the events? A migration tool can do a lot of helpful work, but if it handles keys badly, the whole pitch collapses. The repository shows three paths, and they should be understood separately.
The friendliest modern path is NIP-46 remote signing through Primal. The `nip46.ts` file builds a `nostrconnect://` URI, includes relay information for `wss://relay.primal.net`, names the app "Own Your Posts" and generates a QR code. The user approves from Primal, the app waits for a kind 24133 Nostr Connect acknowledgement, then uses a BunkerSigner to request signatures. In this mode, the user's secret key stays in Primal. The browser holds a local temporary key for the remote signing conversation, but the actual identity key remains with the signer.
The second path is NIP-07 extension signing. If the user has a browser signer, the code can call the extension through `window.nostr`. The Keys step explains that the secret key remains in the extension and tells the user to keep the tab open during publishing. This is a familiar Nostr web pattern: powerful, convenient and worth treating with normal signer caution.
The third path is generated keys. The `nostr.ts` helper creates a secp256k1 keypair, encodes npub and nsec, and the UI can download a `primal-key.txt` file. That makes onboarding simple for someone with no Nostr identity yet. It also creates a real responsibility: the downloaded nsec is the account key. If a user loses it, the account is gone. If someone else gets it, that person controls the account. The app's text says this directly, and that honesty matters.
There is also an older job API in the codebase that accepts `publicKey` and `secretKey` for server-side job creation. The newer `/api/migrations` route is explicit that client-side signing sends no secret keys. Those paths should not be blurred. Own Your Posts appears to have evolved from a server-job importer toward a safer client-side or remote-signed migration flow. That evolution is exactly the kind of thing you want to know before trusting a tool with an archive.
Where the posts land
After media is uploaded and events are signed, Own Your Posts publishes to a small default relay set: `wss://relay.primal.net`, `wss://relay.damus.io` and `wss://nos.lol`. It also tries to import signed events directly to Primal's cache server at `wss://cache1.primal.net/v1`. That cache import is not the same thing as open relay publishing. It is a Primal-specific speed path so imported posts show up in Primal quickly, especially when events carry old timestamps from the original platform.
This is a very practical choice. If you import old Instagram posts and preserve original dates, they may not behave like fresh notes in every client. Some apps may display them in historical order. Some may not index them immediately. Some may show the media differently. Own Your Posts is clearly optimized for Primal as the first destination, while still using normal Nostr events and relays for wider availability.
The post template preserves more than just a caption. For media posts, it carries the uploaded media URLs, MIME type, SHA-256 hash, size and optional dimensions in imeta tags. It also tries to set `created_at` from the original date when possible. For long-form articles, it uses Markdown content, a replaceable addressable event kind, a `d` tag identifier and metadata tags that Primal Reads can use for previews. That is how the importer turns old-platform material into protocol-shaped material rather than only pasting links into a feed.
Still, a migration is not a magic teleport. Your Instagram followers do not become Nostr followers. Your old comments do not become Nostr replies. Algorithmic reach does not carry over. The value is that selected public work can become signed Nostr material attached to your key, visible in Primal and understandable by other Nostr apps to the degree those apps support the event kinds and media tags.
Why Primal sits in the middle
Own Your Posts is closely tied to Primal, and it should be honest about that. The official page says Primal is built on Nostr, links to Primal downloads, uses Primal examples and compares Primal against closed platforms. The builder trail points to Paul Keating, `paulinthejungle`, whose Nostr profile says he is building Primal and links to the repository. In a March 18, 2026 Nostr note, he described going on a Primal onboarding spree and said his tool for bringing existing content over was working well.
That Primal focus is not a weakness if you understand it. Primal is one of the more polished first-touch clients in Nostr, with mobile apps, a web app, built-in wallet behavior and a mainstream social feel. For a creator who is not trying to debug relays on day one, that matters. Own Your Posts does not ask the user to survey the entire Nostr client universe. It chooses a friendly target and tries to make the first profile feel alive.
The site also leans on direct creator economics. The FAQ explains that Primal has a built-in Bitcoin wallet but says the social experience can be used without understanding crypto. It frames zaps as small tips and says Primal's business model is optional services rather than ads or data sales. You can decide how much of that story you accept, but it is coherent: if the first pitch is "you own your posts," the second pitch is "you can earn directly without platform permission."
For the Crays archive, the interesting part is the pattern. Nostr onboarding will not be won by abstract standards pages alone. It will be won by small tools that solve a felt problem. Own Your Posts solves a felt problem: "I have a history somewhere else, and I do not want to arrive empty-handed."
The part that deserves caution
Migration tools are powerful because they touch three sensitive surfaces at once: old-platform data, new-platform identity and media storage. Own Your Posts deserves credit for visible source code and for newer flows that keep secret keys out of the server-side migration route. It still deserves adult caution.
First, the source platform APIs are fragile. Instagram, TikTok and Twitter/X change rules, endpoints, rate limits and anti-scraping behavior. The backend relies on RapidAPI providers for Instagram120, ScrapTik and Twitter API45. If those providers change or fail, discovery can break. That does not make the project bad; it makes it dependent on the old platforms it is helping you leave.
Second, media permanence is a real question. Uploading to Blossom gives the post a content-addressed media URL, and Blossom is the right family of infrastructure for Nostr media. But users should still understand which server hosts the files, how long it keeps them, and whether they have their own copy. "Published to Nostr" does not automatically mean every file is immortal.
Third, signer choice matters. NIP-46 with Primal is friendly. NIP-07 is familiar. Generated nsec keys are simple. Each one has different failure modes. A serious user should know whether they are connecting an existing identity, creating a new one, downloading an nsec, or relying on a remote signing approval. That clarity matters more than hiding the difference behind a shiny migration button.
Finally, the importer should not be mistaken for ownership of audience. Nostr gives you a portable identity and signed posts. It does not give you Instagram's follower graph or TikTok's recommendation engine. The win is not instant reach. The win is that your work can begin to sit under a key you control.
Who built it and what we can prove
The public trail ties Own Your Posts to Paul Keating, known as `paulinthejungle` on Nostr, with the npub `npub1spdnfacgsd7lk0nlqkq443tkq4jx9z6c6ksvaquuewmw7d3qltpslcq6j7`. His Nostr profile says "Building Primal" and links to the repository. The GitHub owner is `primalpaul1`; the repository is public, created on January 1, 2026, updated and pushed on May 15, 2026, with no license field visible in the GitHub API at this research pass.
That last detail is worth noting. The source is visible, but a missing license field means you should not assume broad reuse rights beyond what GitHub visibility allows. For our archive, the source is still valuable evidence. It shows the app's real structure, dependencies and event model. For developers, licensing is a separate question.
Own Your Posts belongs on the Apps Hub because it is a real product surface around Nostr. It is not only a philosophical page. It has a wizard, source fetchers, a signing path, media upload, relay publishing and Primal cache import. It sits at the exact point where onboarding becomes operational: someone has to turn "you own your posts" into "choose these posts, sign them, and watch them appear."
If you are evaluating it as a user, the best first question is not "is this decentralized enough?" The better question is: which identity am I using, what content am I importing, who signs the events, where does the media go, and can another Nostr app understand the result? Own Your Posts gives you a concrete place to ask those questions. That is already more useful than another slogan about open social media.
Sources worth opening
This article keeps claims close to the official page, the public repository, source files, Nostr notes and the relevant protocol references.
- Own Your Posts: Why Primal page
- primalpaul1/instagram-to-nostr-v2 repository
- whyprimal Svelte page source
- frontend/package.json stack and dependencies
- backend/server.py social fetch and Blossom upload service
- worker.py background migration processor
- /api/migrations client-side signing route
- signing.ts Nostr events, Blossom auth and relay publishing
- nip46.ts Primal remote signing flow
- nostr.ts generated keypair helper
- Paul Keating note about the onboarding tool
- Paul Keating Nostr profile
- NostrApps Primal listing
- Primal official site
- NIP-01 basic event and relay model
- NIP-07 browser signing
- NIP-23 long-form content and kind 30023
- NIP-46 remote signing
- NIP-92 imeta media attachments
- Blossom media storage specification
- Own Your Posts on NostrApps
- NIP-54 wiki
- Nostr protocol NIPs repository
- NIP-05 DNS identifiers
- NIP-10 text note threading





