Skip to content

Releases: mrcholer/ludicord

Ludicord v3.1.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 22:20

Ludicord 3.1.0

Ludicord 3.1 strengthens production Discord Activities around authentication, Activity-instance isolation, realtime reliability, and multi-process deployment.

Activity launch isolation

  • Each browser launch now receives an opaque launch identifier that is attached automatically to same-origin HTTP requests and WebSocket connections.
  • Session, OAuth-state, and pending-login cookies are isolated per launch.
  • The same user can open two instances of the same Activity without one instance replacing the other instance's guild, channel, session, or WebSocket identity.
  • Logging out or reauthenticating one launch does not log out another launch.
  • External fetch requests are left unchanged.

Authentication reliability

  • Authenticated Activities renew their Discord-backed session before expiry without unmounting the running React tree.
  • A failed renewal keeps the still-valid session and schedules another renewal attempt.
  • Transient Discord Activity membership misses retry with bounded backoff.
  • Discord rate-limit timing is returned to the client and respected during authentication retries.
  • Cached Activity Instance data is refreshed once when a newly joined user is absent from the cached member list.
  • Local fake authentication supports configurable users, instances, guilds, channels, and scopes.

Multi-process deployments

  • LudicordEphemeralTokenStore allows OAuth state and completion tokens to be shared across servers with atomic one-time consumption.
  • LudicordWebSocketAdapter allows route and Activity-room events to cross process boundaries.
  • Cluster-aware totalClientCount() helpers are available for routes, named rooms, and Activity instances.
  • LudicordSharedStateStore provides atomic create and compare-and-set operations for shared Activity state.
  • Memory-backed implementations remain available for single-process applications.
  • createLudicordProductionServer() accepts shared session, ephemeral-token, and WebSocket adapters.

WebSocket and shared-state behavior

  • WebSocket connections wait for required authentication before opening.
  • Reconnection resumes when the browser returns online or becomes visible after the normal retry burst is exhausted.
  • emitWithAck() supports acknowledged events with bounded timeouts and server rejection details.
  • Server route handlers receive route, room, and Activity broadcast helpers without keeping a client reference.
  • client.broadcast() is Activity-instance-safe; explicit route-wide broadcasting uses client.route.broadcast().
  • Slow clients use latest-value coalescing by default instead of being disconnected immediately.
  • Inbound message count and byte-rate limits are enforced independently.
  • Shared-state validation, serialization, and size failures return an error event without disconnecting the client.
  • Optimistic shared state rolls back to the latest authoritative value after rejection.
  • Shared-state revisions can be coordinated atomically across multiple processes.

Request and session security

  • Framework HTTP routes validate allowed hosts and browser origins.
  • WebSocket upgrades apply the same host and origin policy.
  • Same-origin validation includes the port, and explicitly configured cross-origin callers remain supported.
  • Production warns when every Host header is accepted.
  • Activity Instance verification defaults to automatic activation when a Discord bot token is configured.
  • Production WebSockets can require a server-verified Activity session.
  • Production warns when Activity verification is inactive or a request proxy runs without Discord signature verification.
  • Default WebSocket limits are reduced to 256 KiB per message and 512 KiB per second.

Discord and React runtime

  • Discord user, guild, channel, member, role, entitlement, permission, voice, orientation, and thermal payloads preserve the complete data returned by Discord.
  • Scope diagnostics no longer update framework state during React render.
  • useActivityStorage() supports explicit application and instance scopes while retaining the existing activity scope.
  • LUDICORD_VERSION is typed as string, so patch releases do not break applications that consume the runtime version.

Build, package, and generator

  • The development server announces and reserves its Local URL before source compilation begins.
  • Development startup also prints the LAN address when the server listens on all interfaces.
  • Requests arriving during startup wait for the runtime handlers instead of receiving an early 404 response.
  • Initial source compile failures keep the development server running and recover automatically after the file is fixed.
  • Failed server builds remember the source dependency that caused the failure, allowing imported files to trigger recovery before a successful dependency graph exists.
  • Compiler diagnostics take priority over duplicate module-load runtime errors in the development panel.
  • Development diagnostics expose the current listening, compiling, ready, or error lifecycle state.
  • Compiler cancellation messages caused by an intentional shutdown are ignored.
  • Production builds use the new build schema and keep the previous valid output when a build fails.
  • Package licenses are included in both public npm packages.
  • ludicord/internal is no longer a public package export.
  • Generated applications use automatic Activity Instance verification and same-origin request protection.
  • Generated applications include safer WebSocket limits and configurable local Discord test identities.
  • The generated app keeps the standard dev, build, and start scripts as its primary commands.

