Releases: mrcholer/ludicord
Release list
Ludicord v3.1.0
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
LudicordEphemeralTokenStoreallows OAuth state and completion tokens to be shared across servers with atomic one-time consumption.LudicordWebSocketAdapterallows route and Activity-room events to cross process boundaries.- Cluster-aware
totalClientCount()helpers are available for routes, named rooms, and Activity instances. LudicordSharedStateStoreprovides 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 usesclient.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 explicitapplicationandinstancescopes while retaining the existingactivityscope.LUDICORD_VERSIONis typed asstring, 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, orerrorlifecycle 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/internalis 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, andstartscripts 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.maxPayloadexplicitly. - Multi-process applications should provide all required shared adapters. The memory stores remain process-local by design.
- Code importing
ludicord/internalmust stop; that path was never intended as an application API.
Ludicord v3.0.1
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.jsonfiles now include onlyludicord dev,ludicord build, andludicord startscripts. - 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
ludicordand 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
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/@mefields such as banners, flags, decorations, locale, premium metadata, and future Discord additions are retained insession.user.rawanduseDiscordUser().raw. OAuth credentials are never included. - The selected
/users/@me/guildsobject is retained assession.guildRawand used byuseDiscordGuild()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(), anduseDiscordGuildMember(userId?)resources withdata,status,error,updatedAt, andrefresh(). - Added
refreshDiscordData()to refresh core Discord context and every mounted server resource, anduseDiscordPermissions()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 providesgetUser,getGuild,getChannel,getGuildMember,listGuildMembers,listGuildChannels,listGuildRoles, and a validated read-only API-v10get<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
.rawuser 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 theLudicordSessionDataStoreinterface 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.tsxconvention. It is discovered, imported, and connected by Ludicord without edits toapp/pages.tsx. - Unknown URL hashes preserve the requested deep link and render the project not-found component.
- Projects without
app/not-found.tsxreceive a built-in dark reload/back screen. - Typed
router.push()androuter.replace()still reject unknown routes withLUDICORD2001, 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.tsxfiles plus nearest-routeloading.tsxanderror.tsxfiles. The compiler discovers and connects them without changes topages.tsx. - Added
app/global-error.tsxfor root failures; it takes precedence over the normal Activity error component at the outer boundary. - Added automatic
app/metadata.tswithdefineMetadata()for title, description, application name, theme color, and color-scheme metadata. - Added server-only
app/instrumentation.tswith a typedregister()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
Linknavigation androuter.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.tsfor 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 lintwith the Rules of Hooks and exhaustive dependency checks. It understands Ludicord's lowercaseembed()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()anddefineSharedActivityState()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.localperforms 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 canceledor 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
.ludicordoutput 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...
Ludicord v2.2.5
Ludicord 2.2.5
Project creator
- Choose Tailwind CSS interactively when creating a project.
- Use
--tailwindor--no-tailwindin 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
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)
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)
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)
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)
Published npm package
- Package: create-ludicord-app@2.2.3.
- Original npm publication: 2026-09-04 12:04:52 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.2 (npm release record)
Published npm package
- Package: create-ludicord-app@2.2.2.
- Original npm publication: 2026-09-03 13:50:52 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.