Pilot
The new business account interface of La Centrale, built in Next.js and deployed on AWS Lambda behind CloudFront.
- Employer
- Groupe La Centrale
- Role
- Contributor, end-to-end features and platform
- Period
- Stack
- Next.js
- React
- TypeScript
- in-house design system
- react-hook-form
- zod
- chart.js
- AWS Lambda
- CloudFront
- Secrets Manager
- Cognito
- CDK
- Sentry
- Jest
- Testing Library
Context and problem
Car dealers who sell on La Centrale run their business from a dealer back office. Pilot replaces the old interface. Dealers filter a stock of listings that can be large, follow their leads (calls, emails, SMS), buy and track visibility options, and manage their team members' access.
The app is built with Next.js (App Router, Server Components, server actions) and deployed on AWS Lambda behind CloudFront with CDK.
My role
I have worked on Pilot since its first months, in a team of about ten developers. I ship features end to end: the React UI, the server actions, the calls to backend services and the Jest tests. They include the Leads page, the listing filters, multi-select and deletion of listings, the Boost page (built with the team), archived listings, the rebuilt Team members page and the AI video card.
I also took on platform work: reading secrets at runtime, protecting source maps, and fixing truncated permissions in authentication tokens.
Architecture
The app runs serverless, on AWS:
- CloudFront serves the app and its static files. A CloudFront Function filters access to source maps.
- A Lambda runs Next.js: server rendering, Server Components and server actions.
- Pages call the group's backend services: listings, leads, options, user permissions and AI-generated videos.
- Sign-in goes through Cognito. API keys are read at runtime from Secrets Manager.
The infrastructure is written in AWS CDK. Sentry tracks production errors.
Key decisions
Stream the AI video card instead of waiting for it
- Context
The listing page shows the AI-generated video. The video service can be slow, with retries and a timeout, and the card is not critical to the page.
- Choice
The server component starts the call without awaiting it. The card is streamed with Suspense and Await, and a silent ErrorBoundary hides it on failure. A test whose mock never resolves proves the page still renders.
- Rejected alternative
The default option: await the video service in the server component before rendering the page.
- Consequence
Server rendering of the listing page no longer depends on the video service's response time.
Read secrets at runtime
- Context
A Lambda environment is capped at 4 KB, and the API keys injected at deploy time were getting close.
- Choice
Keys are read at runtime from AWS Secrets Manager, with a cache. A check at CDK synth fails the build before the environment reaches the cap.
- Rejected alternative
- Keep injecting every key as a Lambda environment variable.
- Consequence
The environment keeps headroom, and rotating a key no longer needs a redeploy. A malformed secret raises an error that never quotes its value.
Protect source maps without deleting them
- Context
Sentry needs source maps to read production errors, but they must not expose the source code to the public.
- Choice
A dedicated CloudFront behavior for source map files, filtered by a CloudFront Function: only the error tracker or an allowed address can fetch them.
- Rejected alternative
- Strip source maps from the deploy, or leave them public.
- Consequence
Errors stay readable in Sentry, and a public request for a source map is refused.
One parser for truncated permissions
- Context
To fit the size of a token attribute, a user's list of accounts is truncated with a marker. Several parts of the code read that marker differently, and users linked to many accounts were denied access.
- Choice
A single tested helper reads permissions. When it detects truncation, it fetches the full list from the permissions service.
- Rejected alternative
- Fix every place that read the token, one by one.
- Consequence
Users linked to many accounts get their access back, and the parsing rule lives in one place.
Results
Pilot is open to every dealer and handles 5,000 sign-ins a day. The features listed above are in production.
AI in the product
The AI video card on the listing page shows the videos produced by ad2video, the other project I lead. Another Pilot feature uses an LLM: other team members built it.
Limits and what I would do differently
- Pilot depends on many backend services. A page is only as fast as the slowest service it waits on, which is why non-critical blocks are streamed.
- The permissions format is set by the size of token attributes. Truncation is a trade-off: it costs one more call for users linked to many accounts.