Product
The mobile app is the primary client. The web design brief requires the web client to mirror the app's queries rather than add features of its own. The table shows where each feature lives.
Feature map
| Feature | Mobile | Web | Backend modules | Notes |
|---|---|---|---|---|
| Feed (13 modes, ranked for-you) | yes | yes | feed, feedRanked, ranking, feedHealth | Web mirrors ranked and home feeds with seen and dwell tracking |
| Posts: 20 images, 600 s video, polls, clips, drafts | yes | yes | posts, postCounters, drafts, musicClips | Separate 2.9k and 3.2k-line composers per platform on mobile |
| Comments, replies, voice comments (60 s), stickers | yes | yes | comments, commentStickers | iOS shows comments as a form sheet; Android opens full detail |
| Staðan stories | yes | yes | dailyUpdates | A player pool hands pre-buffered video to the viewer |
| Encrypted messaging, group chats, voice, chat events | yes | yes | messaging, encryption, chatEvents | 5,056-line conversation screen on mobile |
| Groups (Svæði), dues roster, invites, join requests | yes | yes | groups, groupPosts, groupDues, schoolEmails | Dues are recorded only; Slapp takes no money |
| Markaðstorg marketplace | yes | yes | 14 markad modules | Trades, double-blind reviews, saved-search alerts, photo provenance |
| Leigumarkaður rentals | yes | yes | 16 leiga modules | 6 UI languages; AI parses listings from text or screenshots |
| Deit dating (18+) | yes | no | dating, datingUpdateCampaign | Web has a middleware entry for /ast but no page |
| Events and event posts | yes | yes | events, eventPosts | Web adds an ICS feed and a generated OG image |
| Síður pages, automated pages | yes | yes | pages, automatedPages, content modules | Admin screens for news and daily-question approval live in the mobile app |
| Enski boltinn predictor | yes | yes | premierLeague modules | Live since 18 August 2026; per-minute fixture sync during match windows |
| HM leikur World Cup predictor | yes | no | worldCup (8 modules) | Crons retired; data frozen after the tournament |
| Stafli, geo game, daily challenge, trophies | yes | partial | stafli, geoGame, dailyChallenge, gameTrophies | Web has the hashtag challenge only |
| Djamm party mode | yes | yes | djamm, party | 8-hour party status, 1-minute drink cooldown |
| Þjóðhátíð festival mode | yes | no | thjodhatid | Hard-expired 3 August 2026 |
| Tilboð offers, clubs, redemption | yes | yes | 21 tilbod modules | PIN, code and tap redemption; merchant side in its own app |
| Slapp+ purchase | yes | no | subscription, loyalty | Custom paywall on mobile; web explains that purchase happens in the app stores |
| Slapp+ perks (viewers, analytics, private group) | yes | yes | loyalty, slappPlusGroup, postMilestones | |
| Friend map, location sharing | yes | no | mapLocations | By design, no web map |
| Tengslakort connection cards | yes | no | tengsl, graphSuggestions | "Only joint facts" between two users |
| Monthly wrapped, referrals, birthdays | yes | yes | wrapped, referrals, birthday | The referral competition is currently disabled server-side |
| Member tee shop | yes | no | shop | Mobile links to the shop app; Slapp+ has no shop perks |
| Share-to-Slapp, Instagram import | yes | partial | instagramImport, linkPreviews | iOS share extension; web has /deila |
Feed
The feed is the core loop: a friends-plus-discovery list of posts with up to 20 images, video up to 600 seconds, polls, stickers and attached music clips. It has 13 modes, and the production read path is the ranked query described in the feed ranker chapter. Posts can be drafted, and the two post composers on mobile are separate components, 2.9k and 3.2k lines, chosen at runtime per platform.
Comments support replies, 60-second voice comments and stickers. iOS shows comments as a form sheet; Android opens the full post detail. Dwell and view-duration hooks in the feed feed the ranker's training data: how long a post stayed on screen, whether the detail view opened, whether fullscreen opened.
Staðan
Staðan, "the status", is the daily photo or video story, with views, likes and comments, stored in the dailyUpdates table. On mobile a story player pool hands pre-buffered players to the viewer so the next story starts without a stall.
Messaging
Direct and group chats, with voice messages, images, shared posts and in-chat events. Every conversation has its own encryption key, as described in the architecture chapter. Conversations carry denormalised participant IDs and a per-participant unread count, and a kind flag keeps marketplace and rental threads out of the main inbox. Typing status lives in its own table to avoid write conflicts. Sending is rate-limited at 1,000 messages per minute and checks block relationships, and unread counts come from an aggregate. The conversation screen on mobile is the largest file in the app, at 5,056 lines.
Svæði and the two marketplaces
Svæði, "areas", is the groups hub. Groups have posts, invites, join requests and a dues roster; dues are recorded only, and Slapp takes no money. Student associations onboard members through school email lists (Skólanetföng). A per-section allowlist gates early access to new Svæði features.
Two marketplaces live inside it, and both require the user to be 18, which the identity model makes enforceable.
- Markaðstorg is a consumer-to-consumer marketplace with trades, double-blind reviews, saved-search alerts every 15 minutes, and photo provenance. Listings and wanted ads have their own canonical URL prefixes, Vara and Óska. Fourteen backend modules, including a risk model that adjusts surfacing from weighted signals without hiding anything automatically.
- Leigumarkaður is a rental market with owner verification, and it is the one part of the app that is not Icelandic-only: six UI languages (Icelandic, English, Polish, Lithuanian, Ukrainian and Spanish) from lazily loaded string tables, persisted so that push bodies follow the choice. AI parses listings from text or screenshots and translates them into the other five languages at write time. dHash photo fingerprints block listings whose photos match an external index. Sixteen backend modules.
Deit
Deit is the 18+ dating tab, with a swipe deck, top picks, question games and its own message stack. It exists only on mobile; the web has a middleware entry for its code path, ast, but no page. The tab is rendered only when the user is eligible, and eligibility is cached in MMKV so the native tab bar is correct on the first frame. Limits: 200 swipes per hour and 20 free dating likes per day. Feeds refill every six hours, top picks are computed at 11:00, and the Elo ratings that order the deck are replayed every Monday.
Events
Events can be standalone, bound to a group, or bound to a chat. They have RSVP, co-hosts, photos, event posts and public calendar feeds. Reminders go out every 15 minutes. The web client adds an iCalendar feed and a generated 1200 by 630 image for each event.
Síður and automated pages
Síður are multi-author pages. Some of them post without a human. Nine backend modules run them:
- A daily question generated by gpt-5.5 and approved in-app before it posts.
- RSS ingestion from RÚV, mbl, Vísir, DV, Heimildin and fotbolti.net every 30 minutes, with morning and afternoon digests at 07:50 and 16:50 that check their own summaries for entailment before publishing.
- A 07:20 weather post and CAP warnings from Veðurstofa, the Icelandic Met Office.
- An earthquake watch every 15 minutes with a Sunday recap.
- Wikipedia's most-read article daily, and weekly exchange-rate and fuel-price posts.
The admin screens for approving news and the daily question live in the mobile app, not the admin dashboard.
Games
Stafli is an Icelandic Wordle. There is a daily Street View geo game, a daily hashtag challenge, and a trophy system with a Slapphrifavaldur badge at 1,000 points. Two football predictors sit beside them: HM leikur, the World Cup predictor, whose crons are retired and whose data is frozen after the tournament, and Enski boltinn, the Premier League predictor, live since 18 August 2026 with per-minute fixture syncing during match windows. The two football games are the only things that run outside Convex, as two small prediction APIs. On web, only the hashtag challenge exists.
Seasonal modes
Djamm is party night mode: drink logs and leaderboards, with an 8-hour party status and a 1-minute cooldown between drinks. Þjóðhátíð was the festival mode for the Westman Islands festival; it hard-expired on 3 August 2026.
Tilboð
Tilboð, "offers", is the business marketplace. Merchants buy monthly ad slots, run loyalty clubs and redeem offers at the till by PIN, code or tap. The merchant side is its own app. Twenty-one backend modules. The slot tiers, the offer lifecycle and the loyalty plans are on the monetisation page.
Slapp+
Slapp+ is a RevenueCat subscription. Its perks: profile viewers, post analytics, incognito viewing, a private group, and dating perks. Purchase happens in a custom paywall on mobile; the web client explains that the purchase is made in the app stores and shows the perks it can: viewers, analytics and the private group. How the entitlement flows from RevenueCat into the app is on the monetisation page.
Other features
- A friend map with location sharing, mobile only; there is deliberately no web map.
- Tengslakort, connection cards between two users that show only facts both of them share.
- A monthly wrapped, referrals (the referral competition is currently disabled server-side), and birthdays.
- The member tee shop, linked from mobile and described with monetisation.
- Share-to-Slapp through an iOS share extension and a web route, and an Instagram import.
The mobile app
The app is the primary client: Expo Router with 408 route files, five tabs, native iOS tabs, a custom Android tab bar, and a data layer tuned for first-frame paint from device cache.
- Runtime
- Expo, React Native, React, Hermes, the New Architecture, the React Compiler, typed routes.
- Router
- Expo Router with NativeTabs on iOS and a custom bar on Android.
- Updates
- expo-updates with the runtime version bound to the app version. Checks on every launch, downloads on foreground, reloads only on backgrounding, and holds during sign-in.
- Builds
- EAS profiles for development, preview and production, with auto-increment. Channels match. Submitted as Vestra AI ehf.
- Dependencies
- 74 runtime and 6 dev. MMKV in 38 files and no AsyncStorage. Reanimated, gesture-handler, FlashList, expo-video, expo-image, expo-maps, expo-glass-effect, RevenueCat, noble ciphers.
- Native
- No custom native modules or config plugins. Two Xcode targets: the app and the share extension. The ios and android folders are prebuild output and untracked.
- Fonts and icons
- System fonts only. Ionicons in 370 files, 2,502 uses. SF Symbols only in the native tab bar and one icon wrapper.
Navigation
The tab bar is Heim (home), Svæði (groups), Deit (dating), Prófíll (profile) and Leita (search). On iOS the profile icon is the user's own avatar, rasterised off-screen to a 26-point circular PNG and cached.
Each tab owns a stack, and the same shared screens (post, profile, page, group, hashtag, story viewer) are registered inside every stack. As a result, 196 of the route files are under eight lines: they re-export a screen from a shared folder with a base path. The root layout registers roughly 60 more screens as modals, form sheets and deep-link redirects, guarded on auth state and account deletion.
| Stack | Route files | Screens registered | Layout size |
|---|---|---|---|
| Home | 83 | 55 | 1,313 lines |
| Groups | 88 | 63 | 1,106 lines |
| Profile | 51 | 38 | 855 lines |
| Search | 36 | 21 | |
| Dating | 6 | 5 | |
| Root, outside the tabs | 143 | about 60 | 2,525 lines |
Deep links use the slapp:// scheme plus universal links on slapp.is for nine path prefixes. A native-intent file rewrites web URL shapes onto app routes, and a pending-route mechanism waits for auth and the user document, navigates to the tab root first, then pushes the target, so the back button always has a screen to return to.
Data layer
- Convex hooks: 473
useQuery, 452useMutation, 62usePaginatedQuery, 31useAction. - Polled hooks: three custom hooks, plain, paginated and delta, used 120 times. They call a query once, refetch on demand, time out at 20 seconds, retry with a 2 to 30 second backoff, refetch on foreground, and drop stale responses through a generation counter. The reasoning is in the architecture chapter.
- Optimistic updates on 33 mutations across feed, profile, groups, events, pages and messaging.
- Snapshots: 20 MMKV stores implement stale-while-revalidate first paint for the feed, stories, groups, explore, profile, conversations, engagement, eligibility, the tab avatar, video URLs, prices, and the two sports games.
- Auth bridge: a custom hook replaces the stock Convex Better Auth provider. It caches and dedupes token fetches, resolves signed-out only on a definitive 401 or 403, uses hysteresis before flipping state, hydrates from SecureStore on cold start, and can recreate the Convex client to recover a zombie WebSocket after a long background.
- Sign-in: Kenni through the OAuth flow. On Android the session is redirected to the system browser with a five-minute timeout because Chrome Custom Tabs drop SIM-based authentication, and a progress marker in MMKV lets the app resume if an over-the-air reload interrupts the flow.
Media pipeline
- Images: compression presets (feed 1,200 px at quality 0.85, avatar 400 px, full 1,600 px, comment 600 px), an optional blurhash, then a presigned R2 PUT with a metadata sync and a size check before the key is trusted.
- Video: the thumbnail goes to R2, the video to Cloudflare Stream through tus in 10 MiB byte-range chunks, with a 600-second cap and 20 uploads per day.
- Playback: expo-video with a shared buffer config, a warm pool of up to three detached players, the story player pool, and prefetching of upcoming feed videos. The immersive viewer rotates through a transform so the app stays portrait-locked and the change ships over the air.
- expo-image in 277 files, a memory-disk cache policy in 192 places, recycling keys in 55 files, and a memory-pressure hook that clears the cache on warnings.
- An image editor built as an expo-gl shader with brightness, contrast, saturation, temperature, shadows, highlights, vignette and fade uniforms, plus filter presets.
Design system
One accent, orange, on white or near-black. #f97316accent #101112dark background Text is #11181Clight and #ECEDEEdark; borders are #e1e8edlight and #252729dark. Features carry their own palettes beside their code: dating pink and purple, Slapp+ gold #c9a84c, World Cup gold, Premier League. Liquid Glass availability is checked in 34 files to switch header transparency and paddings, but a glass view is rendered in exactly one screen. Haptics are used in 93 files. A measured audit of the app's type, radii and hues proposes a three-role type scale and a single orange.
Push notifications
Registration is deferred past first paint and runs once per session. Foreground pushes are suppressed at the OS level and drawn by an in-app banner instead. Tap handling routes by payload type (message, comment, like, reply, group post, profile views) and rewrites targets that point into another tab to a root-level equivalent, so a push never opens a screen without a back stack. There are no notification categories or action buttons. Which pushes are sent at all is decided by the notification ranker.
Performance habits
- FlashList in 12 list-heavy screens; FlatList remains the default in 134 files.
- The React Compiler plus 1,201
useCallback, 347useMemoand 99memowrappers. - Metro inline requires, root stack options hoisted to constants so the native header never re-lays out, and a deferred-after-paint helper that replaces InteractionManager in 12 files.
Localisation and platform split
The UI is hardcoded Icelandic with no i18n library. The exception is Leigumarkaður, described above. Platform.OS appears 654 times in 198 files; there is one platform-specific file for iOS and none for Android. The two post composers are separate components chosen at runtime.
The other surfaces
The web client is a full signed-in client and the landing page for every URL the app shares, rebuilt in September 2026 into a three-column shell: a left nav of nine items, a 600 px centre column, a right column with search, trending, suggestions and events, a messages dock and a global compose dialog. Phone width gets an install banner and a bottom tab bar. It has 93 pages: 6 public, 9 canonical deep-link pages, and 78 in-app client pages. Posts, profiles, groups, events, marketplace items, wanted ads, rentals, club invites and share-to-Slapp each have a server-rendered page with generated metadata; signed-in visitors see the full screen and logged-out visitors see a teaser with a sign-in bar and one attempt at the app scheme. It ships HSTS with preload, a full content security policy, frame denial in production, and 11 permanent redirects from legacy in-app paths. Not on web: dating, the World Cup game, Stafli, the geo game, connection cards, the friend map and the Slapp+ purchase.
The admin dashboard is 42 pages behind the admin flag, dark-only with its own accent, split into overview, users, analytics and business tooling. It has a user detail page, the reports queue, moderation and listing queues, 18 analytics pages including every model's weights and training history, and the Tilboð business tooling. What it cannot do: ban (bans are set through backend functions; the page only shows the badge), trigger migrations, or edit feature flags beyond the allowlist.
The Tilboð portal and the shop are described with monetisation.
Glossary
The codebase, the interface and the database use Icelandic names. These are the ones you meet in identifiers and route paths.
| Term | Meaning |
|---|---|
| Heim | home tab and feed |
| Svæði | "areas": the groups hub, also hosting the marketplaces |
| Deit | the dating tab (code path ast, "love") |
| Prófíll | profile tab |
| Leita | search tab |
| Staðan | "the status": daily stories, table dailyUpdates |
| Pósta | compose a post |
| Síður | pages: multi-author publications |
| Tilboð | offers: the business ad and loyalty marketplace |
| Vildarklúbbur | a merchant's loyalty club |
| Bókhald | accounting: the merchant invoice page |
| Leiga, Leigumarkaður | rental market |
| Markaðstorg | consumer marketplace |
| Vara, Óska | a listing, a wanted ad (canonical URL prefixes) |
| Klúbbboð | club invitation (route /klubbbod) |
| Deila | share (the share-to-Slapp route) |
| Kennitala | Icelandic national ID number; encrypted at rest |
| Kenni | the eID provider used for sign-in |
| Stafli | the Icelandic Wordle |
| Djamm | party night mode |
| Þjóðhátíð | the Westman Islands festival mode |
| Enski boltinn | Premier League predictor |
| HM leikur | World Cup predictor |
| Tengsl, Tengslakort | connections, the friend-graph card |
| Slapphrifavaldur | "Slapp influencer" badge at 1,000 points |
| Félagsgjald, árgjald | membership dues recorded for groups |
| Spurning dagsins | question of the day page |
| Fréttir, Veðrið, Skjálfta, Fróðleikur | automated news, weather, earthquake and trivia pages |
| Skólanetföng | school email onboarding for student associations |
| Hver er ég | "who am I": the direction and school-verification flow |
| Slapp ari | the mascot on the tee |