Skip to content

About

This is the code for perrinn.com website

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

1,424 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PERRINN

PERRINN is a member collaboration app for profiles and member discovery, conversations, account settings, PRN wallet and membership flows, and community information.

What’s in the app

  • Profiles and directory for viewing members and finding people.
  • Chat for conversations and community activity.
  • Account settings for profile and account details.
  • PRN and membership pages for wallet-related information, membership, and payment flows.
  • Community information and links to related resources.

The main client routes are /home, /profile/:id, /directory, /apps, /chat/:id, /settings, /login, and /buyPRN/:id. The root route redirects to /home. Both desktop and mobile PERRINN brand controls open Home. The home dashboard preserves the home prototype’s shared-image mosaic with full-screen viewing, four upcoming events linking to conversations, and ten recently active users linking to profiles. Touch-device visitors outside standalone mode also see a subtle home-screen tip above the banner; dismissing it hides it for the current tab session. The PERRINN profile banner appears above the headline using the already-loaded profile image; unavailable or failed images are omitted. It adapts to available width without prototype navigation or manual resizing.

Signed-in Home shows a full-width mention list below the headline with up to three unread mentioned chats, chat images, one-line previews and relative times. The panel has no visible heading or chat count and retains an accessible “Mentioned you” label. When there are no unread mentions, the panel shows a compact, muted “You're all caught up.” line. It reuses the sidebar’s loaded conversations and read cursors (initially 30 chats; “Load more” expands the scope), and opens the existing chat route.

The sidebar separates chats according to their latest verified message. Chats with isBackendMessage: true appear in a separate list between the main conversation list and account controls: up to 15 chats, in a fixed 192px space for three rows before scrolling. The list has no visible heading or status text and keeps that space when empty, loading or unavailable. They do not contribute to unread dots, manual-flag summaries or Home mentions. Unflagged legacy records stay in the main list; no backfill is performed. Release the updated message creation/verification Functions and the new Firestore composite index before the client. Cloud Functions changes require the explicit explanation and approval described in AGENTS.md.

Home event countdowns show days from 24 hours, hours from three hours, and hours plus minutes below three hours (only minutes below one hour). Days and standalone hours round to the nearest whole number; the detailed countdown rounds up to the next minute. The final minute shows “Starting now”, then “In progress” from the start time. The exact start date and time remain visible above the countdown.

Home also shows a compact event notice above the banner from one hour before an event starts until its scheduled end. It displays the earliest-starting active event and the nearest upcoming event within that hour, with “Starts in …”, “Starting now” in the final minute, and “In progress” from the start. Each notice opens the existing event conversation; joining remains available there from five minutes before the start. Dates and times use the viewer’s local timezone. The notice has no dismissal and disappears when an event ends or its cancellation reaches the verified feed. Events without valid start/end times or a conversation link are omitted from the notice. A local clock refreshes timing while Home is visible and on tab return, without additional Firestore reads. Loading or unavailable event data does not show a notice; the existing events panel retains its loading/error/empty feedback.

All pages, including prototypes, share a conversation sidebar with PERRINN, Directory, Discover and Apps navigation. The sidebar uses a scrollable, single-line conversation list with icons, truncated subjects, unread/flag dots, chat options (Add flag / Remove flag) and Load more. The main profile feed retains its existing presentation. The account area below it shows Login when signed out, or a flat clickable row with avatar, name, PRN balance and membership indicator that opens your profile and wallet. User profile headers show Buy PRN before the PRN balance; Settings remain accessible from your profile page. Below 900px, use the header menu button to open navigation; Escape or the backdrop dismisses it, and page navigation closes it automatically. Prototype pages retain their own preview controls within the shared shell. The main chat interface and existing route URLs are unchanged.

The /apps page replaces the Apps popup with a responsive grid linking to Google Drive (when the existing team public link is available), WhatsApp, YouTube, LinkedIn, GitHub and Prototyping. External links open in a new tab; Prototyping opens within the app. The page reads the existing team profile through UserInterfaceService and introduces no new persisted data.

