Feature Deep Dive
Beyond the core architecture, Gift Moments includes several specialized modules that enhance the user experience.
Extensible Payments
The payment system uses a provider pattern, allowing new gateways to be plugged in without rewriting core logic. This extensibility is crucial for supporting regional payment methods alongside standard providers.
The backend defines a clear contract for payment gateways via the IPaymentGateway interface:
// tc-be/src/common/interfaces/models.interface.ts
export interface IPaymentGateway extends IBase {
gatewayCode: string; // e.g. 'stripe', 'paypal'
gatewayName: string;
isActive: boolean;
apiKeyPublic?: string; // Public API key
apiKeySecret?: string; // Secret API key (encrypted)
webhookSecret?: string; // Webhook secret
webhookUrl?: string; // Webhook URL
}
Media Richness
The application bridges the gap between local and remote content.
External Assets
Native support for linking media from platforms like Vimeo and YouTube is handled via specific providers. For example, the YouTube Provider automatically extracts metadata and handles embedding:
// tc-app/src/app/Services/common/external-providers/youtube-provider.service.ts
@Injectable({
providedIn: 'root'
})
export class YouTubeProviderService extends BaseProviderService {
readonly providerName = 'YouTube';
readonly supportedDomains = ['youtube.com', 'youtu.be'];
/**
* Extract metadata from YouTube URL
*/
extractMetadata(url: string): Observable {
const videoId = this.extractContentId(url);
const metadata: IRemoteContent = {
// ... metadata extraction logic
thumbnailUrl: videoId ? `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg` : undefined,
metadata: {
videoId: videoId,
embedUrl: this.getEmbedUrl(url),
provider: 'youtube'
},
// ...
};
return of(metadata);
}
}
Media Viewer
A custom-built viewer ensures a consistent playback experience across different media types, whether they are local uploads or external streams.

The Treasure Hunt
Perhaps the most unique feature is the Treasure Hunt. It leverages Geolocation to lock content to specific physical coordinates.
We utilize Leaflet to provide an interactive map for setting these locations:
// tc-app/src/app/Features/map-location/map-location-picker.component.ts
private initMap(): void {
// Create map with zoom controls
this.map = L.map('map', {
zoomControl: true,
touchZoom: true,
dragging: true,
tapHold: true,
zoomSnap: 0.5,
}).setView([location.lat, location.lng], 13);
// Add OpenStreetMap tile layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(this.map);
// Add marker at initial position with popup
this.marker = L.marker([location.lat, location.lng], {
draggable: true
})
.addTo(this.map)
.bindPopup(this.capsuleLocationText)
.openPopup();
}

No time to open

Users must physically travel to these coordinates to "unlock" the gift, turning digital gifting into a real-world adventure.
To view in action or collaborate
Demo Site: https://www.packingfuture.com/
Source Code: Github Repository

