Inspiration
Our inspiration was sparked by the Reddit x Bolt Hackathon's "Silly Sh!t" category itself! We embraced the challenge to create something "hilariously impractical" that serves "no real purpose but brings maximum joy." The classic 1970s "Pet Rock" fad came to mind – a perfect icon of delightful pointlessness. We wanted to translate that absurdity into a shared, interactive experience for Reddit communities, a digital companion that offers only its stoic presence and a chuckle. The goal was to build an app that users would interact with just for the fun of it, embodying that spirit of upvoting content "without knowing why."
What it does
"Silly Pet Rock" is an interactive Devvit app that allows moderators to summon a unique "Pet Rock" into their subreddit as a custom post. Users can then interact with their community's Pet Rock through a series of buttons:
Pat the Rock: Give the rock a friendly pat. Tell the Rock a Secret: A form pops up allowing users to "confide" in the rock (which, of course, maintains stoic silence). Ask for Advice: Solicit profound (or profoundly silly) wisdom from the ancient rock. Stare at the Rock: Engage in a silent, intense staring contest.
Each interaction results in a randomized, humorous, and often deadpan text response displayed from the rock's "perspective." While users can pat the rock as much as they like in their session, a hidden global counter (using Redis) also tracks the total number of pats this specific rock has received from all users, adding a subtle communal layer to the silliness. It's an app designed purely for amusement and light-hearted engagement.
How we built it
"Silly Pet Rock" is built entirely on the Devvit platform using TypeScript.
- Core Structure: We started with a fresh Devvit project (and later considered the devvit-bolt-starter-experimental for environment consistency).
- Custom Post Type (PetRockComponent): This is the heart of the app, registered using Devvit.addCustomPostType(). It renders the UI.
- UI with Devvit Blocks: The interface (title, rock image, interaction text, buttons) is constructed using Devvit's lowercase JSX block components like , ,
, and .
- State Management: useState is used within PetRockComponent to manage the current text response from the rock (lastAction) and a session-specific pat counter (though the display of counters was ultimately hidden based on preference).
- Asset Handling: The pet rock image (pet_rock.png) is stored in the assets folder and referenced directly by its filename in the
component, letting Devvit handle bundling and serving.
- Interaction Logic: Each button has an onPress handler function (e.g., handlePatRock, handleTellSecret). These functions update the lastAction state with a randomly selected humorous response from a predefined array.
- Forms for Interactivity: The "Tell the Rock a Secret" feature uses the useForm hook to define the form structure and an onSubmit callback (handleSecretFormSubmit). context.ui.showForm() is then called to display the modal.
- Persistent Data (Global Pat Counter): We utilized context.redis (after enabling it in Devvit.configure) for the global pat counter. . redis.get() fetches the count when the post loads (managed with useAsync). . redis.incrBy() atomically increments the count in handlePatRock. . The key for Redis is made unique per post using context.postId
Challenges we ran into
The Case of the Silent Console Logs: Our most significant and persistent challenge was an issue where console.log (and console.error) statements within certain onPress handlers (handleAskAdvice, handleStareAtRock) and within catch blocks of async Devvit plugin calls (like ui.showForm or redis.incrBy) would not print to the devvit playtest terminal, even though UI updates from those same blocks were working. This made debugging errors from those plugins very difficult. We confirmed other console.log statements worked. A full node_modules and package-lock.json deletion and reinstall, followed by a devvit playtest restart, seemed to resolve this for most handlers, indicating a potential caching or environment state issue within playtest.
Form API Nuances: We initially tried using the Devvit.createForm() static method for the "Tell a Secret" form, which led to difficulties and the silent catch block logging. Referencing working examples (like a previous Raffler app and Devvit's own documentation for "Interactive Posts") led us to successfully use the useForm hook, which is designed for component-internal forms.
Asset URL Resolution: Early on, we explored different ways to get the URL for our bundled pet_rock.png. The Devvit documentation clarified that simply using the filename (url="pet_rock.png") is the correct approach for images in the root of the assets folder.
KV Store to Redis Migration: We initially planned the global pat counter with kvStore, but upon reviewing newer Devvit documentation you provided, we saw the strong recommendation to migrate to Redis and successfully refactored to use context.redis.incrBy.
Accomplishments that we're proud of
- A Fully Functional, End-to-End Silly App: We successfully built a complete interactive experience with multiple engagement points, from simple button clicks to form input.
- Nailing the "Silly Sh!t Weird" Vibe: We think the concept of the deadpan, slightly philosophical Pet Rock and its quirky responses genuinely captures the spirit of the hackathon category.
- Successful Form Implementation: Getting the "Tell the Rock a Secret" form to work smoothly using the useForm hook was a key achievement after initial hurdles.
- Persistent Global Counter with Redis: Implementing the global pat counter using Redis adds a nice communal touch and demonstrates persistence beyond a single session.
- Debugging Perseverance: Overcoming the very tricky silent console.log issue required a lot of systematic testing and eventually a full environment reset, which was a valuable lesson.
- Iterative UI Refinement: We went through several iterations of the UI layout and text display to arrive at a clean, user-friendly, and aesthetically pleasing presentation.
What we learned
- The useForm hook is the way for forms in interactive posts. While Devvit.createForm has its uses (e.g., for menu actions not tied to a component's state lifecycle), useForm is better integrated for custom post components.
- Devvit's documentation and official starter templates are invaluable. When facing API uncertainties, referring back to these (as you did by providing snippets) was key to resolving issues with forms and asset handling.
- The importance of a clean build environment: The "nuke node_modules" approach can often resolve inexplicable issues in devvit playtest, likely related to caching or stale build artifacts.
- Redis is the preferred data store: Understanding the shift from kvStore to redis and implementing it was an important learning point.
- Console logging in devvit playtest can sometimes have quirks, especially around errors from async plugin calls. Having UI-based feedback in catch blocks (like toasts) became essential when terminal logs were unreliable.
- Crafting genuinely funny and varied text responses requires more iteration than one might think!
What's next for Silly Pet Rock
More Rock Personalities & Responses: Expand the arrays of responses for all interactions to ensure high replayability and even more laughs. Perhaps different "moods" for the rock on different days?
More Silly Interactions: Add new buttons like "Sing to the Rock," "Try to Teach the Rock a Trick," or "Offer a Pebble."
Visual Feedback for Global Pats (Optional): If desired, re-introduce a subtle display of the global pat counter, perhaps with milestones that trigger special rock comments.
Community Naming/Customization: Explore allowing a subreddit to give their specific Pet Rock a name via a one-time setting or form.
Log in or sign up for Devpost to join the conversation.