Technology

  • Angular 21, TypeScript, and Angular CLI.
  • Angular NgModules and the Angular Router.
  • AngularFire compatibility APIs with Firebase Authentication, Cloud Firestore, Realtime Database, and Storage.
  • Firebase Cloud Functions v2, written in JavaScript and configured for Node.js 20.
  • Firebase Hosting, with the production client build output served from dist/.

Get started

Install a Node.js and npm version supported by the Angular CLI and install the workspace dependencies:

npm install

Start the development server:

npm start

The app is served at http://localhost:4200/. The development configuration uses src/environments/environment.dev.ts.

Common commands

For safe public network/configuration checks, current findings, the enterprise IT allowlist and CI usage, see ENTERPRISE_ACCESSIBILITY_AUDIT.md. Run npm run audit:enterprise:test and npm run audit:enterprise -- --output /tmp/perrinn-enterprise-audit.json; no credentials or production changes are required.

Command Purpose
npm start Run the Angular development server with the dev configuration.
npm run start:prod Run the Angular development server with the production configuration.
npm run build Create an optimized production build in dist/.
npm run lint Lint the client TypeScript and HTML files.
npm run test:telemetry Check chart range selection, navigation and touch reset gestures.

The root package.json does not currently define test or end-to-end test scripts. The Functions package provides npm start for its Firebase Functions shell, npm run serve for the Firebase Functions serve command, and npm run logs for viewing deployed Functions logs. Firebase emulator ports are configured in firebase.json; run firebase emulators:start to start the configured emulators when the Firebase CLI and a suitable project configuration are available.

Configuration and secrets

The client Firebase web app configuration is selected through Angular environment files:

  • src/environments/environment.dev.ts for local development.
  • src/environments/environment.prod.ts for production builds.

Browser environment values are included in the client bundle and must be treated as public configuration, not secrets. Do not put service account credentials, payment provider keys, or other privileged values in client files. Cloud Functions read privileged integration credentials through Firebase Functions secrets. Keep those values in the project's approved secret management setup and never add them to this README or source control.

Project layout

src/
  app/                 Angular app shell, routed pages, services, pipes, and directive
  environments/        Development and production Firebase client configuration
  styles.css           Global styles and design tokens
functions/             Firebase Cloud Functions v2 handlers and utilities
firebase.json          Hosting, Functions, rules, and emulator configuration
firestore.rules        Cloud Firestore security rules
firestore.indexes.json Cloud Firestore indexes
database.rules.json    Realtime Database rules
storage.rules          Firebase Storage security rules

The root app component provides the shared navigation and layout. The router renders the page components; on chat routes, the app shell also displays a profile side panel. Most app-wide data and shared behavior are handled by UserInterfaceService.

Firebase backend

The Functions code in functions/ handles trusted server-side workflows, including message and payment processing, membership scheduling, storage events, and Drive/GitHub activity integrations. Firebase rules and indexes are maintained at the repository root. firestore.indexes.json is the desired composite-index configuration; see the query coverage audit and index maintenance workflow. Changes to Firestore paths, stored data, rules, or Functions can affect existing client and server workflows, so review the related readers, writers, and access policies together.

Firebase Hosting is configured to serve the production client from dist/ and rewrite application routes to index.html. Production builds enable the service worker; the development build disables it.

For the current Firestore paths, message lifecycle, payment flow, image handling, and rule summary, see data-model.md. Treat it as a source map; inspect the referenced code and rules before changing persisted data or authorization.

Agent and UI guidance

  • AGENTS.md contains repository-specific instructions for coding agents, including architecture, component size, implementation preferences, and security-sensitive changes.
  • ui-spec.md is the design authority for new and rebuilt components. Read it before building or redesigning a component.

The former Home prototype and Layouts gallery category have been retired. Old /prototypes/home links return to /prototypes. The five mosaic experiments remain available through their existing routes and use a dedicated ImageMosaicComponent; production Home at /home remains independent.