Compatibility notes

  • Cross-origin browser requests must be listed in server.allowedOrigins; the default is "same-origin".
  • Applications that intentionally send WebSocket messages larger than 256 KiB must set websocket.maxPayload explicitly.
  • Multi-process applications should provide all required shared adapters. The memory stores remain process-local by design.
  • Code importing ludicord/internal must stop; that path was never intended as an application API.

Ludicord v3.0.1

Choose a tag to compare

@github-actions github-actions released this 06 Sep 15:50

Ludicord 3.0.1

This patch release improves clean-clone compatibility checks and keeps generated projects focused on the commands most applications need.

Create Ludicord App

  • Generated package.json files now include only ludicord dev, ludicord build, and ludicord start scripts.
  • Lint, bundle analysis, route inspection, project information, and direct TypeScript checks remain available as advanced commands in the documentation.
  • The focused starter app tree, authenticated API example, and realtime global, Home-viewer, and same-channel counters remain included.

Compatibility checks

  • Source checks now use pnpm@10.30.3, which supports every advertised Node.js version, including Node 20.19.
  • Clean-clone typechecks build package declarations before checking workspace examples, so ludicord and its public subpath types resolve consistently on Linux, Windows, and macOS.
  • The release workflow uses the same pinned package-manager version as source checks.

Ludicord v3.0.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 11:36

Ludicord 3.0.0

Ludicord 3.0 is the first major framework release. It focuses on complete Discord data, a dependable Next-style development experience, safer long-running servers, and build output that remains usable when a new compile fails.

Complete Discord data

  • User, channel, guild, guild-member, participant, and voice-state values keep Ludicord's normalized convenience properties and now include raw, containing the complete object supplied by Discord.
  • OAuth /users/@me fields such as banners, flags, decorations, locale, premium metadata, and future Discord additions are retained in session.user.raw and useDiscordUser().raw. OAuth credentials are never included.
  • The selected /users/@me/guilds object is retained as session.guildRaw and used by useDiscordGuild() until richer verified REST data is available.
  • useDiscordData() returns the complete shared Discord state snapshot.
  • useDiscordRawEvent(name) returns the latest untouched SDK payload for supported events, including voice, speaking, layout, orientation, current-user, current-member, thermal, participant, and entitlement updates.
  • useCurrentGuildMember() is enriched automatically from the verified server context when the SDK event is unavailable.
  • useDiscordGuildMembers() retains the complete member object and complete nested user object on every result.
  • Added verified useDiscordGuildChannels(), useDiscordGuildRoles(), and useDiscordGuildMember(userId?) resources with data, status, error, updatedAt, and refresh().
  • Added refreshDiscordData() to refresh core Discord context and every mounted server resource, and useDiscordPermissions() for explicit guild/channel/member bitfields and safe bigint-compatible checks.
  • Discord avatar, banner, guild icon, member avatar, and avatar-decoration CDN helpers now normalize static and animated hashes consistently while every original hash remains in .raw.
  • createDiscordRest() remains server-only and now provides getUser, getGuild, getChannel, getGuildMember, listGuildMembers, listGuildChannels, listGuildRoles, and a validated read-only API-v10 get<T>() escape hatch. Responses are not reduced to a small framework-owned shape.
  • Server REST reads now use bounded caching, concurrent-request deduplication, abortable timeouts, Discord bucket/global limit tracking, and one bounded short-429 retry. Unsafe absolute, traversal, backslash, or newline-containing resource paths are rejected, and the bot token never enters generated client code.

Compact, extensible sessions

  • Complete Discord .raw user and guild payloads are stored behind an opaque random server-side data key instead of being placed in the encrypted browser cookie.
  • Pending and final cookies remain compact even when Discord adds large profile fields, avoiding common four-kilobyte browser/proxy cookie failures.
  • Session responses rehydrate the complete payload, while the internal data key is never returned to client code.
  • The built-in store is bounded, expiring, and in-memory. createMemorySessionDataStore() and the LudicordSessionDataStore interface support controlled custom/shared storage for multi-process deployments.

