Don't let your deploys go unnoticed.

Every deployment is a win. Dplyd gives developers a simple public log of what shipped, when it shipped, and why it mattered. Share your wins, build a streak, and celebrate with the community.

Free forever No credit card API access included
Team of developers celebrating a successful deployment

Here's how it works.

Step 1

Deploy your code

Push to production using your favorite tools. Add one curl to your CI/CD — that's it.

Step 2

Share the moment

Your deployment appears in the live feed for the world to see. Add context about what you shipped.

Step 3

Celebrate together

Get reactions from fellow developers. Build your streak and show off with embeddable badges.

Polaroid photos of deployment moments scattered on a desk

Every deployment tells a story.

A midnight bug fix. A major feature launch. A complete rewrite that was totally worth it. Your deployments are more than git commits — they're milestones worth remembering.

Public deploy log

A permanent record of everything you've shipped, visible on your profile.

Embeddable badges

Add a live deploy badge to your GitHub README or portfolio. Updates automatically.

Shipping streaks

Track your consistency. How many days in a row can you ship?

deploy.sh
# After your deploy succeeds...
curl -X POST https://dplyd.com/api \
  -H "Authorization: Bearer $DPLYD_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "Shipped v2.0!"}'

View full API docs →

One line in your CI/CD.

Add a single curl command to your deployment script. That's it. Works with GitHub Actions, GitLab CI, Vercel, Netlify, or any pipeline.

  • No SDK required — just HTTP
  • Supports any language or platform
  • Real-time broadcast to followers

Your deploys deserve an audience.

Join developers who celebrate their deployments and build in public. Free forever. No credit card required.

Create your free account

Live Feed

Real-time deployments from the community