The /prototypes/home-mentions UX prototype explores a full-width “Mentioned you” panel below the Home headline, with up to three chat titles, one-line mention previews and relative times. It uses sample content and local conversation previews, with controls for loading, empty and error states and a keyboard-accessible resize handle. It is listed under Home in the prototype gallery; the preview remains independent of the production Home mention list and never changes persisted mention/read state.

The colour gallery includes /prototypes/night-signal-dark, the approved production palette with direct comparison to the original Night Signal study. For CSS ownership and the incremental legacy migration process, see ui-spec.md.

424 Nürburgring Telemetry

/424-telemetry connects directly to ws://127.0.0.1:42480/live on this machine; Firebase is not involved. In the Unity project, enter Play Mode and choose PERRINN → Enable 424 Telemetry in Play Mode, then copy the pairing token from the car's 424 Telemetry inspector. Paste it into the page and connect. Start the client with npm start (port 4200); Chrome may request local-network access. The hosted HTTPS page must also be tested against Chrome's localhost WebSocket policy before relying on production access.

424 Nürburgring Telemetry records 43 channels and displays 33 analysis charts with vertical scales fitted to each visible window. Flap angle (degrees) and DRS position (0–100%) appear immediately before the aero coefficient charts in new recordings; older recordings retain their original channels. It refreshes the Angular display at 10 Hz. Missing channels remain unavailable. Front spring rate sets both front wheels in N/m; autopilot position offset is in metres. Controls show Unity-confirmed values and command results. Input bounds are 10,000–1,000,000 N/m and −10–10 m; these are input guards, not validated vehicle operating limits.

Changes last until the bridge stops, when original settings are restored. Disconnecting the browser does not restore settings. Reconnection reads current parameters and never replays commands; a new Unity session requires its new token. Simulation pause through time scale/vehicle pause allows commands, while the Editor Pause button suspends update handling. Unity now records the full bridge session locally in Application.persistentDataPath/LiveLink/<timestamp>-<session ID>/, including data collected before pairing. The folder appears in the Unity inspector. Each session contains session.json, samples.bin and changes.jsonl; normal bridge shutdown flushes the recording and marks it complete. No recordings are uploaded to Firebase. Browser memory retains all samples while this page is open; reconnect catches up from the active Unity session.

Drag the selected speed-overview window or its edges to inspect history. Drag across the overview background to select a new time or distance range; when the full session is visible, drag anywhere away from its edge handles. Double-click or double-tap the navigation chart to restore the full session; Enter follows the newest live window. Arrow keys pan, plus/minus zoom, and Home shows the full session. Click the Time/Distance label in the sticky navigation area to switch every chart, tick, marker and cursor between time and distance. Distance uses recorded LapDistance in metres, resetting at each lap so all recorded laps overlay on the same axis. Each lap has a distinct colour and labelled channel values. The shared distance cursor resolves a separate original sample per lap; missing ranges and recording gaps stay blank. Clicking a lap makes it active for the map and keyboard stepping. Switching back to time follows that active lap’s sample. Hover a channel chart to temporarily show its pointer position across all channels. Drag horizontally across a channel chart to zoom every channel to the selected time or distance range; double-click or double-tap a channel chart (or press Home while focused) to restore the full session. The selection band stays on the chart being dragged, with a matching dashed preview in the navigation chart; its current window stays visible until release. Vertical touch scrolling remains available. Leaving a chart clears the hover cursor and readouts. Arrow keys step through samples when a chart is focused. Dragging a zoom selection stops automatic live-window following while recording continues. Capture gaps show no sample and unavailable values remain blank. Connected first/min/max/last sample reduction preserves spikes and flat sections at overview scale. Resolution follows the rendered chart width and display pixel density; only actual nulls and capture gaps break the trace. Gold markers show applied parameter changes, subtle narrow red bands around the adjacent trace values show capture gaps over 100 ms, and null channel values break detailed traces. After stopping Unity, choose its timestamped folder with Open a saved session folder to review every final sample. Those files are parsed locally. The generated 30-minute test (90,000 rows) used about 5.6 MB of binary data and 5.3 MB of browser telemetry buffers. See the Unity project's Assets/Features/Unity Live Link/README.md for protocol and build setup.