Diagnostics V2

  • Replaced the old development overlay with the new Ludicord black/red panel design.
  • Syntax, TypeScript, React render, event-handler, rejected-promise, API, and WebSocket failures share one diagnostic format.
  • Errors show exact relative file, line, column, highlighted source frame, server stack, and React component stack when available.
  • Clicking the source location uses the local editor endpoint and also copies the location.
  • Copy includes the complete diagnostic rather than only the path.
  • Retry re-reads active diagnostics and no longer hides an unresolved error.
  • The panel can be minimized and reopened from its error badge; multiple errors support paging and keyboard navigation.
  • Source highlighting uses a safe single-pass tokenizer. Source text is escaped before markup is added, preventing source snippets from becoming panel HTML.
  • Removed external font requests so the panel works offline and under stricter Content Security Policies.
  • Development diagnostic endpoints use a per-run client token for non-loopback access and are absent from production.
  • Redaction now covers arbitrary environment variables whose names indicate secrets, tokens, passwords, signing-key material, database URLs, or API/access keys. Messages, frames, stacks, and component stacks are all redacted.
  • Full-document development failures render a matching Ludicord HTML error screen instead of the previous JSON dead end.

Routing and automatic not-found UI

  • Added the automatic app/not-found.tsx convention. It is discovered, imported, and connected by Ludicord without edits to app/pages.tsx.
  • Unknown URL hashes preserve the requested deep link and render the project not-found component.
  • Projects without app/not-found.tsx receive a built-in dark reload/back screen.
  • Typed router.push() and router.replace() still reject unknown routes with LUDICORD2001, catching application mistakes early.
  • Embed navigation now synchronizes with real browser history, including browser back/forward and manual hash changes, while keeping the Activity pathname stable.
  • Generated projects use the built-in not-found fallback until an app chooses to add app/not-found.tsx.
  • Embed folders now support inherited layout.tsx files plus nearest-route loading.tsx and error.tsx files. The compiler discovers and connects them without changes to pages.tsx.
  • Added app/global-error.tsx for root failures; it takes precedence over the normal Activity error component at the outer boundary.
  • Added automatic app/metadata.ts with defineMetadata() for title, description, application name, theme color, and color-scheme metadata.
  • Added server-only app/instrumentation.ts with a typed register() lifecycle and optional async cleanup. Development graph replacement cleans up and re-registers it; production runs cleanup after server drain.
  • Added route groups such as app/embeds/(games)/chess/embed.tsx; parenthesized folders organize embeds, APIs, WebSockets, layouts, and fallbacks without changing URLs.
  • Added typed Link navigation and router.prefetch(). Lazy embed modules are cached and can warm on viewport proximity, focus, or hover without double-loading during navigation.
  • Added automatic server-only app/proxy.ts for redirects, maintenance responses, and pre-routing decisions. Framework-owned /_ludicord/* routes always bypass it.

React and Activity state

  • React Strict Mode is enabled by default in development and can be controlled with react.strictMode.
  • Added ludicord lint with the Rules of Hooks and exhaustive dependency checks. It understands Ludicord's lowercase embed() convention while retaining exact source locations.
  • Added useActivityLifecycle() for visibility, focus, online state, Discord readiness, and aggregate WebSocket readiness.
  • Added useActivityStorage() with activity, user, guild, and channel scopes plus cross-tab updates and custom serialization.
  • Added useActivityQuery() with bounded caching, request deduplication, stale times, retries, abortable timeouts, manual refetch, mutation, and stale-request race protection.
  • Added useDiscordEvent() for cleanup-safe callbacks using untouched Discord SDK event payloads, with optional latest-event replay.
  • Added useActivityPresence() for participants, current participant, voice states, speaking users, and alone-state summaries.
  • Added useGameLoop() with managed animation frames, hidden-tab pausing, and clamped frame deltas.
  • Added useSharedActivityState() and defineSharedActivityState() for small revision-checked values isolated by verified application and Activity instance. Rapid updates are queued behind one in-flight revision and reconnects reconcile with the server before resending. Built-in rooms, lifetime, JSON value size, and validation are bounded; durable or multi-process state remains application-owned.

Development runtime reliability

  • Saving ludicord.config.mjs, .env, .env.local, .env.development, or .env.development.local performs a controlled Ludicord restart automatically; developers no longer need to stop and rerun the command for these files.
  • Config and environment changes use exact per-file polling instead of relying on unreliable recursive watcher filenames, including on Windows and OneDrive workspaces.
  • Invalid configuration is reported clearly and can be retried by saving again.
  • API/WebSocket source and imported local modules continue to rebuild without restarting the HTTP process.
  • A failed server graph compile keeps the last working graph active.
  • Successful graph replacement removes obsolete bundle directories, and dev shutdown removes the current run directory.
  • The runtime remains Ludicord-branded; Vite stays an internal compiler implementation.
  • Fixed browser-runtime dependencies are optimized up front, removing the background dependency-discovery shutdown race that could print false build was canceled or missing-cache-directory errors after the dev server stopped.

Production build durability

  • Production builds are created in an isolated temporary directory and installed atomically only after type checking, client compilation, server bundling, manifest writing, and client secret scanning succeed.
  • A failed build preserves the previous .ludicord output instead of deleting the last deployable build.
  • Failed temporary output and replacement backups are cleaned safely.
  • Transient Windows, antivirus, and synced-folder locks receive bounded retries during atomic replacement. If replacement still fails, Ludicord restores the previous build instead of leaving the output half-installed.
  • Strictly named temporary build and backup directories older than 24 hours are cleaned before a later b...
Read more

Ludicord v2.2.5

Choose a tag to compare

@github-actions github-actions released this 04 Sep 23:09

Ludicord 2.2.5

Project creator

  • Choose Tailwind CSS interactively when creating a project.
  • Use --tailwind or --no-tailwind in scripts and automated setup.
  • Start from a polished responsive interface with either Tailwind CSS or plain CSS.

Package and documentation experience

  • Added the Ludicord banner and live package badges to both npm package pages.
  • Pointed package home, source, issues and release links to the public Ludicord repository.
  • Added public package metadata snapshots, an LLM documentation index and agent instructions.
  • Added a reusable Ludicord skill that teaches coding agents the framework's conventions, security boundaries and validation workflow.

Release delivery

  • Public npm trusted publishing now runs from the public repository with provenance.
  • Private builds hand off only approved compiled tarballs, declarations and public notes; original TypeScript and private application code remain excluded.
  • Version changes automatically stage the public payload, publish both packages, verify integrity, update the changelog and package records, and create matching public and maintainer releases.
  • Discord announcements now use Components V2 with a role mention, branded container, changelog button and install command.

Ludicord 2.2.4 - framework and starter

Choose a tag to compare

@mrcholer mrcholer released this 04 Sep 18:04

Ludicord 2.2.4

Status: published to npm on September 4, 2026.

Published package versions: ludicord@2.2.4 and create-ludicord-app@2.2.4.

Activity authoring

  • Automatic layout, loading, error, auth and minimize files, without manual imports in the root.
  • Lowercase export default function embed() authoring with mapped source locations.
  • Persistent Activity state when switching embeds or showing the compact view.

Development experience

  • API and WebSocket hot replacement without restarting the HTTP server.
  • Shared server imports rebuild together; sockets reconnect after a successful replacement.
  • Ludicord-branded compile timing and a development error panel with file, line, column and source excerpts.
  • Per-project compiler caches and recovery after corrected source errors.

Runtime and security

  • Production CSS linking, shared server chunks, request-body limits and streamed responses.
  • Sanitized production errors, browser/server import boundaries and expanded secret scanning.
  • Pending-login confirmation before issuing a usable session, retryable authentication, safer cookie handling and rejection of development-only sessions in production.
  • Activity membership checks against Discord responses.
  • WebSocket cleanup, configured reconnection, route-isolated rooms and session expiry handling.

Discord and tooling

  • Channel names, types and kinds; guild name, icon and permission-gated extended context.
  • Paginated guild members where the application has the required server-side access.
  • Corrected SDK event handling, typed command helpers and clearer missing-permission diagnostics.
  • Updated starter, environment loading, runtime/testing exports and doctor checks.

Package delivery

  • Both packages are published using workflow-bound npm OIDC credentials from a private source repository.
  • Original TypeScript implementation and source maps are excluded from npm tarballs; compiled JavaScript and type declarations are public.
  • Homepage, documentation and issues remain publicly accessible. The repository metadata identifies the real package subdirectory in the private source repository.
  • Public provenance is unavailable for private source repositories.

Limitations and validation

  • API/WS graph replacement resets module-level server memory. Use durable external storage where needed.
  • Configuration, OAuth scopes, environment values and installed framework changes still require restarting dev; scope changes require renewed authorization.
  • Full guild rosters require server-only bot credentials, guild access, the GUILD_MEMBERS intent and Activity membership verification.
  • Rooms are process-local. Multiple replicas require external shared state and sticky routing for the process-local login handshake.
  • Vite remains an internal compiler dependency.
  • Release validation passed 68 automated tests on GitHub's Linux runner, plus package/example builds and typechecks. Earlier local checks also covered browser hot updates and error recovery. These checks do not establish live Discord OAuth, real guild access, mobile/PiP or multi-user production behavior; those still require validation in a Discord application.

See the upgrade guide and release delivery.

ludicord 2.2.1 (npm release record)

Choose a tag to compare

@mrcholer mrcholer released this 04 Sep 14:41

Published npm package

  • Package: ludicord@2.2.1.
  • Original npm publication: 2026-09-04 12:03:18 UTC.

This is a documentation record for an already-published npm version, not a new npm publication. Detailed historical feature notes were not recorded here.

Full release history · Documentation

The main documentation now describes the published 2.2.4 release. Some 2.2.4 features may not exist in this historical version; check the full release history for current package availability.

This tag points only to the public documentation snapshot. GitHub-generated archives contain documentation, not private framework implementation or npm package binaries. The GitHub record creation date is separate from the npm publication date above.

ludicord 2.2.0 (npm release record)

Choose a tag to compare

@mrcholer mrcholer released this 04 Sep 14:41

Published npm package

  • Package: ludicord@2.2.0.
  • Original npm publication: 2026-09-03 12:49:49 UTC.

This is a documentation record for an already-published npm version, not a new npm publication. Detailed historical feature notes were not recorded here.

Full release history · Documentation

The main documentation now describes the published 2.2.4 release. Some 2.2.4 features may not exist in this historical version; check the full release history for current package availability.

This tag points only to the public documentation snapshot. GitHub-generated archives contain documentation, not private framework implementation or npm package binaries. The GitHub record creation date is separate from the npm publication date above.

ludicord 2.1.0 (npm release record)

Choose a tag to compare

@mrcholer mrcholer released this 04 Sep 14:41

Published npm package

  • Package: ludicord@2.1.0.
  • Original npm publication: 2026-09-02 11:39:29 UTC.

This is a documentation record for an already-published npm version, not a new npm publication. Detailed historical feature notes were not recorded here.

Full release history · Documentation

The main documentation now describes the published 2.2.4 release. Some 2.2.4 features may not exist in this historical version; check the full release history for current package availability.

This tag points only to the public documentation snapshot. GitHub-generated archives contain documentation, not private framework implementation or npm package binaries. The GitHub record creation date is separate from the npm publication date above.

create-ludicord-app 2.2.3 (npm release record)

Choose a tag to compare

Published npm package

This is a documentation record for an already-published npm version, not a new npm publication. Detailed historical feature notes were not recorded here.

Full release history · Documentation

The main documentation now describes the published 2.2.4 release. Some 2.2.4 features may not exist in this historical version; check the full release history for current package availability.

This tag points only to the public documentation snapshot. GitHub-generated archives contain documentation, not private framework implementation or npm package binaries. The GitHub record creation date is separate from the npm publication date above.

create-ludicord-app 2.2.2 (npm release record)

Choose a tag to compare

Published npm package

This is a documentation record for an already-published npm version, not a new npm publication. Detailed historical feature notes were not recorded here.

Full release history · Documentation

The main documentation now describes the published 2.2.4 release. Some 2.2.4 features may not exist in this historical version; check the full release history for current package availability.

This tag points only to the public documentation snapshot. GitHub-generated archives contain documentation, not private framework implementation or npm package binaries. The GitHub record creation date is separate from the npm publication date above.