mdshare.link is now a real app scaffold built with Next.js, Prisma, Stripe,
and Resend.
- minimal homepage with rendered/raw markdown toggle
- email-code auth flow
- anonymous publish + claim flow
- direct markdown publish flow and manifest upload/finalize flow
- CLI publish command and installer scripts
- dashboard routes for links, api keys, plan, and support
- public markdown viewer routes
- password-protected publish flow
- storage adapter with local
.data/dev mode and S3-compatible production mode - cleanup script for expired anonymous publishes
- live plan usage metering with free-tier enforcement
- Resend delivery webhook route
- Stripe Checkout + Customer Portal route handlers
- Stripe webhook route
- Prisma schema for users, sessions, api keys, sites, versions, claims, billing, and support
- Install dependencies:
npm install- Copy envs:
cp .env.example .envIf you're running locally, switch APP_URL in .env to
http://localhost:3001.
- Create the local database:
npx prisma db push- Start the app:
npm run dev- For local Stripe webhook testing, run:
./scripts/stripe-listen.shThat helper forwards Stripe events to http://localhost:3001/api/stripe/webhook
and writes the temporary CLI webhook secret to .stripe-webhook-secret, which
the app will read automatically in development.
If you want the whole local billing loop in one command, run:
npm run dev:stripeThat starts the dev server on 3001, waits for it to come up, and then starts
Stripe webhook forwarding in the same terminal session.
Before deploying, set these values explicitly:
APP_URL=https://mdshare.linkDATABASE_URLto your hosted Postgres databaseSTORAGE_BACKEND=s3with the S3 bucket, region, and credentialsRESEND_API_KEYandRESEND_WEBHOOK_SECRETSTRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET, andSTRIPE_PRICE_HOBBY_MONTHLY
Local development can keep:
APP_URL=http://localhost:3001DATABASE_URL=file:./dev.dbSTORAGE_BACKEND=local
Planning and launch docs live under /Users/jackzerby/Sites/markdown-link/docs/strategy. They are reference material for product, marketing, pricing, and launch work, but they are not part of the runtime app.
Publish a markdown file directly:
./scripts/publish.sh README.md --title "README" --description "project notes" --base-url http://localhost:3001For staging or production, point --base-url at the deployed app domain instead.
Or install the command into ~/.local/bin:
./scripts/install.shThen run:
mdshare README.mdYou can also pipe content in:
cat README.md | mdshare -The public URL that the CLI prints comes from the service response, so make
sure APP_URL matches the host where the app is actually reachable. In
production, that should be the deployed domain, not the local dev server.
When you pass a file path, the CLI uses the manifest create -> upload -> finalize flow. When you pipe markdown through stdin, it uses the direct markdown publish path.
API keys can be supplied with --api-key, MDSHARE_API_KEY,
MARKDOWN_LINK_API_KEY, ~/.mdshare/credentials, or a
~/.markdown-link/credentials file containing the key.
Credential lookup order:
--api-keyMDSHARE_API_KEYMARKDOWN_LINK_API_KEY~/.mdshare/credentials~/.markdown-link/credentials
The credentials file should contain the raw API key on a single line.
The service now supports two publish modes:
- simple markdown body posts to
/api/publishes - manifest-based create/upload/finalize flow via
/api/publishes,/api/publishes/[slug]/files, and/api/publishes/[slug]/finalize
DATABASE_URLSESSION_SECRETAPI_KEY_PEPPERSTORAGE_BACKENDSTORAGE_LOCAL_ROOTSTORAGE_S3_BUCKETSTORAGE_S3_REGIONSTORAGE_S3_ENDPOINTSTORAGE_S3_ACCESS_KEY_IDSTORAGE_S3_SECRET_ACCESS_KEYSTORAGE_S3_PREFIXRESEND_API_KEYRESEND_FROM_EMAILRESEND_WEBHOOK_SECRETSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETSTRIPE_WEBHOOK_SECRET_FILESTRIPE_PRICE_HOBBY_MONTHLY
- free publishes expire after
FREE_PUBLISH_TTL_SECONDS - anonymous publishes can be claimed after email verification
- hobby users get permanent publishes
- Stripe webhooks are the source of truth for billing state
- move upload traffic from server relay to presigned direct-to-blob uploads
- add richer site management actions like duplicate/delete/password audit history
- add background jobs for cleanup and billing retries