Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Install
run: npm ci

- name: Lint
run: npm run lint

- name: Typecheck
run: npm run typecheck

- name: Test
run: npm test

- name: Build
run: npm run build

- name: Upload GitHub Pages artifact
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v3
with:
path: ./out

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: verify
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
66 changes: 43 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,56 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
# Upabode

## Getting Started
Upabode is a small rental listing finder. It ships with 12 sample homes across Bengaluru, Pune, Hyderabad, and Kochi. Search and filters run in the browser, so the site needs no account, database, or API key.

First, run the development server:
**Live site:** [https://naveecode.github.io/upabode/](https://naveecode.github.io/upabode/)

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
GitHub Pages has to be set to **GitHub Actions** before that URL serves this build. The deploy workflow in this repo publishes the static `out/` folder on every push to `main`.

## Features

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
- Text search across title, neighborhood, city, description, and amenities
- Filters for city, home type, maximum rent, bedrooms, pets, and furnished
- Sort by rent or by recently posted
- A listing detail dialog with availability and amenities
- Sample data is bundled with the page

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
## Stack

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
- Next.js 16 (App Router) and React 19
- TypeScript
- Static export (`output: 'export'`) with `basePath` `/upabode` for GitHub project pages
- Vitest for the search and filter functions
- GitHub Actions for lint, typecheck, unit tests, build, and Pages deploy

## Learn More
## Screenshots

To learn more about Next.js, take a look at the following resources:
![Browse page with search, filters, and listing cards](docs/screenshots/browse.png)

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
![Bengaluru filter narrowed to three homes](docs/screenshots/filters.png)

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
![Listing detail dialog](docs/screenshots/detail.png)

## Run locally

```bash
npm install
npm run dev
```

Open [http://localhost:3000/upabode](http://localhost:3000/upabode). The `/upabode` prefix matches the GitHub Pages base path.

```bash
npm test
npm run lint
npm run typecheck
npm run build
```

## Deploy on Vercel
`npm run build` writes the static site to `out/`.

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
## What I learned

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
- A static export can only include what is known at build time. Keeping the listings in the client, and the matching rules in plain functions, meant the page could be hosted as files.
- Those functions are easier to trust once the awkward cases are tests: blank queries, combined filters, every search word required, and sorts that do not reorder the original array.
- Project pages need `basePath: '/upabode'` so CSS, JavaScript, and fonts load from `/upabode/_next/...` instead of the domain root.
- This repository already contained a larger social app (Multigram) that depends on a database, cookies, and route handlers. That cannot be a static export, so the source is preserved under [`legacy/multigram`](legacy/multigram) rather than deleted. Credentials that had been committed in its Render config were replaced with placeholders; the old values are still in git history and should be rotated.
Binary file added docs/screenshots/browse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/detail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/filters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
"legacy/**",
"scratch/**",
]),
]);

Expand Down
9 changes: 9 additions & 0 deletions legacy/multigram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Multigram (preserved snapshot)

This folder is the previous app that lived at the root of this repository: a full-stack social product (posts, reels, chat, calls, Google sign-in) built with Next.js, Prisma, and a Node server.

It is kept here so that work is not thrown away. It is **not** the site deployed to GitHub Pages. Static export cannot run it: the app uses server actions, route handlers, cookies, a database, and request-time APIs.

To run this snapshot, check out the commit before the portfolio change and use that tree as the project root (it expects `DATABASE_URL` and the other service credentials). Do not commit those values.

`render.yaml` in this folder no longer contains live credentials. If those values were ever pushed, rotate them in Pusher, UploadThing, and the database provider. They can still be recovered from older git history.
18 changes: 18 additions & 0 deletions legacy/multigram/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);

export default eslintConfig;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
42 changes: 42 additions & 0 deletions legacy/multigram/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
typescript: {
// Skip typecheck during container build to save 300MB RAM (we verify locally)
ignoreBuildErrors: true,
},

experimental: {
// Restrict to single thread to stay well under 512MB RAM on free tier
cpus: 1,
workerThreads: false,
},

async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin',
},
{
key: 'Permissions-Policy',
value: 'camera=(self), microphone=(self), geolocation=()',
},
],
},
];
},
};

export default nextConfig;
36 changes: 36 additions & 0 deletions legacy/multigram/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "multigram",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "npm install \u0026\u0026 npx prisma generate \u0026\u0026 npx prisma db push \u0026\u0026 next build",
"start": "next start",
"lint": "eslint",
"postinstall": "prisma generate"
},
"dependencies": {
"@prisma/client": "^5.11.0",
"@uploadthing/react": "^7.3.3",
"jose": "^6.2.12",
"next": "16.3.5",
"peerjs": "^1.5.5",
"pusher": "^5.3.4",
"pusher-js": "^8.6.0",
"react": "19.2.8",
"react-dom": "19.2.8",
"uploadthing": "^7.7.4"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.3.5",
"prisma": "^5.11.0",
"tailwindcss": "^4",
"tsx": "^4.23.13",
"typescript": "^5"
}
}
7 changes: 7 additions & 0 deletions legacy/multigram/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};

export default config;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
10 changes: 5 additions & 5 deletions render.yaml → legacy/multigram/render.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ services:
- key: SESSION_SECRET
generateValue: true
- key: PUSHER_APP_ID
value: "2194387"
sync: false
- key: NEXT_PUBLIC_PUSHER_KEY
value: "a1d789b8b44c24f2dac8"
sync: false
- key: PUSHER_SECRET
value: "4127fdaf450956e0782f"
sync: false
- key: NEXT_PUBLIC_PUSHER_CLUSTER
value: "ap2"
sync: false
- key: UPLOADTHING_TOKEN
value: "eyJhcGlLZXkiOiJza19saXZlXzAwN2NiNTc0NDg4YTRjOWM1NzE1YjIxNzgwNGQ5NGEwZGY0YzVjZDBkN2NkYWE3MTg5NGJiZGVmZjllMjAwZDEiLCJhcHBJZCI6InV1N3ZoYjczcjYiLCJyZWdpb25zIjpbInNlYTEiXX0="
sync: false
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading