Skip to content
Up NextUp Next
Esc
↑↓navigate↵open⌘Jpreview
On this page

Libraries

Use the Up Next feed from your own Effect app.

Up Next is built from Effect v4 libraries, published to npm and JSR. They work under Bun and Node.

Package Use it to
@timmo001/effect-upnext Talk to a running daemon over its socket
@timmo001/effect-twitch Sign in to Twitch, find live channels and turn them into MediaItems, without the daemon
@timmo001/effect-youtube Read YouTube channel feeds and live streams and turn them into MediaItems, without the daemon
@timmo001/effect-upnext-shared Use the MediaItem schemas every source and client shares

The CLI is a client of the same RPCs that effect-upnext defines, so anything the CLI does, your app can do too.

Client

bun add @timmo001/effect-upnext @timmo001/effect-upnext-shared effect

effect is a peer dependency, so install the Effect v4 version your app already uses.

UpnextClient is an Effect service built on effect/rpc. UpnextClient.layer(socketPath) opens the Unix socket and speaks newline-delimited JSON. The connection lives as long as the layer, so provide it once around the work that needs it.

resolveSocketPath finds the socket the same way the CLI does. See Socket path.

import { BunRuntime, BunServices } from "@effect/platform-bun";
import { resolveSocketPath, UpnextClient } from "@timmo001/effect-upnext";
import { Console, Effect, Option, Stream } from "effect";

const program = Effect.gen(function* () {
  const client = yield* UpnextClient;

  yield* client.WatchFeed().pipe(
    Stream.runForEach((feed) =>
      Console.log(
        `${feed.items.filter(({ item }) => item.kind === "live").length} live`,
      ),
    ),
  );
});

const main = Effect.gen(function* () {
  const socketPath = yield* resolveSocketPath(Option.none());

  yield* program.pipe(Effect.provide(UpnextClient.layer(socketPath)));
});

main.pipe(Effect.provide(BunServices.layer), BunRuntime.runMain);

RPCs

RPC Does
GetFeed Returns each source’s status and every item
WatchFeed Streams the whole feed, then again after each change
Recheck Checks every source, or one, now
SignIn Starts signing in to Twitch and returns the page the daemon opened
AddChannel, RemoveChannel Change channels.yml
QueueAdd Saves a URL to watch later
MarkWatched Hides a YouTube upload or removes a saved item

Calls fail with RpcClientError when the daemon isn’t reachable rather than waiting for it to come back.

Last updated on October 4, 2026