The 424 Nürburgring Telemetry page automatically loads a bundled copy of the completed 45,165-sample three-lap recording (15 October 2026, 14:30 UTC), including all 43 channels with distance error to trajectory, flap angle, DRS and world position, from src/assets/unity-live-link/sample/. It works without Unity or access to local session folders, including from another machine serving the built web app. The same charts, zoom and cursor tools apply; parameter writes stay disabled. It includes the two recorded front-spring changes (1.1× for lap 2 and 1.2× for lap 3). Only the machine-specific recording path was replaced in the bundled metadata. Sample assets are fetched when this page opens and included in the existing service-worker asset cache after first use.

Telemetry charts calculate each channel’s minimum/maximum from the original samples in the visible time or distance window. Zoom, pan and live following recalculate the Y range. Distance overlays share one range across all displayed laps. This applies to every channel, including percentages, DRS and distance error to trajectory; autoscaling stays within hard limits of 0–100% for balances and DRS, ±500 rpm for front/rear wheel-speed differences, and ±500 mm for distance error to trajectory. Rounded ticks and constant-value padding also respect these limits; values beyond them use the existing edge markers and retain original numeric readouts. Null and non-finite values are ignored, empty windows have no Y ticks, and constant values retain padding. Rounded ticks and cursor dots use the resulting axis. The speed overview fits its own full displayed domain, independently of the zoomed channel range.

Channel charts form one aligned vertical stack, with a shared elapsed-time axis at the bottom of the sticky session navigation, aligned with the channel plot area and no per-chart time/range captions. Names and values sit to the right on wide screens and above full-width charts on mobile. The overview retains its own time labels. Both views include Y labels and subtle grids for their own displayed ranges. Saved folders and the bundled sample open at full-session duration; live connections start in follow mode. Units appear in the chart headings; axis labels remain readable when the plot resizes. Time grids use round elapsed-second intervals anchored to session zero, with whole-second labels by default and fractional seconds when zoomed in. Tick density adapts to plot width, and grid lines match the labels. Cursor/drag coordinates use the plot area, excluding the Y-label gutter.

Telemetry display precision is learned per channel from its full-session min/max: normally one decimal place, with extra decimals for ranges below one unit. Live/cursor values use this formatter. Y-axis labels normally show whole numbers, adding decimals only when needed to represent small grid steps accurately (for example 0.05 or 0.025). Constant channels use their value magnitude; very small ranges use scientific notation. Zoom does not change precision, and stored data remains untouched. Timestamps retain hundredths of a second to distinguish 50 Hz samples.

Chart Y axes expand the learned session range to rounded bounds and uniform 1/2/2.5/5-based intervals, with at most five labeled levels. Meaningfully bipolar channels are symmetric about zero; mostly positive channels keep an asymmetric useful range, and constant channels receive padding. The zero grid line has subtle extra emphasis. Zoom preserves these session-derived axes. Sample-rate diagnostics are omitted from the page.

Lap overlays use thin solid traces: silver for Baseline, gold for Test 1 and sky blue for Test 2, with matching cursor readouts. Distance is the default X axis when lap-distance data is available; sessions without it use time. The axis label switches between distance and time. The 424 Nürburgring Telemetry session navigation area stays visible above scrolling charts and groups an X/Z trajectory map, draggable speed overview and the Time/Distance axis label. Clicking the map pins the nearest recorded sample and brings it into the chart window. At repeated laps, equally close positions prefer the current cursor time. Map geometry preserves world proportions and recording gaps; the dot follows the shared cursor or the latest live sample. The bundled sample includes position channels and displays its recorded trajectory. PositionX/PositionZ are used only by the map; PositionY appears as Altitude in the charts, retaining its original recording index and world elevation in metres. Older recordings without position channels show a placeholder. New Unity captures append world PositionX/PositionY/PositionZ in metres, with Y as elevation; ten-, thirteen- and thirty-one-channel archives are accepted using each binary header’s channel count. Full session remains the initial view for imports. The shell’s content wrappers allow sticky positioning for 424 Nürburgring Telemetry.