Live
Peter Theill
Peter Theill 
deployed a feature 6 minutes ago
6 minutes ago
✨ MCP endpoint for importing donations from Facebook groups (#24)
Adds an MCP server at POST /mcp so an AI agent can turn posts from a public
Facebook group into donations on Forward.
The server never touches Facebook. The agent does the reading, with its own
browser session and its own membership of the groups; the endpoint only turns
"here is a post" into a record. That keeps scraping out of the application and
leaves the MCP surface small enough to stay stable.
Three properties are enforced structurally rather than by convention:

  • Imports are drafts. A new `draft` state is invisible everywhere, because


every listing already goes through `active`, and the direct URL 404s for
anybody but its owner. Watch alerts are held back until `publish!`.

  • Imports are credited to the original poster. `user_id` stays the importing


account - a row needs an owner, and that is who to ask about it - while the
donation is attributed to `source_author_name` and links to `source_url`.
Imports are not requestable, because the importer does not have the item;
visitors are sent to the original post instead. `create_donation` requires
both fields, so there is no way to use this endpoint to post something as
your own.

  • Re-scanning a group is safe. `source_url` is unique at the database, and is


normalised to drop fbclid, mibextid and friends first, so the second import
of a post is refused rather than duplicated.
Two changes fall out of the ownership split. The donor-currency check is
skipped for imports, since `user` is the importer and their region says nothing
about the market the donation belongs to - somebody in Copenhagen curating a
Stockholm group is importing SEK donations, and that is correct. To keep the
invariant that check was protecting, `User#update_stats!` now counts only
donations the user posted themselves, so a curator is neither credited for
items they never had nor able to mix currencies into their totals. The region
and charity checks are untouched.
`list_charities` takes a region and returns only charities whose currency
matches it. The currency rule is the constraint an agent would otherwise trip
over on most calls, and answering it in the tool signature beats answering it
in an error message.
Image URLs arrive from a page an agent was told to go and read, so they are
attacker-influenced in the ordinary case. `RemoteImageFetcher` is https-only,
resolves the host and checks every address it resolves to, pins the connection
to the address it checked, and re-runs all of that per redirect hop.
Authentication is a bearer token rather than the session cookie, because the
caller is not a browser. Tokens are stored as HMAC digests, shown once, can be
named and renamed, and are rate limited per token.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
⬆️ Upgrade libraries
💸 Scope donation currency to the market (#23)
Currency becomes a property of the region a donation happens in rather than
something the donor picks per item.

  • a region owns the currency; a charity accepts exactly one, which keeps its


total raised a single figure

  • a donation copies its region's currency and validates it against the region,


the charity and the donor's own region

  • the locale decides only how an amount is punctuated, never which currency

  • the currency picker is gone from the donation form; `market_controller` keeps


the symbol and charity list in step with the selected region

  • `currency_symbol` columns are dropped for a new `Currency` model, following


`Locale` as the single source of truth

  • the admin dashboard's cross-market total is grouped by currency, not summed


Also makes `regions.donations_count` a true counter cache. An active-only
counter cannot work, since claiming or deleting a donation is an update and
never fires the create/destroy callbacks that maintain it. The regions index,
which labelled that number "available items", now queries for the active count.
Peter Theill
Peter Theill 
deployed a configuration change about 5 hours ago
about 5 hours ago
🌐 Multi-language support: Danish, Swedish, Norwegian, German, French and Spanish (#22)

  • 🌐 Add multi-language support (da, sv, no, de, fr, es)


Localises the site into Danish, Swedish, Norwegian, German, French and
Spanish alongside English, using Rails' own i18n rather than a gem.
URLs
English keeps its existing unprefixed paths, so no URL moves and no
redirects are needed. The other languages are served from a `/da/...`
prefix via `scope "(:locale)"`. Admin, the API and sitemaps opt out.
Locale resolution
URL > signed-in user's profile > cookie > Accept-Language > English.
The URL always wins so a shared or crawled link renders the language it
was shared in. Visitors who prefer another language are redirected once
from an unprefixed path, keeping one canonical URL per language.
Routes without a `(:locale)` segment never redirect. This matters for
the OmniAuth callbacks, which live on fixed paths: redirecting them
discards the auth hash and breaks sign-in.
SEO
`<html lang>`, canonical, hreflang for all seven languages plus
x-default, og:locale and its alternates, and translated titles and
descriptions. The sitemap emits per-entry alternates rather than
duplicating rows per language.
Language selector
Footer dropdown reusing the existing dropdown controller. Saves to the
user's profile when signed in and to a cookie otherwise. Language is
also editable on the profile form.
Content
Navigation, forms, flash messages, emails and meta tags, plus the home,
search, about, press, help, FAQ and MobilePay pages. Emails render in
the recipient's saved language, including their links. Region names and
descriptions are translatable per locale from the admin.
Terms and privacy stay English-only for now and reach other locales
through the fallback; they are keyed and ready for a reviewed
translation.
Fixes found along the way

  • charities#show declared format.rss with no template, so the request


500'd. Added the feed.

  • `xml.language I18n.locale` passed a Symbol, which Builder reads as a


namespace prefix and emitted `<language:en/>`.

  • FAQ answers moved into locale data still contained ERB, which


rendered as literal text. Links now use placeholders resolved in a
helper so they stay locale-correct.
Query efficiency
Fixed N+1s on donation cards (donor avatars, charity logos, regions),
charity logos on the home/MobilePay/country/region pages, comment
authors, leaderboard donors, and notifications in both the navbar and
the notifications page. The sitemap no longer loads each user's
donations separately. Covered by tests that fail if the count grows
with the number of records.
Adds one gem, rails-i18n, for Rails' own date, number and validation
strings in the new languages.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

  • 💚 Fix CI: trailing newline and HTTP verb confusion


Both failures predate this branch and reproduce on develop, but they make
the build red, so they are fixed here.
Rubocop flagged a trailing blank line in admin/users_controller_test.rb.
Autocorrected; the file is otherwise untouched.
Brakeman flagged `request.get?` in Authentication#store_location: HEAD is
routed like GET, so a HEAD request skipped storing the return path.
It now treats the two alike.
The locale redirect had the same divergence, without being flagged. A
crawler checking an unprefixed URL with HEAD would have seen a different
answer than the GET that followed, so it redirects on HEAD as well.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
⬆️ Update version
Support
Support 
deployed a feature 1 day ago
1 day ago
✨ Introduce AI badge for generated media ✨ Introduce video overview preview component
Peter Theill
Peter Theill 
deployed a dependency update 1 day ago
Support
Support 
deployed a feature 5 days ago
Support
Support 
deployed a feature 6 days ago
Support
Support 
deployed a feature 6 days ago
Support
Support 
deployed a feature 6 days ago
6 days ago
✨ Add labels feature to video form ✨ Add new messages and update translations
Support
Support 
deployed a feature 8 days ago
8 days ago
✨ Add conversations data and improve video status handling ✨ Add library upload variant to MediaElementUploadField ✨ Add max duration to SecondsDurationInput ✨ Add new audio and video upload options ✨ Enhance video generation duration menu ✨ Introduce conversation ID and message in video regeneration ✨ Introduce entity chat status handling ✨ Introduce media generation mode in video form ✨ Introduce text effect presets and animations ✨ Introduce video agent response toast component ✨ Introduce video generation duration menu ✨ Update audio version metadata handling
Support
Support 
deployed a bug fix 11 days ago
11 days ago
🐛 Fix partner typecheck issues (#2125) 🐛 Fix sticky table columns (#2126) 🐛 Format video GraphQL queries (#2129) 🐛 Revert templ8-ui declaration path (#2128) ✨ Add image role support and improve image handling ✨ Add text and map effects to video elements ✨ Introduce label types management features ✨ Refactor video generation status handling