Brooklynđ©Poopđ©Map
Project is live here:
Screenshots



Inspiration
Initially I wanted to make a proper, respectable community page, like the one I pitched in my proposal. A landing page for the IMA/ITP Open Source Club, a hub for discussions, events, code repositories, all that good stuff. I had a few ideas for interactive elements, maybe a real-time project showcase, maybe some kind of collaborative coding space. Then I talked to Yu, the current club president, and turns out they donât really need it. And to be honest, neither do I⊠The more I thought about it the more it felt painfully dull.
So I kept walking, thinking maybe there was a way to make open source club interesting. Maybe I just wasnât thinking hard enough, maybe there was something I could do to make it feel alive, maybe⊠and then I stepped in it. Full weight full force no warning no time to react it just happened I looked down and my shoe was gone not literally but spiritually that shoe was finished and I stood there watching my life choices collapse around me thinking about how I got to this exact point in time and space and suddenly it was so clear so obvious like the universe had been trying to tell me something this entire time and I just wasnât listening
Forget open source club, forget community landing pages, Iâm making a Brooklyn Poop Map
Creating the Community
My original vision was that The Watch Your Step Society (TWYSS) would be a fictional community. But technically speaking, anyone who pins a poop location is an instant member. So, thatâs how TWYSS became this half-imaginary, half-very-real collective.
- Insiders: The people who actively submit sightings, read the stats, and basically treat this like a communal vigil. Theyâre my main focus. For them, I want a straightforward, no-bullshit layout, something that feels almost like reading a daily newspaper.
- Outsiders: They might stumble in out of sheer curiosity or necessity (like stepping in something and deciding they never want that experience again).
References
are.na has been a huge help! Iâve basically dumped everything in there.
Brooklynđ©Poopđ©Map | Are.na
The San Francisco Poop Map
The OG concept: crowdsourcing and mapping where human waste is spotted on the streets.
A strong civic horror angle, it exposes urban neglect, inequality, and crumbling infrastructure.
Can BKMP adopt a similar government-shaming* function? Maybe an automatic report function that emails 311?
*Government Shaming
âEric Adams slashed city budgets at the end of last year and the Department of Sanitation is now implementing a 3 percent cut. Along with axing community composting programs and delaying brown bin pickup, the department will be reducing its sidewalk trash can collection service by 40 percent. â
Crime Mapping
The SF Poop Map wonât tell you whatâs actually there or why it was marked, so I took inspiration from this:
![]()
But here comes the horror story. I bookmarked this last year and now found out Itâs gone. Itâs wiped clean. And we donât ask, we donât speak, we donât know. Here, have a screenshot.

Useless Websites
collection of sébastien de ganay, paper toilet .com by rafaël rozendaal, 2006
This paper towel made me realize that we need something that grows, something that stimulates our brains, so I need to make a counter. And also, because poop itself is useless but important.
Honestly, I donât even care if this thing is âusefulâ or not. I just want to entertain the shit on the streets. If it changes something, great, however the shoe is already gone and thereâs no getting it back
Design Mood Board
Iâm leaning into a design language that says both âpublic service announcementâ and âcheck this out, itâs weird.â


Newspaper + Grids
Newspapers: I want it to give an official vibe. They report, they archive, they tell you whatâs happening whether you like it or not. I eventually added a grid at the background becuase I want this to feel like itâs running on pure urban logic.

I also like this hand-drawn style map better than the default OpenStreetMap color scheme. Iâll get to how I achieved the final effect later in the Process part.

poop pin

I wanted this poop pin to happen from the very start.
Sitemaps & Wireframes
graph TD;
A[Home Page] -->|Read about the project| B[About the Community];
A -->|See statistics| C[Poop Count];
A -->|Navigate to Report Page| D[Report Poop];
A -->|View existing reports| E[Map View];
D -->|Select location| F[Use the Map];
D -->|Describe the sighting| G[Write a Report];
D -->|Submit report| H[Send it in];
E -->|See reported locations| I[View Map Data];
E -->|Go back home| A;
E -->|Report a new sighting| D;
Process
At first I focused on getting something functional rather than perfect. The goal was to make it work first & refine later.


Once I had the basic map up and running I got obsessed with small details**,** things like how reports should be displayed, making the UI feel seamless, and making sure interactions felt natural.
Map styling
Why I Switched from OpenStreetMap to MapTiler
I started with OpenStreetMap since itâs free and widely used and Sam recommended it. But pretty quickly, I ran into some issues:
- OSMâs default tiles werenât quite fitting the black-and-white, print-like aesthetic I wanted.
- Customizing styles was possible, but required setting up TileServer or using third-party styling tools, which felt like overkill for what I needed.
How I Used MapTiler & the Toner Style
I switched to MapTiler because it let me easily customize map styles while keeping everything lightweight and API-based.
-
Toner Style:
- This is a high-contrast, blackand-white map style originally from Stamen Design.
- It fits perfectly with my projectâs newspaper-inspired layoutgrid
- It removes unnecessary distractions like satellite imagery or excess colors
In map.js, I use MapTilerâs API and set the mapâs base layer to Toner:
L.maptilerLayer({
style: `https://api.maptiler.com/maps/toner-v2/style.json?key=${MAPTILER_API_KEY}`
}).addTo(map);
Geolocation Handling for Submissions
Users should be able to submit reports by either clicking on the map or using their real-time geolocation. This needs to work across different devices and browsers.
This is super helpful:
- Leaflet.js handles map interactions (
initSelectionMapinmap.js). - Implemented an event listener on map clicks to place a marker and update hidden form fields with latitude/longitude values. in the js file
- Added a geolocation button that triggers
navigator.geolocation.getCurrentPosition(). If permission is granted, the map centers on the userâs location and places a marker. - Fallback: If geolocation is not supported or denied, users manually drop a pin.
Rendering Reports Dynamically on the Map
The map must dynamically display all reported locations with popups that show user-provided descriptions and images.
-
On page load (
window.onloadinmap.js), it fetches reports via/api/reportsand updates the#poop-counterdynamically. -
Used Leaflet markers (
addPoopMarkers()) to plot each report (Iâm glad itâs cutomizable, so I can use the poop emoji) -
Each marker gets a popup with the userâs description, a photo (if uploaded), and a timestamp.
-
If fetching fails, it initializes the map with an empty dataset to avoid breaking the UI.

Poop Report Counter
One feature I really wanted to implement (if youâre wondering why, check the references) is the poop report counter. The number of documented poop sightings (poopCount in index.ejs and #poop-counter in map.ejs) should update dynamically as reports are submitted.
My solution is to fetch reports on page load:
- When the
/mappage loads,fetch('/api/reports')retrieves all submitted reports from the backend. - The length of the returned array determines the poop count, which updates
#poop-counterdynamically.
map.ejs Layout Design
This page went through a lot of iterations. At first, because I set a fixed width for the content in layout.ejs, the map couldnât fully expand. This was restrictive and didnât look great.

I fixed this by making it absolute but It still looks weird.

I decided to go back to the SF Poop Map style and just make it fullscreen. The map view should take up the full screen while hiding unnecessary UI elements when navigating to /map.
To do this:
- Added a
body.map-fullscreen-modeclass instyles.cssthat hides the header, nav, and footer while expanding the map container to 100% width/height. - The function
enableFullscreenMapMode()inmap.jsdetects if the user is on/mapand applies this class dynamically. - Created a floating control panel (
.map-controlsinstyles.css) for navigation and report submission without breaking fullscreen mode.
After all the whole point is to display the map properly

Styling Details
Navigator
One of the first things I noticed was that the navigation felt a bit lackingâthere was no way to tell which tab was currently active. And that bugged me. I kept thinking, âShouldnât the current tab be highlighted?â Besides, it would make the whole layout feel more balanced.
This turned out to be a slightly bigger challenge than I expected. The final solution involved adding a function in map.js (highlightCurrentNavLink()) that checks window.location.pathname and assigns the .nav-link-active class to the corresponding <a> element. Then in CSS, .nav-link-active sets a black background and white text to differentiate it. Simple, but effective.
Poopy Highlighter

Invert (headline, Q&A, etc)
Making it feel like a newspaper header. Also for visual balance
Button Interaction
They start as white with a black border, but when hovered over, they invert to a fully black button with white text.
Grid bg
Other Resources
Future Improvements
Originally I wanted to implement a locked region like SF Poop Map, so the map would stay focused on Brooklyn. But because Iâm using MapTiler API, I never fully figured this out. As a result the current functionality technically makes this a worldwide poop map instead of a bk poop map.
(So yeah my friends all the way in Shanghai can contribute too.)

Also if I learn how to add user authentication, I could create a ranking system (anonymously). Imagine a âTop Poop Reportersâ board.
For now though itâs still an open world poop mapđ©
Thank You for Reading