New 424 Nürburgring Telemetry recordings contain 40 channels, including lap distance and timing counters/results. The original catalogue contains 31 channels. The 30 visible charts are ordered as lap distance, inputs, accelerations, chassis, individual tire vertical loads, axle left-minus-right wheel rpm differences, motor speeds, electrical power and front shares, aero coefficients/balance, then altitude. chartChannels.ts owns display names/order and preserves raw recording indices. Power/torque shares use front divided by the signed total in percent, with undefined totals left blank. Aero SCx/SCz are area-weighted coefficients (m²), matching the model. The bundled sample includes all 40 channels, with lap distance, lap/sector triggers and timing results. Older archives show only their available recorded channels; a new Unity session is required to capture missing measurements.

Visible-window extrema are calculated before trace reduction, so isolated peaks remain included in the Y range at every resolution. Raw history, recordings and numeric cursor readouts retain original values. Nulls and recording gaps keep their existing breaks.

Drag either side of the speed overview’s selected window to resize its time range while keeping the opposite boundary fixed; drag the middle to pan. Small grips identify the edges, with larger invisible hit areas for touch. Resizing clamps to session bounds and a minimum duration of 0.2 seconds (or the available duration for shorter sessions). Pointer capture keeps resizing active beyond the plot until release/cancel. Chart/map/overview pointer interactions suppress browser focus borders; keyboard focus indicators and existing arrow/zoom controls remain available.

424 Nürburgring Telemetry is available from Apps at /424-telemetry; the former prototype URL redirects there. Session contains a fixed three-lap timing table: Baseline, Test 1 and Test 2, with official simulation-clock lap/sector durations and signed comparisons to Baseline (green faster, red slower). Each test selects a parameter and either an offset in its physical unit or a dimensionless gain, with the resulting target displayed. Both tests use the original setup as their reference; plans lock during the run, and Unity applies each change at that lap’s start. App-started simulations pause at lap 3 completion, recover the final telemetry, then automatically finalize the recording and exit Play Mode. The narrow-screen table scrolls with the lap identity pinned. Timing events are captured immediately and stored as latched counters and result channels, so history recovery and local recording imports preserve them. Captures started mid-lap omit that partial lap until the first recorded start trigger; incomplete laps are labelled. The bundled sample includes three completed valid laps, with distance navigation and sector times available. Firebase data, authorization and Cloud Functions are unchanged.

The follow-live hint scrolls above the sticky navigation area. The Time/Distance label shares the selected-window tick row; the speed overview is taller for dragging and resizing. Recording gaps use narrow bands centred on each channel’s adjacent trace values while the signal itself remains broken.

The Start simulation button becomes Stop simulation once telemetry connects to the running simulation. Use it to end the run; it shows Stopping… until acknowledgement. The authenticated bridge captures a final row, finalizes the local recording, sends a stop acknowledgement, then exits Editor Play Mode or quits the standalone player. The browser disconnects without retrying and keeps its loaded chart history. Saved/sample sessions retain Start simulation; Stop simulation is disabled for connected bridges that do not advertise stop support. An unconfirmed stop displays an error and never retries the command automatically.

In distance mode the speed overview also overlays laps. Its selection pans/resizes a shared lap-distance window. Lap rows choose the active lap without hiding the other overlays. The cursor reads original nearest samples independently for each lap, without interpolating channel values or crossing a recording gap. Partial laps show blanks beyond their recorded distance.

Chart cursors and readouts are transient: hover or focus a chart to inspect samples, and leave or blur it to clear them. There is no persistent cursor pin. Zoom in/out centers on the current window.

