NOTE: This project has been discontinued since ChatGPT has introduced built-in sharing of conversations.
Extension to share your ChatGPT conversations and prompts.
Main page is at ShareConversation.com.
Inspired by ShareGPT, does not share any code with that project.
Backend is Rust with Postgres db. Frontend is JavaScript with Vue. Learning as I go here.
Pieces:
- Extension The extension itself is built with JavaScript. It goes through Vite and the CRX plugin. There is a "content script" that does the main interaction with OpenAI webpages. There is a "popup" script that shows options and has some buttons. This uses Vue. Both communicate with the backend to actually do things.
- Backend
This is a Rust program that runs at
shareconversation.com
. The server talks to a local Postgres database. Uses Diesel and Actix as the main technology. Some settings are in environment variables loaded from a local.env
file. The backend also serves HTML conversations (not just JSON results). - Website
The main website at
shareconversation.com
is a single-page app using Vue. It talks to the backend to do things.
Each piece has it's own npm
stuff. Even the backend has a build step, then the server serves the bundled
files.
Command to make a snapshot db backup (saved locally in timestamped file):
ssh [email protected] "su - postgres -c \"pg_dump --clean sharedprompts\"" > sharedprompts-`date +"%FT%H%M"`.sql
To restore from backup, assuming backup file is locally copied to ~postgres
location:
sudo su - postgres -c "psql -d sharedprompts -f sharedprompts-XXX.sql"
WARNING: With the --clean
in the backup generation, this will wipe the DB and
go directly to backup state. Also note that restoring from backups requires
stopping the backend API server. Can't drop the database until that is done.
The Chrome extension is an "app" in the Chrome developer console so has its own
application id and everything. From within the extension we can access
chrome.identity
and request authentication tokens. The scopes are controlled
by the manifest file. These tokens are full "access tokens". I don't see a way
to just get id tokens (why???)
To validate access tokens, I use:
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=...
For the website, there are some Google Identity Services for Web components. This uses Google Client API JavaScript and shows a "Sign in with Google" button. The result of this flow is an id token.
To validate the id token you need the Google public keys. Google keys are in JWKS (JSON Web Key Set) format at:
https://www.googleapis.com/oauth2/v3/certs
The server caches them and uses cached values. The server grabs the keys every few hours whatever the cache control headers say.
I tried to use existing Rust clients for this but was not successful in getting them to work.
Setup npm
, then do:
cd extension
npm install
To build just for Chrome:
cd extension
npm run package_chrome
To build just for Firefox:
cd extension
npm run package_firefox
To build for both:
cd extension
npm run full_package
That produces the extension/dist/extension_chrome.zip
for uploading to Google
for Chrome and extension/dist/extension_firefox.zip
for uploading to Mozilla
for Firefox. For development, you can do:
BROWSER=chrome npm run dev
If the extension is installed "unpacked" from the dist/
location then this will do
extension HMR. To get the link working, do "Inspect" on the extension popup window.
This establishes the websocket connection and keeps it open for HMR. Final built
extension doesn't need this.