0xVenture Capitalist is a browser game inspired by AdVenture Capitalist, where players invest in businesses to generate revenue and strive for financial success.
It is an idle/clicker/incremental game that educates players about investing, blockchain and cryptocurrencies.
Invest in different blockchain businesses and gain revenue, starting out with a single lemonade stand. Hire managers to earn while you're away, and make as much money as possible.
Become a blockchain business tycoon, and MAKE YOUR FORTUNE!
- As a player, I want to invest in various businesses to generate revenue.
- As a player, I want to hire managers to earn money even when I'm not actively playing.
- As a player, I want to track my progress and see how much money I've earned.
- As a player, I want to upgrade my businesses to increase their revenue.
- As a player, I want to unlock new businesses as I progress in the game.
- As a player, I want to have an engaging and visually appealing user interface.
- As a player, I want to experience smooth gameplay with no errors.
- As a player, I want to learn about investing, blockchain and cryptocurrencies.
- As a player, I want to be guided on how to play when I first start playing.
- As a player, I want to earn rewards for playing the game.
CRUD | Method | Endpoint | Description |
---|---|---|---|
C | POST | /api/auth/[...nextauth] | Create new user. |
R | GET | /api/player/[email] | Get a User by user.email . |
R | GET | /api/player/business/[userId] | Get all Business with userId . |
U | PUT | /api/player/business/buy/[userId] | Buy a Business for userId , update user.coins , business.quantity , and business.time or business.revenue from unlock bonus if any. |
U | PUT | /api/player/business/collect/[userId] | Collect profits for userId , update user.coins . |
U | PUT | /api/player/business/manager/[userId] | Purchase a manager for Business for userId , update user.coins and business.managerOwned . |
C | POST | /api/player/business/seed/[id] | Create all Business and Upgrade for userId . |
R | GET | /api/upgrade/[userId] | Get all Upgrade with userId . |
U | PUT | /api/upgrade/buy/[userId] | Purchase an Upgrade for userId , update user.coins , upgrade.purchased , and business.revenue . |
D | DELETE | /api/admin/reset/[userId] | If requester's user.admin === true , delete all Business and Upgrade with userId , reset user.coins to 0, and increment user.resets by 1. |
The game is built using Next.js, bootstrapped with create-next-app
.
To provide a visually appealing user interface, an interactive and engaging experience, and with smooth gameplay mechanics, the following libraries are used:
-
Languages: JavaScript, TypeScript
-
Framework: React
-
Meta Framework: Next.JS v13.4 with
app
directory -
State Management: Zustand
-
Authentication: Auth.js
-
UI/UX:
-
AI Tools:
I decided to use Next.js
, TypeScript
, Auth.js
, Prisma
, TailwindCSS
and Radix UI
from the start. The usual process is to decide on a stack after the project is scoped, but I wanted to challenge myself to learn new technologies and build a full-stack application with a modern tech stack.
After the initial planning phase, I used an iterative approach to develop the game, first focusing on building the core functionality and gradually adding features to enhance the gameplay experience, and quickly work towards a working prototype.
This allowed me to launch the game publicly in 10 days, fix major bugs on launch day, and further iterate on it to improve the user experience.
Here are the major steps taken during the development process:
-
Project Setup & Deployment: Set up the development environment and install the necessary dependencies. Configure the Next.js v13 app router project structure and setup boilerplate for Navbar, Authentication, Prisma and DB connection. Deployed the application to Vercel early, enabling easier detection of bugs related to production vs localhost.
-
Planning: Brainstormed ideas and decided on "an educational game about finance/investing". Researched existing games to find inspiration for a game that would be fun play, technically challenging to build, and achieveable within the given timeframe. Found AdVenture Capitalist, and decided to clone it. Researched the game, learned from existing clones, and asked ChatGPT for help.
-
Backend Development: Build the backend using the Next.js v13 app router, and MongoDB with Prisma for database. Designed the database schema and implemented the API endpoints for creating, reading, updating, and deleting data.
-
Frontend Development: Implemented the frontend using React, TypeScript and Next.js. Used Zustand for state management. Designed the user interface, including the game mechanics, investment options, and revenue tracking. Used Tailwind CSS for styling, Radix UI for pre-made components, React Hot Toast for notifications, Framer Motion for animations, and Use Sound for sound effects.
-
Integration: Integrated the frontend with the backend, enabling seamless communication between the client and server. Implemented passwordless OAuth 2.0 authentication using Auth.js to support user and admin logins with different access levels. Strived for 0 breaking/critical UX issues before launching publicly.
-
Testing and Refinement: Thoroughly tested the application to identify and fix any bugs or issues. Gathered feedback from users and made improvements based on their suggestions.
Throughout the development process, followed best practices such as limiting the use of client components
to where user interaction is required, writing clean, DRY, and maintainable code, and using version control with Git.
During the development process, encountered some challenges and had a few unsolved problems. These include:
- Performance & Optimization - Laggy UI & Critical UX Issues:
It takes ~2 seconds for an action to get a response on the live server, if the action involves calling the backend API to Prisma to MongoDB and needs to wait for a response, especially if there are additional checks and multiple requests in a single action.
As the game progresses and the player accumulates more businesses and managers, the front-end components re-render more often and more backend api calls are made, and as a result, the performance of the application may be further impacted. Occassionally, a player's browser may run out of memory, causing the client to crash.
Furthermore, the higher the number of concurrent players, the more backend API calls are made, which may result in the server crashing.
Possible solutions to optimize the code and implement strategies to improve overall performance include:
- fix bugs that cause memory leaks (e.g. dismount timers when not in use, unsubscribe from event listeners, etc.)
- take advantage of server-side rendering and server components to reduce frontend load
- optimize use of
useState
,useEffect
,useRef
etc. to prevent unnecessary re-renders - effective use of
useMemo
anduseCallback
etc. to memorize expensive values and computations - optimize server & db locations to reduce latency (e.g. use CDN, or edge network)
- scale up server & db to handle more concurrent requests
- code splitting to reduce bundle size
- hydration to reduce time to interactive
- caching, lazy loading, data pagination to reduce number of API calls
- Performance & Optimization - MongoDB & Concurrent Players:
MongoDB Altas free tier limitation (source):
- 100 crud requests per second at max
To maximize usage, we want to reduce the number of API calls to MongoDB (per player, per second) as much as possible. Ideally, we want to make <1 CRUD request per second per player, so that we can have 100+ concurrent players while on the free tier.
In the initial version of the game, 1 API call to MongoDB is made every time revenue is auto-collected, which can be 20+ times per second per business. As a result, the app could only support less than 5 concurrent users. This is not scalable.
As a temporary solution, the auto-generated revenue is first saved to Zustand store, and then pushed to MongoDB every 30 seconds. In a perfect world, this scales the app up to enable a max of 3,000 concurrent players (3,000 requests / 30 seconds = 100 req/s) while on the free MongoDB tier.
Some other possible solutions include:
- queue API calls to MongoDB (e.g. use
Promise.all
to batch API calls) - reduce API calls for remaining player actions (e.g. collect revenue manually, buy business, hire manager, etc.)
- throttle / rate limit the number of API calls
- use React Query (Tanstack Query) or Redis to cache data
- use GraphQL to reduce the number of API calls
- use "static" or "closure" functions
- Syncing Database vs Store/State:
Notably, this version uses MongoDB as the primary source of truth, and Zustand was implemented later on to improve UX with instant updates to the UI.
As a result, there are 2 states to manage: the database and the store/state, and they are not always in sync.
There are several cases where a discrepancy occurs between the database and the store/state, where one is updated but not the other. This mostly involves the 30 second window when the auto-generated revenue is saved to the store but not yet pushed to the database. Examples include:
- the player refreshes the page, resulting in the store/state being reset to the database values.
- the player purchases an upgrade or investment, resulting in database value becoming negative while the store/state value is still positive.
- the profits earned when a player is actively playing vs when offline are calculated differently (offline profits pays pro-rated revenue vs if actively playing you would earn 0 if timer is not yet reached), resulting in offline profits being higher/faster.
Possible solutions include:
- use Zustand as primary source of truth with occassional updates to MongoDB
- Gameplay Bugs, Loopholes and Exploits:
A major bug is that the player is able to purchase an upgrade multiple times, even though there are basic checks in place to try prevent multiple buys.
When purchasing the upgrade, the following checks are made on the backend API route:
- if the player has enough money to purchase the upgrade
- if the player has already purchased the upgrade
On the frontend, the purchase upgrade button is also disabled once the player clicks on it, until the function to purchase the upgrade is completed.
One possible reason for this bug is that almost-simultaneous calls manage to pass the check of upgrade.purchased = false
and coins > upgradeCost
.
Possible solutions:
- implement a more robust check on the backend API route
- disable the button on the frontend for a longer period of time
- implement a queue system to handle multiple requests
- implement a random delay (0-1s) before the purchase upgrade function is executed
- write unit tests
- Security:
Ensuring the security of user data and preventing unauthorized access is crucial.
Measures taken to secure the application include:
- using HTTPS
- using Auth.js for authentication
- using
next-auth
to create API routes - using
next-auth
to create protected pages
Other security measures to consider:
- protect API routes such that they can't be called directly with bogus data and/or by user without authorization
- using
next-rate-limit
to limit the number of requests - using
next-secure-headers
to set security-related HTTP headers - using
next-csp
to set Content Security Policy headers - etc.
- User Feedback, Testing and Iteration:
While the application has been thoroughly tested, there may be some bugs or issues that have not been identified.
If you encounter any problems while playing the game, please report them by creating an issue so that they can be addressed.
Gathering user feedback and incorporating it into the application is an ongoing process. Encourage users to provide feedback and suggestions, which will help identify areas for improvement and enhance the overall user experience.
-
Mobile-friendly UI: The game is currently optimized for desktop and tablet screens, but not yet for mobile. This is a future development that will be implemented in the next version of the game.
-
Cloning All Features: Due to time constraints, not all features of AdVenture Capitalist were cloned. Some of the features that were not implemented include:
- angel investors (reset game)
- moon/mars expansion
- unlocks for 5,000+ quantity of businesses
- achievements (milestones)
- events
- advertisements
- etc.
- New Features: Some new features that could be implemented in the future include:
- Leaderboard
- Web3 integration
- NFTs for players/characters, skins, etc.
- Weekly/monthly rewards
- Multiplayer
- etc.
- Explore Alternative Technologies: Some other technologies that could be explored in the future include:
- JS frameworks: Deno+Fresh, Svelte, Astro, Qwik, Solid, Bun, Vue
- TypeScript libraries: Zod, tRPC
- State management: Jotai, Redux Toolkit
- Database: Firebase, Supabase, Planetscale, Cassandra, FaunaDB, PocketBase, CockroachDB
- Caching: Tanstack Query (also for state), Redis (also for db)
- Object Relational Mapper: Drizzle
- Authentication: Clerk
- Web3: Thirdweb, Wagmi, Ethers, Siwe
- Testing: Playwright, Cypress, Jest
- API: GraphQL
- Containerization: Docker
- Mobile frameworks: React Native, Flutter
- Game frameworks: Unity, Phaser
- Headless? Serverless? Edge? "Edge is slower if data-fetching is involved but not optimized"
References:
- How to OVER Engineer a Website // What is a Tech Stack?
- Web Development In 2023 - A Practical Guide
- 2023 JavaScript Predictions: What to Expect
- 2023 Frontend Dev and more
- 7 better ways to create a React app
- I built the same app 10 times // Which JS Framework is best?
- My Bleeding Edge Tech Stack for 2025
- 5 dev trends to follow in 2023
- Clone the repository:
git clone https://github.com/sov3333/0xVenture-Capitalist.git
- Install dependencies:
cd your-repo
npm i
- Set up the database:
Create a MongoDB database and obtain the connection URL. Rename the .env.example
file to .env
and update the DATABASE_URL
with your MongoDB connection URL.
Sync Prisma client API with the DB:
npx prisma db push
Whenever Prisma schema is changed, need to manually invoke npx prisma db push
in order to accomodate the changes in the Prisma Client API.
- Fill in remaining values in
.env
:
NEXTAUTH_SECRET
- use random hex string e.g. https://generate-secret.now.sh/32.[AuthProvider]_ID
and[AuthProvider]_SECRET
for Google/Twitter/Github.
- Start the development server:
npm run dev
- Open your browser and visit http://localhost:3000 to see the app running.
I would like to acknowledge the following resources that inspired and supported the development of 0xVenture Capitalist:
-
AdVenture Capitalist clones in JavaScript by @Rukmoni, @matart15 and @Satttoshi.
-
YouTube tutorials:
- Next.js 13 - The Basics
- Securely Fetching Data in NextJS 13 Server and Client Components!
- The Ultimate NEXT.JS 13 Tutorial (Complete Walkthrough w/ Examples)
- NextJS 13 Introduction - Building a fullstack app using Prisma & Mongodb
- Set up a (Next.js + Zustand + Typescript) app | Part 1
- Authentication with Next Auth and Next.js 13
- Full Stack Airbnb Clone with Next.js 13 App Router: React, Tailwind, Prisma, MongoDB, NextAuth 2023
-
Icons on Flaticon.com created by designbydai, Taufik Ramadhan, Freepik, justicon, itim2101, Flowicon, Konkapp, and iconjam.
-
Sound effects on Freesounds.org created by yottasounds, JomelleJager, Bertrof, Mr.Fritz, The-Sacha-Rush, and plasterbrain, and music on Itch.io created by JDSherbert.
0xVenture Capitalist is a captivating idle/clicker/incremental browser game that allows players to invest in businesses, generate revenue, and strive for financial success. With its intuitive user interface, engaging gameplay mechanics, and seamless integration of backend and frontend technologies, the game offers an immersive experience for players.
Hope you enjoy playing 0xVenture Capitalist as much as I enjoyed creating it. Feel free to provide feedback, report any issues, or contribute to the project's ongoing development.
See you on the moon!
This project is licensed under the MIT License.