Start simulation controls an already-open Unity Editor and starts the car's Autopilot. Pair once using PERRINN → Copy 424 Telemetry Editor pairing token, paste it into the web app and choose Start simulation. Subsequent starts use the remembered local pairing: enter Play Mode, wait for the car, enable telemetry, engage Autopilot through its existing guarded action, then connect the charts automatically. No manual driving is required. The Editor control channel is ws://127.0.0.1:42482/live; transient telemetry sessions continue on port 42480. The pairing secret is stored only in per-project EditorPrefs and this browser's localStorage (perrinn.telemetry.editorToken), and failed Editor authentication clears the rejected browser token and shows pairing again. Domain reloads reconnect using the same operation ID; duplicate starts do not toggle Autopilot off or restart a stopped operation. Missing/invalid recorded laps and refused alignment checks are reported as errors. No cloud data, Firebase rules or Functions change.

424 Nürburgring Telemetry enables Start simulation only after this project’s local Editor controller answers a presence probe. It checks every three seconds and shows when the Editor is unavailable. Presence exposes no pairing token or telemetry; starting still requires Editor pairing.

The pairing form appears only after the Editor is detected and no valid pairing is saved. While the Editor is unavailable, pairing and Start simulation stay hidden. The combined button remains visible during startup and connected runs so Stop simulation stays accessible. Rejected Editor authentication clears the saved token; a temporary presence-check failure preserves it so reopening Unity can reuse the pairing. Autopilot startup errors after successful authentication preserve pairing.

The 424 Nürburgring Telemetry connection panel contains Start/Stop simulation and Open saved session actions. The session-folder picker is hidden behind its button; pairing fields appear only after Start simulation requires pairing, and errors appear only when needed. Routine connection status, sample descriptions and folder-selection instructions are omitted.

The 424 Nürburgring Telemetry panel contains only its charts and navigation, with a concise empty state. Routine capture diagnostics, recording paths, interaction descriptions and the parameter event log are omitted; parameter changes remain available as chart markers and in the local recording. Recording failures appear conditionally beside the connection controls. The minimal-copy rule is documented in ui-spec.md and linked from AGENTS.md.

During a live simulation, the connection toolbar shows only simulation time and the measured speed ratio (for example 3.2×). The ratio uses changes in Unity simulation time divided by changes in its monotonic real-time timestamps over the latest five seconds; it does not display the configured time scale. It waits for one second of measurements, reads 0.0× when paused, and shows an unavailable value for stale telemetry or a reset clock. Browser receipt latency and skipped snapshots do not affect the calculation.

424 Nürburgring Telemetry records AutopilotDistanceError as Distance error to trajectory in mm on new captures; existing files without that channel show an unavailable chart. The final ride-height scatter plots front ride height on X against rear ride height on Y, using original paired samples as dots. It follows the selected time/distance window and lap colours in distance mode. Both axes reuse the exact visible-window bounds and ticks of the corresponding ride-height channel charts and rescale with zoom and pan. Null pairs are omitted.

Hover a ride-height scatter dot to inspect its original paired front/rear values and synchronize the shared chart cursor. Outlined dots identify the selected sample (and corresponding lap samples in distance mode). Hovering a channel chart also highlights its paired ride heights in the scatter. Leave or blur the scatter to clear the cursor; focused arrow keys step through samples. Scatter hit testing uses screen distance and only selects dots within 12 CSS pixels.

Distance error to trajectory uses the same visible-window scaling as every other channel in time and distance views.

Telemetry charts are grouped into Session & trajectory, Driver inputs, Vehicle dynamics, Chassis, Tire loads, Powertrain and Aerodynamics, followed by Correlations for the ride-height scatter. Compact muted labels and thin dividers mark each group without separate cards or expanded section headers. Groups with no available channels are omitted; unknown visible channels appear under Other channels. Grouping changes presentation order only and retains original recorded channel indices, shared navigation and cursor behaviour.

Distance overlays pass the chart's resolved Y axis directly to trace rendering. The trace, tick labels, cursor dots and ride-height scatter therefore share identical bounds; an already rounded axis is never rounded a second time. This prevents offsets on channels whose rounded bounds would otherwise change the signed-range centring decision (including front downforce and ride heights).

About

This is the code for perrinn.com website

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages