A collectible attendee index for every face in the Doon Tech Community.
A web app that catalogs every attendee from Doon Tech Community events as Pokédex-style profile cards. The app lets visitors browse, search, and filter attendees, view their event history, and explore fun community metadata like specialties, tech stack, favorite topics, and attendance badges. Organizers can create and edit attendee profiles, import attendees from events, and manage attendance records. The experience is playful, visual, and community-first, while still being useful as a living member directory for the Dehradun tech scene.
- Needs: Browse people they met at events, remember names, and learn what others build and talk about.
- Pain points: Forgets names after events, has no easy way to find attendees by interests, and wants a fun reason to revisit the community.
- Needs: Maintain an up-to-date attendee catalog, add new event attendees quickly, and keep profile data consistent.
- Pain points: Manually tracking attendance is tedious, profile data is incomplete, and updates are hard to manage after events.
- Needs: Discover who attends, what kinds of people are in the community, and who to connect with at future events.
- Pain points: Feels disconnected before the first event and lacks context on the people in the room.
Status labels:
- Implemented: Present in the current app.
- Partial: Core flow exists, but part of the described feature is still missing.
- Planned: Yet to be added.
A browsable grid of attendee profile cards with avatar, name, role, specialties, level, and badge count.
- User value: Makes the community feel collectible and easy to explore at a glance.
- Status: Partial. The grid exists; verified attendance count is not implemented yet.
Detailed profile pages with bio, current role, company, social links, event history, badges, and fun stats.
- User value: Helps members remember people and understand their interests quickly.
- Status: Partial. Profiles, badges, links, tags, and level exist; event history is not implemented yet.
Search attendees by name, company, role, badges earned, event attended, and skill set.
- User value: Lets users find the right person fast without scrolling the whole directory.
- Status: Partial. Name/company/role search, badge filtering, and sorting exist; event-attended filters are not implemented yet.
Admin tools to create, edit, archive, and merge attendee profiles.
- User value: Keeps the directory accurate and maintainable after every event.
- Status: Implemented.
A simple read-only list of past and upcoming Doon Tech Community events, each linking out to its external event page (e.g. Luma).
- User value: Gives newcomers and members a quick history of what the community has run, without duplicating event-platform features.
- Status: Implemented.
Award playful badges such as first event, frequent attendee, speaker, mentor, or open source contributor.
- User value: Adds gamification and encourages participation.
- Status: Implemented. Badge types can be created and organizer-awarded; attendance-specific automation is not implemented yet.
Show an attendee level derived from profile completeness, awarded badge rarity, and account tenure. Level is calculated by the server and cannot be manually edited by users.
- User value: Gives the Pokedex a playful progression mechanic while keeping the score tied to real profile quality and organizer-awarded recognition.
- Status: Implemented.
Highlight selected members on the homepage or a special spotlight section.
- User value: Makes it easy to introduce active community members and speakers.
- Status: Planned. The
featuredtable exists in the schema, but no public spotlight UI or admin workflow is implemented yet.
Generate shareable links for attendee profiles with social preview metadata.
- User value: Helps attendees share their presence and increases community visibility.
- Status: Implemented via public profile URLs and dynamic OG images.
Show metrics like total attendees, most common skills, most attended event, and active cities or companies.
- User value: Provides useful insight into the community composition.
- Status: Planned. Basic counts exist in the landing/admin UI, but the fuller stats dashboard is not implemented yet.
- As a community attendee, I want to browse attendee cards so that I can remember who I met at previous events.
- As a newcomer, I want to search by interests and job roles so that I can find people relevant to me.
- As an organizer, I want to create and edit attendee profiles so that the Pokedex stays accurate.
- As a community attendee, I want to open a profile page so that I can learn more about someone before reaching out.
- As a newcomer, I want to see the list of past and upcoming events so that I can jump to the event page and join the next one.
- As an organizer, I want to award badges so that I can make participation feel fun and recognizable.
- As a community attendee, I want levels to be earned from profile completeness, badges, and tenure so that progression feels credible.
- As an organizer, I want to feature selected attendees so that I can spotlight speakers and active members.
Look & feel: A 90s handheld Pokédex device, rendered in HTML/CSS. The entire viewport sits inside a coral-red plastic chassis that tilts in 3D on cursor movement, with a recessed light-blue glass LCD screen as the actual content area. Frosted-glass card tiles for content, chunky beveled plastic buttons, pixel-font headings, and faint CRT scanlines across the screen. The device chrome is functional: D-pad navigates between attendees, A-button opens the focused profile, a power button toggles boot state, and a speaker grille mutes click sounds. The aesthetic is unapologetically retro, but the layout under the chrome is a modern responsive card grid.
Typography:
- Display / headings / chips / buttons / labels:
Press Start 2P(pixel font, vianext/font/google). Used for h1–h3, the.pixelutility, chip text, button labels, and the v-LCD tag lines. Small sizes (0.55–0.7rem) to stay legible. - Body / inputs / stat values:
VT323(monospace LCD-style font). Set as the body default at 18px with light letter-spacing.
Color palette (implemented):
- Chassis (coral plastic):
#F26B6Fshell ·#FFA8ABhighlight ·#E6585Dmid ·#B8383Dlow ·#7A1F23deep ·#3A0A0Dink (outlines) - Glass LCD screen:
#E6F4FBhaze ·#B7E1F5lite ·#5BA8D4mid ·#1E5A82deep - Ink (readable on glass):
#0B2A3Eink ·#2F5670ink-soft ·#5B7E97ink-mute - LED indicators:
#6CCFF6blue ·#FF6B6Fred ·#FFD54Fyellow ·#5DE39Agreen - Page outside chassis: dark wine
#2A1416 → #1A0A0Cwith two soft radial-glow accents (coral + glass-blue) so the device floats - Rarity chip variants:
rare(lavender/purple),epic(gold),legendary(coral),success(green) — all rendered as beveled plastic chips
Component language:
.dex-shell— the chassis: glossy coral-plastic gradient with multi-layer drop shadow stacked beneath it for visible thickness when tilted, plus four corner screw-bump dots and a horizontal panel seam..lcd-panel— the screen: tinted light-blue glass with subtle scanlines, a top-left gloss highlight, chrome+ink bezel, and inset shadow to feel recessed into the chassis..led-lens— the big animated Pokédex eye: radial-gradient blue lens with pulsing glow, chrome bezel, and a sparkle highlight..led— small status dots (red/yellow/green) with inset shine and currentColor outer glow..card-frame— frosted-glass card tile (backdrop-filter: blur(6px)) with a top-left sheen, a 3px hover lift, and a soft cyan glow on hover..stat-block— small inset glass tile for numeric stats (used in profile and admin headers)..chip— pixel-font tag/badge pill with inset bevel. Variants drive rarity colors. Active filter chips switch to the blue button gradient..btn— chunky 3D plastic button with 4px bottom-slab depth and:active { translateY(3px) }press feel. Variants: default (coral),btn-primary(blue glass),btn-ghost(glass),btn-danger(dark red)..input— glass field with inset shadow and a yellow focus ring; selects use a CSS-only chevron via background gradients..dpad/.action-btn/.speaker-grille/.pwr-btn— functional device controls below the screen (DeviceControls,PowerButton,SoundProvider).
Motion & interaction:
PokedexTiltrotates the chassis a few degrees toward the cursor via CSS variables (--tilt-x,--tilt-y). The screen contents stay flat — the chassis moves around them.- Focus outline is a 3px solid yellow (
#FFD54F) at 2px offset — visible on every focusable element. - Card hover lifts 3px with extra cyan glow; buttons press down 3px.
- All transforms and the lens pulse animation are disabled under
prefers-reduced-motion. SoundProviderplays soft click ticks on button presses; the speaker grille toggles mute (persisted, with a green LED when on and a slash overlay when muted).
Accessibility & responsiveness:
- Skip-to-content link at the top of
<body>. - All controls reach via keyboard; chip filters use
aria-pressed, pagination usesaria-current="page". - Color contrast is verified against the light-blue glass screen background, not the dark outside chassis — body ink stays at
#0B2A3Eon#E7F6FD–#7ABDDE. - Chassis is capped at 768px on desktop and goes full-width on mobile; the attendee grid steps down from 2 → 1 columns.
- 3D tilt and decorative chrome degrade gracefully under reduced motion.
- Landing (
/): Boot screen inside the LCD. "SYSTEM READY" LED row, two-line pixel titleDOON TECH COMMUNITY, intro paragraph in VT323, three stat blocks (Developers / Events / Tags), a primary▶ ENTER POKÉDEXbutton, keyboard hintPRESS A OR ENTER TO START, and small secondary links toEvents →andAdmin →. - Pokédex Grid (
/dex): Header with a coral►bullet, pixelTHE POKÉDEXtitle, and a one-line description. Below it: a search input + sort dropdown row, a horizontal row of badge-filter chips colored by rarity (active chips switch to the blue button gradient), a result-count + page-count strip, the attendee card grid, a chip-style pagination row, and a glass empty-state card when filters return nothing. - Attendee Profile (
/attendees/[slug]): A frame card with a coral→badge→gold gradient banner, large square avatar overlapping the banner, name with aLVL Nepic chip, role · company, location, tag chips, and a small stat block grid (Badges / Level). Below: a two-column layout — Bio + Developer Card (preferred stack, favorite topic, company, location) on the left; Badges, Social Links, and Related Attendees on the right. - Organizer Dashboard (
/admin): Logged-out state shows a centered glass card prompting organizer sign-in. Signed in: page title with a greenORGANIZERchip, a+ New developerprimary button, three stat blocks (Attendees / Events / Tags), and the attendees table with search, edit/archive row actions, and a merge mode that selects a source and target. - Events (
/events): A simple two-column grid of glass cards. Each card shows the title, anupcoming(gold) orcompleted(green) chip derived from the date, the date line, a two-line description, and anOpen event ↗link. The whole card links out to the external event URL.
Levels are derived, not manually edited. The implementation source of truth is lib/levels.ts.
xp = profile completeness XP + badge rarity XP + tenure XP
level = highest nonlinear threshold reached by xpProfile completeness is capped at 80 XP:
| Signal | XP |
|---|---|
| Avatar uploaded | 10 |
| Role/title filled | 10 |
| Company filled | 10 |
| Location filled | 10 |
| Bio has at least 40 normalized characters | 10 |
| At least one social/personal link | 10 |
| One tag | 5 |
| Two or more tags | 10 |
| Preferred stack or favorite topic filled | 10 |
Badge XP is based on organizer-defined rarity:
| Rarity | XP |
|---|---|
| common | 25 |
| rare | 75 |
| epic | 180 |
| legendary | 400 |
Tenure adds 5 XP per full month since the attendee record was created, capped at 60 XP.
Levels use nonlinear thresholds so early progression is quick and higher levels require badges or long-term participation:
| Level | XP required |
|---|---|
| 1 | 0 |
| 2 | 50 |
| 3 | 125 |
| 4 | 225 |
| 5 | 375 |
| 6 | 575 |
| 7 | 850 |
| 8 | 1200 |
| 9 | 1650 |
| 10 | 2200 |
| 11 | 2900 |
| 12 | 3700 |
| 13 | 4700 |
| 14 | 6000 |
| 15 | 7600 |
| 16 | 9600 |
| 17 | 12000 |
| 18 | 15000 |
| 19 | 18500 |
| 20 | 22500 |
attendee.level is stored as a server-computed cache for display and sorting fallback. It is recalculated when:
- an attendee profile is created or updated
- a badge is awarded or removed
- attendees are merged
- a tag is deleted and removed from attendee profiles
The /dex?sort=level listing recomputes level from live profile, badge, and tenure data before sorting the filtered result set. Current implementation cap: live level sorting considers up to 1000 filtered attendees.
| Field | Type | Notes |
|---|---|---|
| id | string | Unique user identifier. |
| createdAt | datetime | Account creation timestamp. |
| updatedAt | datetime | Last account update timestamp. |
| name | string | Display name. |
| string | Login email. | |
| role | string | Values: organizer, member. |
| avatar_url | string | Profile image URL. |
| Relationships: Represents an authenticated account. Organizers can manage the Pokedex; regular members can browse and optionally edit their own profile if allowed. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique attendee identifier. |
| createdAt | datetime | Record creation timestamp. |
| updatedAt | datetime | Last record update timestamp. |
| name | string | Full name. |
| slug | string | URL-friendly profile identifier. |
| bio | string | Short community bio. |
| role_title | string | Job title or community role. |
| company | string | Current company or organization. |
| location | string | City, usually Dehradun or nearby. |
| avatar_url | string | Profile picture. |
| cover_image_url | string | Optional banner image. |
| linkedin_url | string | Optional social link. |
| github_url | string | Optional social link. |
| website_url | string | Optional personal site. |
| status | string | Values: active, archived. |
| user_id | string | Optional link to a user account for self-service editing. |
| preferred_stack | string | Optional favorite/current technology stack. |
| favorite_topic | string | Optional favorite topic to discuss. |
| level | integer | Server-computed cache derived from profile completeness, badge rarity, and tenure. Not user-editable. |
| tag_ids | string[] | Array of tag ids used for filters and profile chips. |
| Relationships: Primary directory entity. An attendee may be linked to one user account and can have many attendance records and badges. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique tag identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| name | string | Tag label such as Flutter, AI, DevOps, Product. |
| type | string | Values: skill, interest, industry, topic. |
| Relationships: Reusable interest or skill label. Many attendees can have many tags. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique join record identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| attendee_id | string | References attendee. |
| tag_id | string | References tag. |
| Relationships: Join table linking attendees and tags. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique event identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| title | string | Event name. |
| description | string | Event summary. |
| date | date | Event date. |
| external_url | string | Link to the external event page (e.g. Luma). |
| Relationships: Standalone reference to a Doon Tech Community event. Attendance is not tracked in this app. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique badge identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| name | string | Badge name. |
| description | string | What the badge means. |
| icon | string | Icon name or asset key. |
| rarity | string | Values: common, rare, epic, legendary. |
| Relationships: Reusable achievement that can be assigned to many attendees. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique join record identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| attendee_id | string | References attendee. |
| badge_id | string | References badge. |
| awarded_at | datetime | When the badge was awarded. |
| Relationships: Join table linking attendees and badges. |
| Field | Type | Notes |
|---|---|---|
| id | string | Unique feature record identifier. |
| createdAt | datetime | Creation timestamp. |
| updatedAt | datetime | Update timestamp. |
| attendee_id | string | References attendee. |
| start_at | datetime | Feature start time. |
| end_at | datetime | Feature end time. |
| priority | number | Ordering value. |
| Relationships: Stores which attendees are highlighted on the homepage for a given time window. |
List attendees with search, filters, sorting, and pagination.
- Request: None
- Response: [{ id, name, slug, role_title, company, avatar_url, tags[], level, badge_count, badges[] }]
- Frontend: Next.js with TypeScript and Tailwind CSS
- Backend: Appwrite
- Database: Appwrite TablesDB
- Auth: Appwrite Auth
- Hosting: Appwrite Sites for frontend, Appwrite Cloud for backend
- Notes: Next.js is a strong fit for a content-rich, shareable public directory. Appwrite gives managed auth, database, and access control, and Appwrite Storage can handle avatars, cover images, and badge assets.
- Load the attendee grid in under 2 seconds for typical community-size datasets and keep profile pages responsive under normal traffic.
- Meet WCAG AA accessibility standards with keyboard navigation, sufficient color contrast, semantic headings, and accessible filter controls.
- Use a responsive layout that works well on mobile, tablet, and desktop, with the attendee grid collapsing gracefully on smaller screens.
- Protect organizer actions with role-based access control and require authenticated sessions for create, edit, archive, badge assignment, and attendance management.
- Sanitize all user-generated content, validate uploaded images, and enforce file type and size limits for avatars and cover images.
- Use caching and pagination or infinite loading to keep browsing fast as the attendee list grows.
- Should attendees be publicly visible to anyone, or only to logged-in community members?
- Do you want attendees to be able to claim and edit their own profiles, or should only organizers manage profiles?
- Should the app add verified event check-ins as another level signal later?