打造 Hounty:循序渐进

2025-06-07

打造 Hounty:循序渐进

我从事软件开发已经十六年了。我搭建过无数的网站、移动应用、后端解决方案,以及一些稀奇古怪的业余项目。这些项目从未像这个一样认真,我既兴奋又忐忑。

我不知道这会引领你走向何方,但我希望你能从我亲身经历的新鲜经历中感同身受,并希望你能从我的失败或成功中受益。最重要的是,我非常感激你愿意分享的任何反馈!

但遗憾的是,让我向你介绍一下 Hounty 的想法:

使用按钮清洁图片之前和之后

主意

我有两个孩子(一个9岁,一个10岁);我深爱着他们,他们是我梦寐以求的最好的家庭。但家里总是乱糟糟的:他们和我一样,创意十足,经常把衣服扔得到处都是,从沙发到床,到处都是零食,还把各种零食剩菜剩饭都扔得到处都是。你可以在上面的图片里看到一些。

大约一个月前,大约在圣诞节前后,为了让他们帮忙,我提出玩一个游戏:

“拿起你们的手机”,我说,“你们其中一个人需要尽可能多地拍下这个房间里所有不合适的东西,然后我们清理这些赏金物品来获得积分”。

我们利用 WhatsApp 群组来实现这一点:

VGGirls 群聊图片乱七八糟

很难记住谁在打扫什么,哪些照片是之前,哪些是之后的,但我们花了大约15分钟就让房间看起来更整洁了。效果显著!

但是用户体验非常糟糕,更不用说我的照片库变得一团糟了:)

概念验证

最初的版本有一个 S3 bucket 作为后端,但后来被IndexedDB取代了。你知道什么比无服务器更好吗?完全没有服务器!

在这里,您可以自己尝试一下:https://hounty.app/clean

它是一个单页 Web 应用程序;所有数据都存储在本地数据库中:

IndexedDB 的控制台视图

图像也存储在那里data:image/png;base64,...

IndexedDB 有一些烦人的回调 API,因此我将它包装在承诺中,以使其使用起来更愉快,例如:

/**
 * Open local indexedDB database & setup schema
 * @returns {Promise<IDBDatabase>}
 */
export const openDb = () => {
    return new Promise((resolve, reject) => {
        try {
            const req = indexedDB.open("bounties", 1);
            req.onerror = (_event) => {
                reject(`Failed to open database`,);
            };
            req.onsuccess = () => resolve(req.result)

            req.onupgradeneeded = () => {
                const db = req.result;

                db.onerror = console.error;

                const objectStore = db.createObjectStore("bounties", {
                    keyPath: "id",
                });
                objectStore.createIndex("status", "status", { unique: false });
                objectStore.createIndex("session", "session", { unique: false });
                objectStore.createIndex("createdAt", "createdAt", { unique: false });
                return resolve(db);
            };
        } catch (error) {
            reject(error)
        }
    })
};
Enter fullscreen mode Exit fullscreen mode

然后我可以使用类似的东西:

/**
 * Add new bounty to the database
 * @param {IDBDatabase} db 
 * @param {import("./types").OpenBounty} bounty 
 * @returns {Promise<IDBValidKey>}
 */
export const createBounty = (db, bounty) => new Promise((resolve, reject) => {
    if (!db) return reject("No opened database");
    const t = db
        .transaction("bounties", "readwrite")
        .objectStore("bounties")
        .add(bounty);
    t.onerror = () => {
        reject("Failed to create a bounty");
    };
    t.onsuccess = () => {
        resolve(t.result);
    };
})
Enter fullscreen mode Exit fullscreen mode

任何设备的存储空间都是有限的,因此,作为快速修复,我添加了按下“再次播放”时清除数据库的功能。

就堆栈而言 - 它开始于 Preact 项目,但现在我已将代码移至 Svelte(Kit),以将游戏合并到世界上最无聊的登陆页面中:

黑白 Hounty 登陆页面

猎豹?

我几乎每天都开始玩这个更干净的游戏;为了方便访问,我甚至通过“添加到主屏幕”安装了它。编写一个能帮到你的软件感觉很有趣:这让我不禁思考过去十六年我到底在干什么 ;-)

但孩子们对此并不太感兴趣:是的,他们偶尔会用,但只有在我坚持的情况下才会用。管理层告诉我,获得答案最简单的方法就是提问和倾听——所以我直接问他们,是什么让一款应用如此令人兴奋。

“奖励!”他们告诉我,“如果我们能够获得积分并购买头像,那就太酷了!”

让我直说吧:我再也不用用零花钱和礼物贿赂他们了?他们会为了虚拟积分和SVG去打扫卫生吗?!

闭嘴,拿我的钱!

奖励。赏金。家。家赏金。赏金?没错,打扫卫生每天都让我头疼!不如找个帮你打扫的小鬼来帮忙?

以下是一些正在进行的工作阶段,从 AI 生成的原型到 SVG 绘制的吉祥物和徽标:

《猎杀者》的演出

创业

我太兴奋了!我不仅能做出一些我迫切需要的、有意义的东西,而且终于有借口写代码了!

你看,自从我接手管理工作以来,过去一年里,我花在会议上的时间比写代码的时间还多。别误会——我喜欢促成好的改变,会议室才是真正适合我的地方!我手下还有十几位优秀的开发人员,他们的代码写得比我好得多!但我仍然不想放弃管理。如果我对技术方面一窍不通,我想我就无法成为一名优秀的经理——如果我不能体会他们的苦恼,我又怎么能理解那些依赖我的人呢?

此外,我有时会变得有点过于急躁和固执己见,我认为最好有一个地方来培养我所有疯狂/有远见的想法,而不会过早地打扰其他人的思路,让他们无法从改变中获益。

话虽如此,我将继续致力于草莓的成功,并将继续在目前的岗位上竭尽全力。在雇主的允许下,我将利用我的空闲时间以独资经营者的身份继续经营Hounty。

我昨天提交了文件🎉

这很可怕,简直太可怕了。这是一个充满新规则和新义务的新世界,如果继续做B2B网站和应用,会容易得多。但我有远见,我会投入时间,尽我所能。

我相信软件可以改善生活。我知道承担家庭责任、兼顾家务、工作,还要日复一日地培养下一代是多么不容易。而且我知道,在这样的困境中,我并不孤单。

我相信,如果洗衣、做饭和打扫卫生能少花点时间和精力,我就能创造出令人惊叹的东西!无论是音乐、应用程序、微缩模型(我最近迷上了微缩绘画,太好玩了!),还是其他任何我还没发现的东西!

我相信,如果我能让别人更容易一些,他们就会想出办法来解决一个又一个问题……

我是个梦想家,但也很现实。我知道兼顾工​​作、孩子、副业以及推广消费类应用会非常困难,而且可能需要花费大量时间才能做好。

但我已经决定要这么做。

现在我所拥有的只是一个线框原型,这就是开始的地方:

线框原型

如果您有任何问题、建议或反馈,请告诉我!

如果你们当中有人有兴趣参加用户访谈,我将不胜感激:15-20 分钟的视频通话。

如果您有兴趣,请通过LinkedInvaleria@hounty.app与我联系。

无论如何,我都会随时向您通报进展情况!

文章来源:https://dev.to/valeriavg/building-an-app-baby-steps-2jb7
PREV
使用 React Hooks 和 context 进行全局状态管理
NEXT
创建 React App 的更好方法