This is a stripped-down Devvit project, showing a basic example of how games can create daily posts with new levels/content without requiring an app update and keeping previous levels/posts untouched.
The example "game" is a simple "find the treasure" game. The user is presented with a 5 x 5 grid of "boxes" to select. The user then "clicks" on the boxes to find whether that box has treasure or not. Once all treasure is found, the user wins!
Each post is able to define the "boxes" that the treasure is in. Moderators use a "menu" on the subreddit level to give a "Level Name" and "Game Data" (csv of box indicies that contain treasure). On submit, it gets "queued" to create a post via a scheduler (right now every minute, but could be at a specific time every day). The post created by the scheduler saves the "Level Name" in the "Post Data". When the front-end loads, it calls the back-end to fetch the "Game Data" from redis.
This file contains the basic configuration for a Devvit application. The key points that are unique to this example:
-
menu - This defines a menu action on the subreddit menu, only available to moderators. This menu simply opens the form defined in the form section. See Menu Documentation
-
forms - This defines a single "createGameForm" form and the API endpoint to call when the form is submitted. See below for further details. See Forms Documentation
-
scheduler - This defines a single "task" that runs every minute and the API endpoint to call when the task runs. See below for further details. See Scheduler Documentation
The server side code consists of these major "focus" areas:
-
src/server/actions/1_menuAction.ts - This defines an endpoint that is called when the menu at the subreddit level is selected by a moderator. It simply displays the "createGameForm" form, which has two inputs: Level Name and Game Data. The Level Name is a unique name given to the data provided in the next input, and acts like a "name" for the post that gets created. The Game Data represents the data specific to the new post being created. In the example, it is a comma separated value list of numbers representing the box indicies the treasure is located in.
-
src/server/actions/2_formAction.ts - This defines an endpoint that is called when a moderator submits the "createGameForm" mentioned above. It simply stores the Level Name and Game Data into a redis hash with a key of "data:queue", where the Level Name is a hash property. This will then be used by the scheduler (next).
-
src/server/actions/3_scheduledAction.ts - This defines an endpoint that is called by a scheduler that runs every minute. It's job is to detect new post data provided by a moderator by the menu + form previously mentioned. First, if there is no new "data:queue" items to process, it exits. If there is data, it loops over each hash entry (Level Name => Game Data), stores them as a new Redis key, and creats a post with the "Level Name" stored in the "postData" property. This was to demonstrate how a scheduler could be used to pull in new game data from different sources, such as (old Reddit) wiki pages, external APIs, or even content generated by the scheduler itself!
-
src/server/actions/4_initGameAction.ts - This defines an endpoint that is called by the game front-end (from Reddit post). This was to demonstrate how post specific game data can be obtained using the postData (Level Name), which is specific to each post created!
The client / Reddit post code consists of one major "focus" area:
- src/client/App.tsx - This defines a basic app that renders the "find treasure game". The main focus is on calling the /api/init API to get the "treasure locations" from the back-end, then rendering the "game grid" and using the "treasure locations" when a user chooses a "grid box".
I have also included my commonly used "Logger Helper", which I used for logging on the Devvit server side. It allows you to specify a LogLevel in app settings (see the "settings" block in Devvit.json as well). You can then create a new Logger with a specified label, then log messages at various log levels to help with debugging a production application.
This provides all basic information needed for logging: date, area of code, log level, and the message/data. Here is an
example log from the src/server/actions/2_formAction.ts file.
2025-10-19 12:42:03 [Form - Create Game] INFO - Form action triggered. Saving Level Four and 24 to processing queue.