Skip to content

Commit eb7391a

Browse files
authored
Merge pull request #69 from yakew7/main
V2.0.0
2 parents f0da7ac + c6a1ce6 commit eb7391a

34 files changed

Lines changed: 3743 additions & 159 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
title: "[city request] "
2+
labels: ["community"]
3+
body:
4+
- type: markdown
5+
attributes:
6+
value: |
7+
Want StudyMap to cover your city? Tell us which one and why, we use these
8+
requests to prioritize where the dataset grows next.
9+
- type: input
10+
id: city
11+
attributes:
12+
label: Which city?
13+
description: Name the city (and state/country if it could be ambiguous).
14+
validations:
15+
required: true
16+
- type: textarea
17+
id: why
18+
attributes:
19+
label: Why this city?
20+
description: What makes it student-relevant, e.g. exam centres, colleges, coaching hubs.
21+
validations:
22+
required: true
23+
- type: dropdown
24+
id: help
25+
attributes:
26+
label: Willing to help with data?
27+
description: Adding places is a PR, see CONTRIBUTING.md.
28+
options:
29+
- "Yes, I can contribute places"
30+
- "Maybe, depends on scope"
31+
- "No, just requesting"
32+
validations:
33+
required: true

ARCHITECTURE.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Pure TypeScript modules. No JSX, no React imports. Each file has a single respon
137137
| File | What it does |
138138
|------|-------------|
139139
| `types.ts` | `Place`, `PlaceType`, `City` types; label maps |
140-
| `places.ts` | Imports all 8 JSON files; exports `getPlaces()` and `filterPlaces()` |
140+
| `places.ts` | Reads places from `studymap.config.ts`; exports `getPlaces()` and `filterPlaces()` |
141141
| `geo.ts` | Haversine distance, `placesByDistance()`, `formatDistance()` |
142142
| `map.ts` | `PLACE_TYPE_COLORS` (color-blind-safe palette); `directionsUrl()` |
143143
| `share.ts` | URL state encode/decode for shareable filtered map links |
@@ -151,10 +151,10 @@ Pure TypeScript modules. No JSX, no React imports. Each file has a single respon
151151
## Data flow
152152

153153
```
154-
data/places/*.json
154+
studymap.config.ts imports data/places/*.json, exports the merged Place[]
155155
156156
157-
src/lib/places.ts getPlaces() merges all 8 files into one Place[]
157+
src/lib/places.ts getPlaces() reads the config's Place[]
158158
│ filterPlaces() narrows by type and/or city
159159
160160
src/components/map/places-map.tsx
@@ -176,7 +176,7 @@ src/components/pins/pin-popup.tsx
176176
buildShareUrl(state) ← src/lib/share.ts
177177
```
178178

179-
**No network requests at runtime.** The JSON is bundled at build time via static `import` statements in `places.ts`. The Leaflet tile layer (OpenStreetMap) is the only external request when the map is open.
179+
**No network requests at runtime.** The JSON is bundled at build time via static `import` statements in `studymap.config.ts`. The Leaflet tile layer is the only external request when the map is open.
180180

181181
---
182182

