[{"data":1,"prerenderedAt":2035},["ShallowReactive",2],{"all-projects":3},[4,184,271,527,623,692,862,1080,1309,1666,1921],{"id":5,"title":6,"body":7,"category":164,"date":165,"description":166,"draft":167,"extension":168,"github":169,"meta":170,"navigation":171,"path":172,"seo":173,"status":174,"stem":175,"tags":176,"url":182,"__hash__":183},"projects\u002Fprojects\u002Fkedarkul\u002Findex.md","Kedarkul",{"type":8,"value":9,"toc":157},"minimark",[10,14,17,22,51,55,61,67,73,79,85,89],[11,12,13],"p",{},"Kedarkul is a school management platform built for the way Indian schools actually work. It replaces the scattered mix of registers, spreadsheets, and WhatsApp forwards that most school offices depend on, with one system that covers the full school lifecycle from the day a student applies to the day they graduate.",[11,15,16],{},"Each school gets its own private workspace at their subdomain. Data is fully isolated and what's inside one school is never mixed with another.",[18,19,21],"h2",{"id":20},"who-uses-it","Who uses it",[23,24,25,33,39,45],"ul",{},[26,27,28,32],"li",{},[29,30,31],"strong",{},"School administrators"," manage admissions, fee collection, staff records, and day-to-day operations",[26,34,35,38],{},[29,36,37],{},"Teachers"," mark attendance, enter marks, and share notices from any device",[26,40,41,44],{},[29,42,43],{},"Parents"," get fee receipts, report cards, and school announcements without having to visit in person",[26,46,47,50],{},[29,48,49],{},"Management"," gets a clear picture of enrollment, fee dues, and school performance",[18,52,54],{"id":53},"what-it-covers","What it covers",[11,56,57,60],{},[29,58,59],{},"Admissions:"," Online application forms, document uploads, and shortlisting. No more physical files or missed follow-ups.",[11,62,63,66],{},[29,64,65],{},"Fee management:"," Define fee structures by class, collect payments, generate receipts, and track dues. Reduces the back-and-forth between parents and the accounts desk.",[11,68,69,72],{},[29,70,71],{},"Attendance:"," Daily student and staff attendance with class-wise reports. Late arrivals, absences, and monthly summaries at a glance.",[11,74,75,78],{},[29,76,77],{},"Results & gradebook:"," Exam setup, marks entry, and automatic report card generation. Teachers enter marks; the system does the rest.",[11,80,81,84],{},[29,82,83],{},"Noticeboard:"," Announcements and circulars reach parents and staff instantly, without relying on the school diary or WhatsApp groups.",[18,86,88],{"id":87},"tech-stack","Tech Stack",[90,91,92,105],"table",{},[93,94,95],"thead",{},[96,97,98,102],"tr",{},[99,100,101],"th",{},"Layer",[99,103,104],{},"Technology",[106,107,108,117,125,133,141,149],"tbody",{},[96,109,110,114],{},[111,112,113],"td",{},"Backend",[111,115,116],{},"Node.js + Express",[96,118,119,122],{},[111,120,121],{},"Frontend",[111,123,124],{},"Vue.js 3 + Vite",[96,126,127,130],{},[111,128,129],{},"Database",[111,131,132],{},"MySQL (per-school isolation)",[96,134,135,138],{},[111,136,137],{},"Cache & queues",[111,139,140],{},"Redis",[96,142,143,146],{},[111,144,145],{},"Object storage",[111,147,148],{},"MinIO",[96,150,151,154],{},[111,152,153],{},"Infrastructure",[111,155,156],{},"Kubernetes, ArgoCD, GitHub Actions",{"title":158,"searchDepth":159,"depth":159,"links":160},"",2,[161,162,163],{"id":20,"depth":159,"text":21},{"id":53,"depth":159,"text":54},{"id":87,"depth":159,"text":88},"SaaS · Education","2026-06-28","School management SaaS built for Indian schools. Admissions, fees, attendance, results, and communication in one place, without the spreadsheet chaos.",false,"md",null,{},true,"\u002Fprojects\u002Fkedarkul",{"title":6,"description":166},"live","projects\u002Fkedarkul\u002Findex",[177,178,179,140,148,180,181],"Node.js","Vue.js","MySQL","Kubernetes","ArgoCD","kedarkul.com","2volZ2p9glRbKqkJsf4xNTG1p5GcUSOa07h3vYzIEfs",{"id":185,"title":186,"body":187,"category":260,"date":261,"description":262,"draft":167,"extension":168,"github":169,"meta":263,"navigation":171,"path":264,"seo":265,"status":174,"stem":266,"tags":267,"url":269,"__hash__":270},"projects\u002Fprojects\u002Fhope-studio\u002Findex.md","Hope Studio",{"type":8,"value":188,"toc":255},[189,192,196,210,212,248,252],[11,190,191],{},"Hope Studio is a photography portfolio and booking website. The design is intentionally minimal, putting the work front and centre while making it easy for potential clients to get in touch.",[18,193,195],{"id":194},"what-it-does","What it does",[23,197,198,201,204,207],{},[26,199,200],{},"Showcases the studio's photography portfolio",[26,202,203],{},"Clean, fast-loading gallery pages",[26,205,206],{},"Contact and enquiry section for bookings",[26,208,209],{},"Fully responsive across mobile and desktop",[18,211,88],{"id":87},[90,213,214,222],{},[93,215,216],{},[96,217,218,220],{},[99,219,101],{},[99,221,104],{},[106,223,224,232,240],{},[96,225,226,229],{},[111,227,228],{},"Framework",[111,230,231],{},"Nuxt.js (Vue 3)",[96,233,234,237],{},[111,235,236],{},"Styling",[111,238,239],{},"Tailwind CSS",[96,241,242,245],{},[111,243,244],{},"Hosting",[111,246,247],{},"Static, deployed via Nginx",[18,249,251],{"id":250},"design-approach","Design approach",[11,253,254],{},"The brief was simple: get out of the way of the photos. The site uses a lot of whitespace, minimal UI chrome, and lets the photography speak for itself. Load times are a priority since large images are common.",{"title":158,"searchDepth":159,"depth":159,"links":256},[257,258,259],{"id":194,"depth":159,"text":195},{"id":87,"depth":159,"text":88},{"id":250,"depth":159,"text":251},"Web · Photography","2026-06-25","Portfolio and booking site for a photography studio. Minimal design focused on showcasing work and converting visitors into clients.",{},"\u002Fprojects\u002Fhope-studio",{"title":186,"description":262},"projects\u002Fhope-studio\u002Findex",[268,239,178],"Nuxt.js","hope.9ovind.in","1boaoIS2ion-kMV4WFW5dfh3IHBJUzZmoIB9exm2DBc",{"id":272,"title":273,"body":274,"category":514,"date":515,"description":516,"draft":167,"extension":168,"github":517,"meta":518,"navigation":171,"path":519,"seo":520,"status":174,"stem":521,"tags":522,"url":169,"__hash__":526},"projects\u002Fprojects\u002Fdotfiles\u002Findex.md","Dotfiles",{"type":8,"value":275,"toc":509},[276,279,283,316,327,331,337,342,402,408,414,434,438,446,449,498,505],[11,277,278],{},"A developer machine bootstrap toolkit. Run one command on a fresh machine and get a fully configured development environment in minutes: shell, editor, tmux, Kubernetes tools, runtimes, and GUI apps all set up automatically via Ansible.",[18,280,282],{"id":281},"quick-start","Quick Start",[284,285,289],"pre",{"className":286,"code":287,"language":288,"meta":158,"style":158},"language-bash shiki shiki-themes github-light","curl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F9ovindyadav\u002Fdotfiles\u002Fmain\u002Fbootstrap.sh | bash\n","bash",[290,291,292],"code",{"__ignoreMap":158},[293,294,297,301,305,309,313],"span",{"class":295,"line":296},"line",1,[293,298,300],{"class":299},"s7eDp","curl",[293,302,304],{"class":303},"sYu0t"," -fsSL",[293,306,308],{"class":307},"sYBdl"," https:\u002F\u002Fraw.githubusercontent.com\u002F9ovindyadav\u002Fdotfiles\u002Fmain\u002Fbootstrap.sh",[293,310,312],{"class":311},"sD7c4"," |",[293,314,315],{"class":299}," bash\n",[11,317,318,319,322,323,326],{},"The script installs ",[290,320,321],{},"git"," and ",[290,324,325],{},"ansible",", clones the repo, and runs the full playbook automatically.",[18,328,330],{"id":329},"what-gets-installed","What gets installed",[11,332,333,336],{},[29,334,335],{},"System packages:"," git, vim, tmux, fzf, jq, htop, curl, rsync, podman, build-essential, gnupg",[11,338,339],{},[29,340,341],{},"Development runtimes",[90,343,344,357],{},[93,345,346],{},[96,347,348,351,354],{},[99,349,350],{},"Runtime",[99,352,353],{},"Manager",[99,355,356],{},"Version",[106,358,359,369,380,391],{},[96,360,361,363,366],{},[111,362,177],{},[111,364,365],{},"NVM",[111,367,368],{},"24",[96,370,371,374,377],{},[111,372,373],{},"Java",[111,375,376],{},"SDKMAN",[111,378,379],{},"27",[96,381,382,385,388],{},[111,383,384],{},"Go",[111,386,387],{},"Direct binary",[111,389,390],{},"1.26.4",[96,392,393,396,399],{},[111,394,395],{},"Docker",[111,397,398],{},"Official script",[111,400,401],{},"Latest",[11,403,404,407],{},[29,405,406],{},"Kubernetes tools:"," kubectl, helm, k9s",[11,409,410,413],{},[29,411,412],{},"GUI apps:"," Brave, Bitwarden, Zed, Sublime Merge, VLC",[11,415,416,419,420,423,424,423,427,423,430,433],{},[29,417,418],{},"Dotfiles:"," ",[290,421,422],{},".bashrc",", ",[290,425,426],{},".vimrc",[290,428,429],{},".tmux.conf",[290,431,432],{},".gitconfig",", all symlinked via GNU Stow",[18,435,437],{"id":436},"structure","Structure",[284,439,444],{"className":440,"code":442,"language":443},[441],"language-text","ansible\u002F\n└── roles\u002F\n    ├── packages\u002F   # apt packages\n    ├── dotfiles\u002F   # stow symlinks\n    ├── tools\u002F      # runtimes + k8s tools\n    └── apps\u002F       # GUI applications\n","text",[290,445,442],{"__ignoreMap":158},[11,447,448],{},"Run selectively with tags:",[284,450,452],{"className":286,"code":451,"language":288,"meta":158,"style":158},"# Fast setup — packages and dotfiles only\nansible-playbook ansible\u002Fplaybook.yml --tags packages,dotfiles\n\n# Kubernetes tools only\nansible-playbook ansible\u002Fplaybook.yml --tags tools\n",[290,453,454,460,474,480,486],{"__ignoreMap":158},[293,455,456],{"class":295,"line":296},[293,457,459],{"class":458},"sAwPA","# Fast setup — packages and dotfiles only\n",[293,461,462,465,468,471],{"class":295,"line":159},[293,463,464],{"class":299},"ansible-playbook",[293,466,467],{"class":307}," ansible\u002Fplaybook.yml",[293,469,470],{"class":303}," --tags",[293,472,473],{"class":307}," packages,dotfiles\n",[293,475,477],{"class":295,"line":476},3,[293,478,479],{"emptyLinePlaceholder":171},"\n",[293,481,483],{"class":295,"line":482},4,[293,484,485],{"class":458},"# Kubernetes tools only\n",[293,487,489,491,493,495],{"class":295,"line":488},5,[293,490,464],{"class":299},[293,492,467],{"class":307},[293,494,470],{"class":303},[293,496,497],{"class":307}," tools\n",[11,499,500,501,504],{},"Versions are centralised in ",[290,502,503],{},"ansible\u002Froles\u002Ftools\u002Fvars\u002Fmain.yml",". Change one file to standardise a runtime version across the whole team.",[506,507,508],"style",{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":158,"searchDepth":159,"depth":159,"links":510},[511,512,513],{"id":281,"depth":159,"text":282},{"id":329,"depth":159,"text":330},{"id":436,"depth":159,"text":437},"DevOps · Open Source","2026-06-21","One command on a fresh machine gets you a fully configured development environment. Shell, editor, tmux, Kubernetes tools, runtimes, and apps, all set up automatically via Ansible.","https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Fdotfiles",{},"\u002Fprojects\u002Fdotfiles",{"title":273,"description":516},"projects\u002Fdotfiles\u002Findex",[523,524,525,180,395],"Ansible","Bash","Linux","0p1Ln9vSRR6BhMNf7_85EGU1Be8bREA9_yFguDvQIfk",{"id":528,"title":529,"body":530,"category":612,"date":613,"description":614,"draft":167,"extension":168,"github":169,"meta":615,"navigation":171,"path":616,"seo":617,"status":174,"stem":618,"tags":619,"url":621,"__hash__":622},"projects\u002Fprojects\u002Fbrownie-point\u002Findex.md","Brownie Point",{"type":8,"value":531,"toc":608},[532,535,537,554,556],[11,533,534],{},"Brownie Point is a loyalty reward card system built for a dessert chain. Customers earn points with each purchase and redeem them for discounts. Staff manage points issuance and redemption from a web dashboard.",[18,536,195],{"id":194},[23,538,539,542,545,548,551],{},[26,540,541],{},"Loyalty points system for customers",[26,543,544],{},"Staff dashboard for counter staff to issue and redeem points",[26,546,547],{},"Admin panel for managing rewards, tiers, and customer data",[26,549,550],{},"MinIO for storing receipts and related files",[26,552,553],{},"Runs on Kubernetes",[18,555,88],{"id":87},[90,557,558,566],{},[93,559,560],{},[96,561,562,564],{},[99,563,101],{},[99,565,104],{},[106,567,568,575,582,588,595,602],{},[96,569,570,572],{},[111,571,121],{},[111,573,574],{},"Vue.js 3",[96,576,577,579],{},[111,578,113],{},[111,580,581],{},"Laravel (PHP)",[96,583,584,586],{},[111,585,129],{},[111,587,179],{},[96,589,590,592],{},[111,591,145],{},[111,593,594],{},"MinIO (S3-compatible)",[96,596,597,600],{},[111,598,599],{},"Orchestration",[111,601,180],{},[96,603,604,606],{},[111,605,236],{},[111,607,239],{},{"title":158,"searchDepth":159,"depth":159,"links":609},[610,611],{"id":194,"depth":159,"text":195},{"id":87,"depth":159,"text":88},"Loyalty Platform","2026-06-20","Loyalty reward card system for a dessert chain. Vue.js frontend, Laravel backend, MySQL database, MinIO for storage, all running on Kubernetes.",{},"\u002Fprojects\u002Fbrownie-point",{"title":529,"description":614},"projects\u002Fbrownie-point\u002Findex",[178,620,179,148,180],"Laravel","brownie.9ovind.in","hIeLxwjooR7eIqZ-4aWHx6RCz-PMYmpjNw4537xjgRs",{"id":624,"title":625,"body":626,"category":683,"date":613,"description":684,"draft":167,"extension":168,"github":169,"meta":685,"navigation":171,"path":686,"seo":687,"status":174,"stem":688,"tags":689,"url":690,"__hash__":691},"projects\u002Fprojects\u002Fshaurya-academy\u002Findex.md","Shaurya Academy",{"type":8,"value":627,"toc":679},[628,631,633,647,649],[11,629,630],{},"Shaurya Academy is the website for a local coaching centre. The goal was simple: look professional, load fast, and convert visitors into enquiries.",[18,632,195],{"id":194},[23,634,635,638,641,644],{},[26,636,637],{},"Presents courses, faculty, and results",[26,639,640],{},"Contact and enquiry form for prospective students",[26,642,643],{},"Mobile-first, fast-loading design",[26,645,646],{},"SEO-optimised pages for local search visibility",[18,648,88],{"id":87},[90,650,651,659],{},[93,652,653],{},[96,654,655,657],{},[99,656,101],{},[99,658,104],{},[106,660,661,667,673],{},[96,662,663,665],{},[111,664,228],{},[111,666,231],{},[96,668,669,671],{},[111,670,236],{},[111,672,239],{},[96,674,675,677],{},[111,676,244],{},[111,678,247],{},{"title":158,"searchDepth":159,"depth":159,"links":680},[681,682],{"id":194,"depth":159,"text":195},{"id":87,"depth":159,"text":88},"Web · Education","Website for a coaching center. Clean, fast, and built to convert prospective students into enrolments.",{},"\u002Fprojects\u002Fshaurya-academy",{"title":625,"description":684},"projects\u002Fshaurya-academy\u002Findex",[268,239],"academy.9ovind.in","NjC7uILmsr5-SKKr4ph8WTvKEFN1zC5y9_SUauI0XzI",{"id":693,"title":694,"body":695,"category":851,"date":852,"description":853,"draft":167,"extension":168,"github":854,"meta":855,"navigation":171,"path":856,"seo":857,"status":174,"stem":858,"tags":859,"url":860,"__hash__":861},"projects\u002Fprojects\u002Fcodebhejo\u002Findex.md","CodeBhejo",{"type":8,"value":696,"toc":846},[697,700,704,730,732,786,790,840,843],[11,698,699],{},"CodeBhejo is an open-source code sharing and collaboration tool for developers. Instantly create and share code snippets through a web editor, or transfer files peer-to-peer directly from the terminal.",[18,701,703],{"id":702},"features","Features",[23,705,706,712,718,724],{},[26,707,708,711],{},[29,709,710],{},"Monaco Editor:"," The same editor that powers VS Code, with syntax highlighting across all major languages",[26,713,714,717],{},[29,715,716],{},"Passwordless auth:"," Email-based magic link login via AWS SES, no password required",[26,719,720,723],{},[29,721,722],{},"P2P file transfer:"," A Go CLI tool that transfers files directly between machines over WebRTC. The backend acts only as a signaling server, so file data never touches the server",[26,725,726,729],{},[29,727,728],{},"S3-backed storage:"," File content stored on S3 (or any S3-compatible provider), metadata in MySQL",[18,731,88],{"id":87},[90,733,734,742],{},[93,735,736],{},[96,737,738,740],{},[99,739,101],{},[99,741,104],{},[106,743,744,751,758,764,772,778],{},[96,745,746,748],{},[111,747,121],{},[111,749,750],{},"Vue.js 3, Vite, Pinia, Monaco Editor",[96,752,753,755],{},[111,754,113],{},[111,756,757],{},"Node.js, Express",[96,759,760,762],{},[111,761,129],{},[111,763,179],{},[96,765,766,769],{},[111,767,768],{},"Storage",[111,770,771],{},"AWS S3",[96,773,774,776],{},[111,775,599],{},[111,777,180],{},[96,779,780,783],{},[111,781,782],{},"Email",[111,784,785],{},"AWS SES (magic link login)",[18,787,789],{"id":788},"cli-usage","CLI Usage",[284,791,793],{"className":286,"code":792,"language":288,"meta":158,"style":158},"# Send a file\ncodebhejo send .\u002Fmyfile.zip\n\n# Receive a file\ncodebhejo receive \u003Ccode>\n",[290,794,795,800,811,815,820],{"__ignoreMap":158},[293,796,797],{"class":295,"line":296},[293,798,799],{"class":458},"# Send a file\n",[293,801,802,805,808],{"class":295,"line":159},[293,803,804],{"class":299},"codebhejo",[293,806,807],{"class":307}," send",[293,809,810],{"class":307}," .\u002Fmyfile.zip\n",[293,812,813],{"class":295,"line":476},[293,814,479],{"emptyLinePlaceholder":171},[293,816,817],{"class":295,"line":482},[293,818,819],{"class":458},"# Receive a file\n",[293,821,822,824,827,830,833,837],{"class":295,"line":488},[293,823,804],{"class":299},[293,825,826],{"class":307}," receive",[293,828,829],{"class":311}," \u003C",[293,831,832],{"class":307},"cod",[293,834,836],{"class":835},"sgsFI","e",[293,838,839],{"class":311},">\n",[11,841,842],{},"The CLI uses WebRTC for the actual transfer. The backend only handles signaling, so file bytes never pass through the server.",[506,844,845],{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":158,"searchDepth":159,"depth":159,"links":847},[848,849,850],{"id":702,"depth":159,"text":703},{"id":87,"depth":159,"text":88},{"id":788,"depth":159,"text":789},"Developer Tool · Open Source","2026-04-09","Open-source code sharing tool with a Monaco editor, passwordless auth, and a Go CLI for peer-to-peer file transfer over WebRTC. File data never touches the server.","https:\u002F\u002Fgithub.com\u002Fcodebhejo\u002Fcodebhejo",{},"\u002Fprojects\u002Fcodebhejo",{"title":694,"description":853},"projects\u002Fcodebhejo\u002Findex",[178,177,179,771,180],"codebhejo.in","qDMRdmqnV0y3FROXR1wjMeeY_cxzWtNo78drdfH9hCY",{"id":863,"title":864,"body":865,"category":1067,"date":1068,"description":1069,"draft":167,"extension":168,"github":169,"meta":1070,"navigation":171,"path":1071,"seo":1072,"status":1073,"stem":1074,"tags":1075,"url":169,"__hash__":1079},"projects\u002Fprojects\u002Fvoicebot\u002Findex.md","VoiceBot",{"type":8,"value":866,"toc":1060},[867,870,872,878,884,890,892,985,989,1040,1043,1047,1054,1057],[11,868,869],{},"VoiceBot is a multi-tenant platform for deploying AI voice agents. Businesses sign up, create an organisation, and configure agents. Each agent handles inbound calls, runs outbound campaigns, and can be embedded as a web widget.",[18,871,195],{"id":194},[11,873,874,877],{},[29,875,876],{},"Inbound calls:"," Agent picks up, transcribes speech in real time, generates a response via LLM, and speaks it back. Full transcript and recording saved automatically.",[11,879,880,883],{},[29,881,882],{},"Outbound campaigns:"," Upload a CSV of contacts, select an agent, set a schedule. The platform dials each number automatically, runs the conversation, and retries failed calls.",[11,885,886,889],{},[29,887,888],{},"Web voice demo:"," Embeddable widget powered by AudioWorklet + WebSocket. Visitors can try the agent directly in the browser.",[18,891,88],{"id":87},[90,893,894,902],{},[93,895,896],{},[96,897,898,900],{},[99,899,101],{},[99,901,104],{},[106,903,904,910,917,925,933,941,949,956,962,970,977],{},[96,905,906,908],{},[111,907,113],{},[111,909,116],{},[96,911,912,914],{},[111,913,121],{},[111,915,916],{},"Vue.js 3 (dashboard + landing page)",[96,918,919,922],{},[111,920,921],{},"Telephony",[111,923,924],{},"Plivo (primary) + Twilio",[96,926,927,930],{},[111,928,929],{},"STT",[111,931,932],{},"Deepgram (multi-language, low latency)",[96,934,935,938],{},[111,936,937],{},"LLM",[111,939,940],{},"Gemini · OpenAI · Groq (provider-swappable)",[96,942,943,946],{},[111,944,945],{},"TTS",[111,947,948],{},"Sarvam AI (Indian language synthesis)",[96,950,951,953],{},[111,952,129],{},[111,954,955],{},"MySQL + Prisma ORM",[96,957,958,960],{},[111,959,145],{},[111,961,148],{},[96,963,964,967],{},[111,965,966],{},"Queue",[111,968,969],{},"BullMQ + Redis",[96,971,972,974],{},[111,973,599],{},[111,975,976],{},"Kubernetes (k3s + Traefik)",[96,978,979,982],{},[111,980,981],{},"CI\u002FCD",[111,983,984],{},"GitHub Actions + GHCR",[18,986,988],{"id":987},"language-support","Language support",[90,990,991,1001],{},[93,992,993],{},[96,994,995,998],{},[99,996,997],{},"Language",[99,999,1000],{},"Status",[106,1002,1003,1011,1018,1025,1032],{},[96,1004,1005,1008],{},[111,1006,1007],{},"English",[111,1009,1010],{},"✅",[96,1012,1013,1016],{},[111,1014,1015],{},"Hindi",[111,1017,1010],{},[96,1019,1020,1023],{},[111,1021,1022],{},"Marathi",[111,1024,1010],{},[96,1026,1027,1030],{},[111,1028,1029],{},"Gujarati",[111,1031,1010],{},[96,1033,1034,1037],{},[111,1035,1036],{},"More",[111,1038,1039],{},"Planned",[11,1041,1042],{},"Language is configured per agent. No code changes required to add a new language once the AI provider supports it.",[18,1044,1046],{"id":1045},"provider-abstraction","Provider abstraction",[11,1048,1049,1050,1053],{},"The AI provider is fully swappable via a single env var (",[290,1051,1052],{},"VOICE_MODEL","). Switching Gemini ↔ OpenAI requires zero code changes. Same pattern for telephony: the Twilio bridge is already built alongside Plivo.",[18,1055,1000],{"id":1056},"status",[11,1058,1059],{},"Core platform is working: inbound calls, outbound campaigns, STT\u002FTTS, and the web widget. Productionisation, billing integration, and multi-language intent handling are ongoing.",{"title":158,"searchDepth":159,"depth":159,"links":1061},[1062,1063,1064,1065,1066],{"id":194,"depth":159,"text":195},{"id":87,"depth":159,"text":88},{"id":987,"depth":159,"text":988},{"id":1045,"depth":159,"text":1046},{"id":1056,"depth":159,"text":1000},"AI · Telephony","2026-03-01","Multi-tenant voice AI platform. Businesses deploy AI agents for inbound\u002Foutbound phone calls and web voice demos, with real-time STT\u002FTTS in English and Indian languages.",{},"\u002Fprojects\u002Fvoicebot",{"title":864,"description":1069},"ongoing","projects\u002Fvoicebot\u002Findex",[177,178,1076,1077,1078,179,140,180],"Plivo","Deepgram","Sarvam AI","Uc8M77TP5WNBW5wwk5NlJeR1ukV8BGzlHuNB-dhhsKw",{"id":1081,"title":1082,"body":1083,"category":1299,"date":1300,"description":1301,"draft":167,"extension":168,"github":1302,"meta":1303,"navigation":171,"path":1304,"seo":1305,"status":174,"stem":1306,"tags":1307,"url":169,"__hash__":1308},"projects\u002Fprojects\u002Flaravel-cicd\u002Findex.md","Laravel CI\u002FCD with GitOps",{"type":8,"value":1084,"toc":1293},[1085,1088,1092,1167,1171,1181,1193,1198,1212,1216,1222,1226,1283,1290],[11,1086,1087],{},"A step-by-step reference implementation of a full CI\u002FCD pipeline for a Laravel application. GitLab CI builds and pushes the Docker image on every commit. ArgoCD monitors the repo and syncs changes to a k3s cluster on Hetzner automatically.",[18,1089,1091],{"id":1090},"stack","Stack",[90,1093,1094,1103],{},[93,1095,1096],{},[96,1097,1098,1101],{},[99,1099,1100],{},"Component",[99,1102,104],{},[106,1104,1105,1113,1120,1128,1136,1143,1151,1159],{},[96,1106,1107,1110],{},[111,1108,1109],{},"App",[111,1111,1112],{},"Laravel 12",[96,1114,1115,1118],{},[111,1116,1117],{},"Containerisation",[111,1119,395],{},[96,1121,1122,1125],{},[111,1123,1124],{},"Registry",[111,1126,1127],{},"GitLab Container Registry",[96,1129,1130,1133],{},[111,1131,1132],{},"Cluster",[111,1134,1135],{},"k3s on Hetzner (CX22, ~$5\u002Fmo)",[96,1137,1138,1141],{},[111,1139,1140],{},"GitOps",[111,1142,181],{},[96,1144,1145,1148],{},[111,1146,1147],{},"CI",[111,1149,1150],{},"GitLab CI",[96,1152,1153,1156],{},[111,1154,1155],{},"Ingress",[111,1157,1158],{},"Traefik (Gateway API)",[96,1160,1161,1164],{},[111,1162,1163],{},"DNS & TLS",[111,1165,1166],{},"Cloudflare + Let's Encrypt wildcard cert",[18,1168,1170],{"id":1169},"pipeline","Pipeline",[11,1172,1173,1176,1177,1180],{},[29,1174,1175],{},"Build stage:"," On every push to ",[290,1178,1179],{},"main",":",[1182,1183,1184,1190],"ol",{},[26,1185,1186,1187],{},"Build the Docker image from ",[290,1188,1189],{},"Dockerfile",[26,1191,1192],{},"Push to GitLab Container Registry",[11,1194,1195,1180],{},[29,1196,1197],{},"Deploy stage",[1182,1199,1200,1206,1209],{},[26,1201,1202,1203],{},"Update the image tag in ",[290,1204,1205],{},"kubernetes\u002Fapps\u002Flci\u002Fvalues.yaml",[26,1207,1208],{},"Commit and push the change back to GitLab",[26,1210,1211],{},"ArgoCD detects the config change and rolls out the new image to k3s",[18,1213,1215],{"id":1214},"repository-structure","Repository structure",[284,1217,1220],{"className":1218,"code":1219,"language":443},[441],"laravel-app\u002F     # Application code\ndocker\u002F          # Dockerfile, compose, nginx, entrypoint\nkubernetes\u002F\n├── apps\u002F        # ArgoCD-managed Helm releases\n├── argocd\u002F      # ArgoCD installation + App of Apps config\n└── proxy\u002F       # Traefik Gateway API config + TLS certs\n.gitlab-ci.yml   # Full CI\u002FCD pipeline definition\n",[290,1221,1219],{"__ignoreMap":158},[18,1223,1225],{"id":1224},"running-locally","Running locally",[284,1227,1229],{"className":286,"code":1228,"language":288,"meta":158,"style":158},"git clone https:\u002F\u002Fgitlab.com\u002F9ovindyadav\u002Flaravel-cicd.git\ncd laravel-cicd\ncp laravel-app\u002F.env.example laravel-app\u002F.env\ndocker compose -f docker\u002Fcompose.yaml --env-file laravel-app\u002F.env up\n",[290,1230,1231,1241,1249,1260],{"__ignoreMap":158},[293,1232,1233,1235,1238],{"class":295,"line":296},[293,1234,321],{"class":299},[293,1236,1237],{"class":307}," clone",[293,1239,1240],{"class":307}," https:\u002F\u002Fgitlab.com\u002F9ovindyadav\u002Flaravel-cicd.git\n",[293,1242,1243,1246],{"class":295,"line":159},[293,1244,1245],{"class":303},"cd",[293,1247,1248],{"class":307}," laravel-cicd\n",[293,1250,1251,1254,1257],{"class":295,"line":476},[293,1252,1253],{"class":299},"cp",[293,1255,1256],{"class":307}," laravel-app\u002F.env.example",[293,1258,1259],{"class":307}," laravel-app\u002F.env\n",[293,1261,1262,1265,1268,1271,1274,1277,1280],{"class":295,"line":482},[293,1263,1264],{"class":299},"docker",[293,1266,1267],{"class":307}," compose",[293,1269,1270],{"class":303}," -f",[293,1272,1273],{"class":307}," docker\u002Fcompose.yaml",[293,1275,1276],{"class":303}," --env-file",[293,1278,1279],{"class":307}," laravel-app\u002F.env",[293,1281,1282],{"class":307}," up\n",[11,1284,1285,1286,1289],{},"Open ",[290,1287,1288],{},"http:\u002F\u002Flocalhost:9000",".",[506,1291,1292],{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":158,"searchDepth":159,"depth":159,"links":1294},[1295,1296,1297,1298],{"id":1090,"depth":159,"text":1091},{"id":1169,"depth":159,"text":1170},{"id":1214,"depth":159,"text":1215},{"id":1224,"depth":159,"text":1225},"DevOps · Cloud","2025-09-06","Full CI\u002FCD pipeline for a Laravel application on Kubernetes using GitLab CI for automated builds and ArgoCD for GitOps-based continuous deployment on a Hetzner VPS.","https:\u002F\u002Fgitlab.com\u002F9ovindyadav\u002Flaravel-cicd",{},"\u002Fprojects\u002Flaravel-cicd",{"title":1082,"description":1301},"projects\u002Flaravel-cicd\u002Findex",[620,395,180,981,1140,181,1150],"EL4pm_t8swUofIaYW23SbxsIhNGAzg6iynTqQobMNvQ",{"id":1310,"title":1311,"body":1312,"category":1652,"date":1653,"description":1654,"draft":167,"extension":168,"github":1655,"meta":1656,"navigation":171,"path":1657,"seo":1658,"status":174,"stem":1659,"tags":1660,"url":169,"__hash__":1665},"projects\u002Fprojects\u002Finvoice-generator\u002Findex.md","Invoice Generator",{"type":8,"value":1313,"toc":1647},[1314,1317,1321,1335,1339,1383,1387,1390,1634,1644],[11,1315,1316],{},"An automated invoice generation tool. It pulls client data from a Google Sheet, generates a PDF invoice for each row using a custom template, and emails them out via SMTP. All triggered with a single command.",[18,1318,1320],{"id":1319},"how-it-works","How it works",[1182,1322,1323,1326,1329,1332],{},[26,1324,1325],{},"Google Sheets acts as the data source (via Apps Script web app)",[26,1327,1328],{},"Node.js script fetches the JSON response from the sheet",[26,1330,1331],{},"Generates a PDF invoice per client using your template",[26,1333,1334],{},"Sends each invoice by email via SMTP",[18,1336,1338],{"id":1337},"setup","Setup",[284,1340,1342],{"className":286,"code":1341,"language":288,"meta":158,"style":158},"git clone https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002FinvoiceGenerator.git\ncd invoiceGenerator\ncp .env.example .env\n# Fill in SMTP and Google Sheet credentials\nnode app.js\n",[290,1343,1344,1353,1360,1370,1375],{"__ignoreMap":158},[293,1345,1346,1348,1350],{"class":295,"line":296},[293,1347,321],{"class":299},[293,1349,1237],{"class":307},[293,1351,1352],{"class":307}," https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002FinvoiceGenerator.git\n",[293,1354,1355,1357],{"class":295,"line":159},[293,1356,1245],{"class":303},[293,1358,1359],{"class":307}," invoiceGenerator\n",[293,1361,1362,1364,1367],{"class":295,"line":476},[293,1363,1253],{"class":299},[293,1365,1366],{"class":307}," .env.example",[293,1368,1369],{"class":307}," .env\n",[293,1371,1372],{"class":295,"line":482},[293,1373,1374],{"class":458},"# Fill in SMTP and Google Sheet credentials\n",[293,1376,1377,1380],{"class":295,"line":488},[293,1378,1379],{"class":299},"node",[293,1381,1382],{"class":307}," app.js\n",[18,1384,1386],{"id":1385},"google-sheets-as-an-api","Google Sheets as an API",[11,1388,1389],{},"The sheet is exposed as a JSON API using Google Apps Script. Add this to your Apps Script project:",[284,1391,1395],{"className":1392,"code":1393,"language":1394,"meta":158,"style":158},"language-javascript shiki shiki-themes github-light","function doGet(req) {\n  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('YourSheet');\n  var values = sheet.getDataRange().getValues();\n  var keys = values[0];\n  var output = values.slice(1).map(row => {\n    var obj = {};\n    keys.forEach((k, i) => obj[k] = row[i]);\n    return obj;\n  });\n  return ContentService.createTextOutput(JSON.stringify({ data: output }))\n    .setMimeType(ContentService.MimeType.JSON);\n}\n","javascript",[290,1396,1397,1415,1446,1469,1487,1524,1538,1572,1581,1587,1612,1628],{"__ignoreMap":158},[293,1398,1399,1402,1405,1408,1412],{"class":295,"line":296},[293,1400,1401],{"class":311},"function",[293,1403,1404],{"class":299}," doGet",[293,1406,1407],{"class":835},"(",[293,1409,1411],{"class":1410},"sqxcx","req",[293,1413,1414],{"class":835},") {\n",[293,1416,1417,1420,1423,1426,1429,1432,1435,1438,1440,1443],{"class":295,"line":159},[293,1418,1419],{"class":311},"  var",[293,1421,1422],{"class":835}," sheet ",[293,1424,1425],{"class":311},"=",[293,1427,1428],{"class":835}," SpreadsheetApp.",[293,1430,1431],{"class":299},"getActiveSpreadsheet",[293,1433,1434],{"class":835},"().",[293,1436,1437],{"class":299},"getSheetByName",[293,1439,1407],{"class":835},[293,1441,1442],{"class":307},"'YourSheet'",[293,1444,1445],{"class":835},");\n",[293,1447,1448,1450,1453,1455,1458,1461,1463,1466],{"class":295,"line":476},[293,1449,1419],{"class":311},[293,1451,1452],{"class":835}," values ",[293,1454,1425],{"class":311},[293,1456,1457],{"class":835}," sheet.",[293,1459,1460],{"class":299},"getDataRange",[293,1462,1434],{"class":835},[293,1464,1465],{"class":299},"getValues",[293,1467,1468],{"class":835},"();\n",[293,1470,1471,1473,1476,1478,1481,1484],{"class":295,"line":482},[293,1472,1419],{"class":311},[293,1474,1475],{"class":835}," keys ",[293,1477,1425],{"class":311},[293,1479,1480],{"class":835}," values[",[293,1482,1483],{"class":303},"0",[293,1485,1486],{"class":835},"];\n",[293,1488,1489,1491,1494,1496,1499,1502,1504,1507,1510,1513,1515,1518,1521],{"class":295,"line":488},[293,1490,1419],{"class":311},[293,1492,1493],{"class":835}," output ",[293,1495,1425],{"class":311},[293,1497,1498],{"class":835}," values.",[293,1500,1501],{"class":299},"slice",[293,1503,1407],{"class":835},[293,1505,1506],{"class":303},"1",[293,1508,1509],{"class":835},").",[293,1511,1512],{"class":299},"map",[293,1514,1407],{"class":835},[293,1516,1517],{"class":1410},"row",[293,1519,1520],{"class":311}," =>",[293,1522,1523],{"class":835}," {\n",[293,1525,1527,1530,1533,1535],{"class":295,"line":1526},6,[293,1528,1529],{"class":311},"    var",[293,1531,1532],{"class":835}," obj ",[293,1534,1425],{"class":311},[293,1536,1537],{"class":835}," {};\n",[293,1539,1541,1544,1547,1550,1553,1555,1558,1561,1564,1567,1569],{"class":295,"line":1540},7,[293,1542,1543],{"class":835},"    keys.",[293,1545,1546],{"class":299},"forEach",[293,1548,1549],{"class":835},"((",[293,1551,1552],{"class":1410},"k",[293,1554,423],{"class":835},[293,1556,1557],{"class":1410},"i",[293,1559,1560],{"class":835},") ",[293,1562,1563],{"class":311},"=>",[293,1565,1566],{"class":835}," obj[k] ",[293,1568,1425],{"class":311},[293,1570,1571],{"class":835}," row[i]);\n",[293,1573,1575,1578],{"class":295,"line":1574},8,[293,1576,1577],{"class":311},"    return",[293,1579,1580],{"class":835}," obj;\n",[293,1582,1584],{"class":295,"line":1583},9,[293,1585,1586],{"class":835},"  });\n",[293,1588,1590,1593,1596,1599,1601,1604,1606,1609],{"class":295,"line":1589},10,[293,1591,1592],{"class":311},"  return",[293,1594,1595],{"class":835}," ContentService.",[293,1597,1598],{"class":299},"createTextOutput",[293,1600,1407],{"class":835},[293,1602,1603],{"class":303},"JSON",[293,1605,1289],{"class":835},[293,1607,1608],{"class":299},"stringify",[293,1610,1611],{"class":835},"({ data: output }))\n",[293,1613,1615,1618,1621,1624,1626],{"class":295,"line":1614},11,[293,1616,1617],{"class":835},"    .",[293,1619,1620],{"class":299},"setMimeType",[293,1622,1623],{"class":835},"(ContentService.MimeType.",[293,1625,1603],{"class":303},[293,1627,1445],{"class":835},[293,1629,1631],{"class":295,"line":1630},12,[293,1632,1633],{"class":835},"}\n",[11,1635,1636,1637,1640,1641,1289],{},"Deploy as a web app with access set to ",[29,1638,1639],{},"Anyone",", then use the script URL in your ",[290,1642,1643],{},".env",[506,1645,1646],{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}",{"title":158,"searchDepth":159,"depth":159,"links":1648},[1649,1650,1651],{"id":1319,"depth":159,"text":1320},{"id":1337,"depth":159,"text":1338},{"id":1385,"depth":159,"text":1386},"Automation · Backend","2024-03-25","Automated invoice generator that pulls client data from Google Sheets and generates PDF invoices via a Node.js script, triggered through Google Apps Script.","https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002FinvoiceGenerator",{},"\u002Fprojects\u002Finvoice-generator",{"title":1311,"description":1654},"projects\u002Finvoice-generator\u002Findex",[177,1661,1662,1663,1664],"Google Sheets","PDF","SMTP","Automation","M0UB0L5RS5kk_c2wxXMt0sfU8mw-OcTd92KzbzDQydg",{"id":1667,"title":1668,"body":1669,"category":1909,"date":1910,"description":1911,"draft":167,"extension":168,"github":1912,"meta":1913,"navigation":171,"path":1914,"seo":1915,"status":174,"stem":1916,"tags":1917,"url":1919,"__hash__":1920},"projects\u002Fprojects\u002Ffood-order-php\u002Findex.md","Food Order System",{"type":8,"value":1670,"toc":1903},[1671,1674,1678,1683,1694,1699,1710,1715,1726,1728,1776,1778,1834,1840,1844,1900],[11,1672,1673],{},"A web-based restaurant order management system built for internal staff use. It streamlines order processing, menu management, and reporting across three roles: counter staff, kitchen staff, and admin.",[18,1675,1677],{"id":1676},"roles","Roles",[11,1679,1680],{},[29,1681,1682],{},"Counter staff",[23,1684,1685,1688,1691],{},[26,1686,1687],{},"Create and manage customer orders",[26,1689,1690],{},"Track payment status",[26,1692,1693],{},"View all active orders",[11,1695,1696],{},[29,1697,1698],{},"Kitchen staff",[23,1700,1701,1704,1707],{},[26,1702,1703],{},"View incoming orders in real time",[26,1705,1706],{},"Update order status (preparing \u002F ready)",[26,1708,1709],{},"Toggle menu item availability",[11,1711,1712],{},[29,1713,1714],{},"Admin",[23,1716,1717,1720,1723],{},[26,1718,1719],{},"Full menu management (add, edit, delete items)",[26,1721,1722],{},"User management",[26,1724,1725],{},"Order history and statistics",[18,1727,88],{"id":87},[90,1729,1730,1738],{},[93,1731,1732],{},[96,1733,1734,1736],{},[99,1735,101],{},[99,1737,104],{},[106,1739,1740,1747,1753,1760,1768],{},[96,1741,1742,1744],{},[111,1743,113],{},[111,1745,1746],{},"PHP",[96,1748,1749,1751],{},[111,1750,129],{},[111,1752,179],{},[96,1754,1755,1757],{},[111,1756,121],{},[111,1758,1759],{},"jQuery, HTML, CSS",[96,1761,1762,1765],{},[111,1763,1764],{},"Web server",[111,1766,1767],{},"Nginx",[96,1769,1770,1773],{},[111,1771,1772],{},"Deployment",[111,1774,1775],{},"Docker + Docker Compose",[18,1777,1225],{"id":1224},[284,1779,1781],{"className":286,"code":1780,"language":288,"meta":158,"style":158},"git clone https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ffood-order-php\ncd food-order-php\ncp .env.example .env\n# Update .env with your MySQL config\ncd docker\ndocker compose up -d --build\n",[290,1782,1783,1792,1799,1807,1812,1819],{"__ignoreMap":158},[293,1784,1785,1787,1789],{"class":295,"line":296},[293,1786,321],{"class":299},[293,1788,1237],{"class":307},[293,1790,1791],{"class":307}," https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ffood-order-php\n",[293,1793,1794,1796],{"class":295,"line":159},[293,1795,1245],{"class":303},[293,1797,1798],{"class":307}," food-order-php\n",[293,1800,1801,1803,1805],{"class":295,"line":476},[293,1802,1253],{"class":299},[293,1804,1366],{"class":307},[293,1806,1369],{"class":307},[293,1808,1809],{"class":295,"line":482},[293,1810,1811],{"class":458},"# Update .env with your MySQL config\n",[293,1813,1814,1816],{"class":295,"line":488},[293,1815,1245],{"class":303},[293,1817,1818],{"class":307}," docker\n",[293,1820,1821,1823,1825,1828,1831],{"class":295,"line":1526},[293,1822,1264],{"class":299},[293,1824,1267],{"class":307},[293,1826,1827],{"class":307}," up",[293,1829,1830],{"class":303}," -d",[293,1832,1833],{"class":303}," --build\n",[11,1835,1285,1836,1839],{},[290,1837,1838],{},"http:\u002F\u002Flocalhost:8000"," in your browser.",[18,1841,1843],{"id":1842},"test-credentials","Test credentials",[90,1845,1846,1858],{},[93,1847,1848],{},[96,1849,1850,1853,1855],{},[99,1851,1852],{},"Role",[99,1854,782],{},[99,1856,1857],{},"Password",[106,1859,1860,1875,1888],{},[96,1861,1862,1865,1872],{},[111,1863,1864],{},"Counter",[111,1866,1867],{},[1868,1869,1871],"a",{"href":1870},"mailto:counter@gmail.com","counter@gmail.com",[111,1873,1874],{},"admin",[96,1876,1877,1880,1886],{},[111,1878,1879],{},"Kitchen",[111,1881,1882],{},[1868,1883,1885],{"href":1884},"mailto:kitchen@gmail.com","kitchen@gmail.com",[111,1887,1874],{},[96,1889,1890,1892,1898],{},[111,1891,1714],{},[111,1893,1894],{},[1868,1895,1897],{"href":1896},"mailto:admin@gmail.com","admin@gmail.com",[111,1899,1874],{},[506,1901,1902],{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":158,"searchDepth":159,"depth":159,"links":1904},[1905,1906,1907,1908],{"id":1676,"depth":159,"text":1677},{"id":87,"depth":159,"text":88},{"id":1224,"depth":159,"text":1225},{"id":1842,"depth":159,"text":1843},"Web · Backend","2023-12-05","A PHP-based restaurant order management system for counter staff, kitchen, and admins. Containerised with Docker and Nginx, with role-based access and menu management.","https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ffood-order-php",{},"\u002Fprojects\u002Ffood-order-php",{"title":1668,"description":1911},"projects\u002Ffood-order-php\u002Findex",[1746,179,395,1767,1918],"jQuery","fop.9ovind.in","5Zkfk9v5ApNEvgtlNZaNQek0LPz0DcDlV3fIkhdnk7o",{"id":1922,"title":1923,"body":1924,"category":2021,"date":2022,"description":2023,"draft":167,"extension":168,"github":2024,"meta":2025,"navigation":171,"path":2026,"seo":2027,"status":174,"stem":2028,"tags":2029,"url":2033,"__hash__":2034},"projects\u002Fprojects\u002Ftrekworld\u002Findex.md","Trekworld",{"type":8,"value":1925,"toc":2016},[1926,1929,1931,1942,1944,1986,1988,2014],[11,1927,1928],{},"Trekworld is a static website for a trekking community. Built early in my journey with plain HTML, CSS, and JavaScript, no frameworks.",[18,1930,195],{"id":194},[23,1932,1933,1936,1939],{},[26,1934,1935],{},"Showcases trekking routes and destinations",[26,1937,1938],{},"Community-facing landing page",[26,1940,1941],{},"Fully static, no backend required",[18,1943,88],{"id":87},[90,1945,1946,1954],{},[93,1947,1948],{},[96,1949,1950,1952],{},[99,1951,101],{},[99,1953,104],{},[106,1955,1956,1964,1971,1979],{},[96,1957,1958,1961],{},[111,1959,1960],{},"Markup",[111,1962,1963],{},"HTML5",[96,1965,1966,1968],{},[111,1967,236],{},[111,1969,1970],{},"CSS3",[96,1972,1973,1976],{},[111,1974,1975],{},"Interactivity",[111,1977,1978],{},"Vanilla JavaScript",[96,1980,1981,1983],{},[111,1982,244],{},[111,1984,1985],{},"Static",[18,1987,1225],{"id":1224},[284,1989,1991],{"className":286,"code":1990,"language":288,"meta":158,"style":158},"git clone https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ftrekworld.git\ncd trekworld\n# Open index.html in your browser\n",[290,1992,1993,2002,2009],{"__ignoreMap":158},[293,1994,1995,1997,1999],{"class":295,"line":296},[293,1996,321],{"class":299},[293,1998,1237],{"class":307},[293,2000,2001],{"class":307}," https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ftrekworld.git\n",[293,2003,2004,2006],{"class":295,"line":159},[293,2005,1245],{"class":303},[293,2007,2008],{"class":307}," trekworld\n",[293,2010,2011],{"class":295,"line":476},[293,2012,2013],{"class":458},"# Open index.html in your browser\n",[506,2015,1902],{},{"title":158,"searchDepth":159,"depth":159,"links":2017},[2018,2019,2020],{"id":194,"depth":159,"text":195},{"id":87,"depth":159,"text":88},{"id":1224,"depth":159,"text":1225},"Web · Frontend","2023-10-30","A static frontend website for a trekking community, built with HTML, CSS, and JavaScript.","https:\u002F\u002Fgithub.com\u002F9ovindyadav\u002Ftrekworld",{},"\u002Fprojects\u002Ftrekworld",{"title":1923,"description":2023},"projects\u002Ftrekworld\u002Findex",[2030,2031,2032],"HTML","CSS","JavaScript","trekworld.9ovind.in","ZGLcCWtXN1rEtRctbFb_Q9NxcfsCh6w9zz0wx4BwSSM",1782753863073]