@@ -189,10 +189,13 @@ The single aggregation point for place data. Every component that needs places c
189189
```ts
190190
getPlaces(): Place[]
191191
filterPlaces(places, { types?, cities? }): Place[]
192-
MMR_CENTER // [lat, lng] for the initial map view
193-
MMR_DEFAULT_ZOOM
192+
getCities(places, preferredOrder?): City[]
194193
```
195194
195+
Region and dataset settings (initial map center, default zoom, coordinate bounds, the
196+
city display order, and which `data/places/*.json` files get loaded) live in
197+
`studymap.config.ts` at the repo root, the one file a fork edits to retarget StudyMap.
198+
196199
### `src/lib/geo.ts`
197200
198201
All distance math lives here. Used by `places-map.tsx` to find the five nearest places when the user enables geolocation.

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ Use [Conventional Commits](https://www.conventionalcommits.org/): `<type>: <shor
148148

149149
Optional scope in parens: `feat(calendar): add today label`. One logical change per commit.
150150

151+
## Get recognized
152+
153+
First merged PR? Add your GitHub handle to [CONTRIBUTORS.md](CONTRIBUTORS.md), in the
154+
same PR or a quick follow-up.
155+
151156
## House rules
152157

153158
- No em dashes in any copy

CONTRIBUTORS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Contributors
2+
3+
Everyone who has helped build StudyMap, whether through code, data, or docs.
4+
5+
- [@AnayDhawan](https://github.com/AnayDhawan)
6+
- [@yakew7](https://github.com/yakew7)
7+
- [@shauryagangrade](https://github.com/shauryagangrade)
8+
- [@shauryagangrade-blip](https://github.com/shauryagangrade-blip)
9+
- [@Circout-sudo](https://github.com/Circout-sudo)
10+
- [@thunderrblitzyt-eng](https://github.com/thunderrblitzyt-eng)
11+
12+
## Adding yourself
13+
14+
Opened your first merged PR? Add your GitHub handle to the list above, alphabetical
15+
order doesn't matter, append it. Do this in the same PR as your contribution, or a
16+
quick follow-up if you forgot.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,24 @@ data/
9595
- **shadcn/ui + Tailwind v4** (UI components)
9696
- **next-themes** (dark/light mode)
9797

98+
## Running your own fork
99+
100+
Want StudyMap for a different city? Click "Use this template" above, then follow
101+
[SELF-HOSTING.md](SELF-HOSTING.md): set your region and dataset in one config file, optionally
102+
wire up your own Supabase project for sign-in, and deploy.
103+
98104
## Contributing
99105

100106
See [CONTRIBUTING.md](CONTRIBUTING.md).
101107

108+
## Good first issues
109+
110+
New here? Start with an issue tagged [`good first issue`](https://github.com/StudentSuite/StudyMap/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or browse everything tagged [`help wanted`](https://github.com/StudentSuite/StudyMap/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). Adding a place from your own neighbourhood ([#18](https://github.com/StudentSuite/StudyMap/issues/18)) needs no coding at all.
111+
112+
## Contributors
113+
114+
See [CONTRIBUTORS.md](CONTRIBUTORS.md).
115+
102116
## License
103117

104118
MIT. See [LICENSE](LICENSE).

SELF-HOSTING.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Self-hosting StudyMap
2+
3+
Run StudyMap for your own city. Everything below works from a fork, no coding required beyond
4+
editing one config file and your place data.
5+
6+
## What you get out of the box
7+
8+
- The interactive map, filters, search, and calendar for whatever `data/places/*.json` you provide.
9+
- Two optional, signed-in-only features (saved places, personal calendar events) if you set up your
10+
own Supabase project. Skip that section entirely and the app still works, just without those.
11+
12+
## 1. Get the code
13+
14+
Click "Use this template" at the top of [StudentSuite/StudyMap](https://github.com/StudentSuite/StudyMap)
15+
to create your own copy, then clone it:
16+
17+
```bash
18+
git clone https://github.com/<your-account>/<your-fork>.git
19+
cd <your-fork>
20+
npm install
21+
```
22+
23+
## 2. Set your region and dataset
24+
25+
Everything region- and data-specific lives in one file: `studymap.config.ts` at the repo root.
26+
27+
```bash
28+
cp studymap.config.example.ts studymap.config.ts
29+
```
30+
31+
Edit it:
32+
33+
- `center`: `[lat, lng]` for the initial map view
34+
- `defaultZoom`: initial zoom level (11-13 works well for a metro area)
35+
- `bounds`: rough coordinate box around your region, used for data validation and map fitting
36+
- `cities`: display order for the city filter (any city present in your data but missing here
37+
still shows, just sorted alphabetically after)
38+
- `places`: swap the sample imports for your own `data/places/*.json` files
39+
40+
The dataset itself follows the schema in [`data/CONTRIBUTING.md`](data/CONTRIBUTING.md): one JSON
41+
file per place type, one object per place, with `id`, `name`, `type`, `city`, `lat`, `lng`,
42+
`gmaps_link`, and `added_by`. `data/places.sample/` has two minimal example entries if you want to
43+
start from a clean skeleton instead of the Mumbai dataset that ships with the template.
44+
45+
Validate as you go:
46+
47+
```bash
48+
npm run validate
49+
```
50+
51+
## 3. Environment variables
52+
53+
```bash
54+
cp .env.example .env.local
55+
```
56+
57+
- `NEXT_PUBLIC_MAPTILER_KEY` is required for the map basemap. Free tier, no credit card, at
58+
[cloud.maptiler.com](https://cloud.maptiler.com/account/keys/).
59+
- The Supabase variables are optional. Leave them blank and the map, filters, and calendar all
60+
work; you just won't get sign-in or the two private features below. See step 5 to fill them in.
61+
62+
## 4. Run it
63+
64+
```bash
65+
npm run dev
66+
```
67+
68+
Open [http://localhost:3000/map](http://localhost:3000/map) and confirm your places show up in
69+
the right spot.
70+
71+
## 5. Optional: sign-in, saved places, and personal calendar events
72+
73+
These three features (`src/app/login`, saved custom places, personal calendar events) need a
74+
Supabase project:
75+
76+
1. Create a free project at [supabase.com](https://supabase.com).
77+
2. Copy its URL and anon key into `.env.local` (`NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`).
78+
3. In the Supabase SQL editor, run every file in `supabase/migrations/`, in filename order. Each
79+
one creates its tables with row-level security already scoped to `auth.uid()`, so users can
80+
only ever read or write their own rows.
81+
4. Enable whichever auth providers you want (email, Google, etc.) under Authentication > Providers.
82+
83+
Skip this whole section if you only want the public map and calendar.
84+
85+
## 6. Deploy
86+
87+
Deploy like any standard Next.js app, for example on Vercel:
88+
89+
```bash
90+
npx vercel
91+
```
92+
93+
or import the repo at [vercel.com/new](https://vercel.com/new) and set the same environment
94+
variables from step 3 in the project settings.
95+
96+
**Static export (`output: "export"`) is not supported.** Sign-in needs a live server: the OAuth
97+
callback route exchanges a code for a session server-side, and middleware refreshes that session
98+
on every request. Both are incompatible with a static build. Deploy to a normal server/edge
99+
runtime instead, that's the default for Vercel and most other Next.js hosts.
100+
101+
## Keeping your fork current
102+
103+
StudyMap doesn't push updates to forks automatically. To pull in upstream fixes, add the original
104+
repo as a remote and merge from it:
105+
106+
```bash
107+
git remote add upstream https://github.com/StudentSuite/StudyMap.git
108+
git fetch upstream
109+
git merge upstream/main
110+
```
111+
112+
Your `studymap.config.ts`, `.env.local`, and `data/places/*.json` are yours, upstream changes to
113+
shared code (map, calendar, components) merge in without touching them, unless you've also edited
114+
those files.

data/places.sample/book_shop.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[
2+
{
3+
"id": "example-book_shop-01",
4+
"name": "Example Street Book Shop",
5+
"type": "book_shop",
6+
"city": "example_city",
7+
"lat": -0.01,
8+
"lng": 0.01,
9+
"address": "Replace with a real address",
10+
"gmaps_link": "https://maps.google.com/?q=-0.01,0.01",
11+
"added_by": "your-github-handle"
12+
}
13+
]

data/places.sample/library.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[
2+
{
3+
"id": "example-library-01",
4+
"name": "Example City Central Library",
5+
"type": "library",
6+
"city": "example_city",
7+
"lat": 0,
8+
"lng": 0,
9+
"address": "Replace with a real address",
10+
"gmaps_link": "https://maps.google.com/?q=0,0",
11+
"added_by": "your-github-handle"
12+
},
13+
{
14+
"id": "example-library-02",
15+
"name": "Example University Library",
16+
"type": "library",
17+
"city": "example_city",
18+
"lat": 0.01,
19+
"lng": 0.01,
20+
"address": "Replace with a real address",
21+
"gmaps_link": "https://maps.google.com/?q=0.01,0.01",
22+
"added_by": "your-github-handle"
23+
}
24+
]

docs/OFFLINE_CACHING.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Offline caching and stale content
2+
3+
StudyMap is a Progressive Web App (PWA). It registers a service worker
4+
(`public/sw.js`) so the map still opens on exam day with a weak or absent
5+
signal. This also means the app can keep serving cached content after a
6+
deploy ships, which can look like "the fix never happened" when really your
7+
browser or installed PWA is still holding the previous version.
8+
9+
## What gets cached
10+
11+
The service worker keeps two caches, both versioned by `VERSION` in
12+
`public/sw.js`:
13+
14+
- **App cache** (`app-<version>`): the app shell (`/`, `/offline`,
15+
`/manifest.webmanifest`), plus build output under `/_next/static` and
16+
`/icons`. Static build assets are cache-first since they're
17+
content-hashed and never change under the same URL. Page navigations try
18+
the network first and fall back to the cache when offline.
19+
- **Tile cache** (`tiles-<version>`): map tiles from `api.maptiler.com`,
20+
cache-first, capped at 300 tiles so it doesn't grow unbounded.
21+
22+
On every deploy, `VERSION` changes, which causes the new service worker to
23+
delete all caches that don't match the new version on activation. In most
24+
cases a normal reload picks up the new version automatically. Staleness
25+
happens when the browser hasn't fetched the new `sw.js` yet, usually because
26+
the old service worker is still controlling the page or the browser served
27+
`sw.js` itself from an HTTP cache.
28+
29+
## Forcing a fresh load
30+
31+
If the map or UI looks out of date after a known deploy, try these in order:
32+
33+
1. **Hard refresh**: reload while bypassing the cache (Cmd+Shift+R on
34+
Mac, Ctrl+Shift+R on Windows/Linux, or Ctrl+F5).
35+
2. **Clear site data**: in browser dev tools, Application (Chrome/Edge) or
36+
Storage (Firefox) tab, clear Service Workers, Cache Storage, and Storage
37+
for the site, then reload.
38+
3. **Uninstall and reinstall the PWA**: if StudyMap was installed as an app,
39+
remove it from your device and reinstall from the site to pick up a
40+
fresh service worker.
41+
42+
If none of these help, the deploy itself likely hasn't shipped yet, so
43+
check the deployment status before assuming it's a caching issue.

0 commit comments

Comments
 (0)