@longtq2501/next-spring-skills 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtq2501/next-spring-skills",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Standardized best practices and code patterns for Next.js and Spring Boot",
5
5
  "bin": {
6
6
  "next-spring-skills": "bin/cli.js"
package/skills/SKILL.md CHANGED
@@ -63,6 +63,9 @@ See [ui-state.md](./nextjs/ui-state.md) for Zustand store patterns and URL param
63
63
  ### Three.js & 3D
64
64
  See [threejs.md](./nextjs/threejs.md) for high-performance 3D development and R3F.
65
65
 
66
+ ### WebRTC & P2P
67
+ See [webrtc.md](./nextjs/webrtc.md) for real-time media and signaling.
68
+
66
69
  ### Accessibility (a11y)
67
70
  See [accessibility.md](./nextjs/accessibility.md) for semantic HTML and ARIA.
68
71
 
@@ -111,6 +114,10 @@ High-performance, stateless REST API patterns using Spring Boot, JPA, and JWT.
111
114
  - [Query Optimization](./spring/query_optimization.md)
112
115
  - [Performance Optimization](./spring/performance_optimization.md)
113
116
 
117
+ ### Real-time
118
+ - [WebSocket & STOMP](./spring/websocket.md)
119
+ - [Server-Sent Events (SSE)](./spring/sse.md)
120
+
114
121
  ---
115
122
 
116
123
  **Templates:** See the [spring/templates/](./spring/templates/) directory for production-ready boilerplates.
@@ -0,0 +1,77 @@
1
+ # Skill: WebRTC - Peer-to-Peer Communication
2
+
3
+ Guidelines for implementing real-time video, audio, and data streaming between browsers.
4
+
5
+ ## TL;DR - Quick Reference
6
+
7
+ ### Critical Rules
8
+ 1. **Signaling Server Required**: WebRTC needs a side-channel (WebSocket/SSE) to exchange SDP and ICE candidates.
9
+ 2. **ICE Protocol**: Use STUN/TURN servers to bypass NAT and Firewalls. (Google's STUN is for dev, use Twilio/Metered for Prod).
10
+ 3. **Media Constraints**: Use `navigator.mediaDevices.getUserMedia` with specific resolutions to optimize performance.
11
+ 4. **DataChannels**: Use `RTCDataChannel` for low-latency P2P data (e.g., file sharing, gaming).
12
+ 5. **Security**: Always use HTTPS. WebRTC will not work on non-secure origins.
13
+
14
+ ---
15
+
16
+ ## 1. Core Lifecycle (Signaling)
17
+
18
+ WebRTC communication happens in steps:
19
+ 1. **Offer**: Peer A creates an offer (SDP).
20
+ 2. **Answer**: Peer B receives the offer and sends back an answer.
21
+ 3. **ICE Candidates**: Both peers exchange network pathway information.
22
+
23
+ // Bad: Trying to connect without a signaling server
24
+ // Good: Using WebSocket for signaling
25
+ socket.on('offer', async (offer) => {
26
+ await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
27
+ const answer = await peerConnection.createAnswer();
28
+ await peerConnection.setLocalDescription(answer);
29
+ socket.emit('answer', answer);
30
+ });
31
+
32
+ ---
33
+
34
+ ## 2. Media Handling
35
+
36
+ ### Capturing Video/Audio
37
+ // Good: Requesting specific constraints
38
+ const stream = await navigator.mediaDevices.getUserMedia({
39
+ video: { width: 1280, height: 720 },
40
+ audio: true
41
+ });
42
+ videoRef.current.srcObject = stream;
43
+
44
+ ---
45
+
46
+ ## 3. NAT Traversal (STUN/TURN)
47
+ Without these, peers cannot find each other over the public internet.
48
+
49
+ // Good: Configuration with ICE servers
50
+ const pcConfig = {
51
+ iceServers: [
52
+ { urls: 'stun:stun.l.google.com:19302' }, // STUN finds public IP
53
+ {
54
+ urls: 'turn:my-turn-server.com', // TURN relays data if P2P fails
55
+ username: 'user',
56
+ credential: 'password'
57
+ }
58
+ ]
59
+ };
60
+ const peerConnection = new RTCPeerConnection(pcConfig);
61
+
62
+ ---
63
+
64
+ ## 4. Performance & Troubleshooting
65
+
66
+ ### Optimization
67
+ - **Simulcast**: Send multiple resolution streams to cater to different bandwidths.
68
+ - **Bitrate Capping**: Manually limit bandwidth to prevent congestion.
69
+
70
+ ### Debugging
71
+ - **chrome://webrtc-internals**: Essential tool for inspecting connections and bitrates.
72
+
73
+ ---
74
+
75
+ ## Related Skills
76
+ - **WebSocket & STOMP**: `skills/spring/websocket.md`
77
+ - **Interactivity & Animation**: `skills/nextjs/interactivity.md`
@@ -0,0 +1,91 @@
1
+ # Skill: Server-Sent Events (SSE)
2
+
3
+ Guidelines for implementing lightweight unidirectional server-to-client streaming.
4
+
5
+ ## TL;DR - Quick Reference
6
+
7
+ ### Critical Rules
8
+ 1. **Unidirectional**: Use SSE for server-to-client push only (e.g., notifications, stock tickers). Use WebSocket for bi-directional.
9
+ 2. **Standard Protocol**: SSE uses standard HTTP and doesn't require a special protocol upgrade (unlike WebSocket).
10
+ 3. **Reconnection**: Browsers automatically reconnect to SSE streams if the connection drops.
11
+ 4. **Content-Type**: Always set response to `text/event-stream`.
12
+ 5. **Resource Cleaning**: Always complete or timeout `SseEmitter` to avoid thread/memory leaks.
13
+
14
+ ---
15
+
16
+ ## 1. Spring Boot Implementation
17
+
18
+ ### SseEmitter (Imperative)
19
+ Ideal for basic notifications within a standard Spring Web project.
20
+
21
+ // Good: Basic SSE Controller
22
+ @GetMapping(path = "/notifications", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
23
+ public SseEmitter streamNotifications() {
24
+ SseEmitter emitter = new SseEmitter(30_000L); // 30s timeout
25
+
26
+ // In a real app, store emitter in a Map keyed by UserID
27
+ executor.execute(() -> {
28
+ try {
29
+ emitter.send(SseEmitter.event()
30
+ .name("message")
31
+ .data("Hello at " + LocalTime.now()));
32
+ emitter.complete();
33
+ } catch (Exception e) {
34
+ emitter.completeWithError(e);
35
+ }
36
+ });
37
+ return emitter;
38
+ }
39
+
40
+ ### WebFlux (Reactive)
41
+ Best for high-concurrency streaming.
42
+
43
+ // Good: Reactive Streaming
44
+ @GetMapping(path = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
45
+ public Flux<String> streamFlux() {
46
+ return Flux.interval(Duration.ofSeconds(1))
47
+ .map(i -> "Data chunk " + i);
48
+ }
49
+
50
+ ---
51
+
52
+ ## 2. Next.js Client Integration
53
+
54
+ ### EventSource API
55
+ SSE is natively supported by the browser's `EventSource`.
56
+
57
+ // Good: Consuming SSE in React
58
+ useEffect(() => {
59
+ const eventSource = new EventSource('/api/notifications');
60
+
61
+ eventSource.onmessage = (event) => {
62
+ const newData = JSON.parse(event.data);
63
+ setNotifications(prev => [...prev, newData]);
64
+ };
65
+
66
+ eventSource.onerror = (err) => {
67
+ console.error("SSE failed:", err);
68
+ eventSource.close();
69
+ };
70
+
71
+ return () => eventSource.close(); // Important: Cleanup
72
+ }, []);
73
+
74
+ ---
75
+
76
+ ## 3. Advanced Patterns
77
+
78
+ ### Last-Event-ID
79
+ Used for data consistency during reconnections.
80
+ - The server sends an `id` with each event.
81
+ - If the client reconnects, it sends the `Last-Event-ID` header.
82
+
83
+ ### Scaling SSE
84
+ - **Load Balancers**: Ensure your load balancer supports long-lived connections and `text/event-stream` (disable buffering).
85
+ - **Redis Pub/Sub**: Use Redis to broadcast events across multiple server instances.
86
+
87
+ ---
88
+
89
+ ## Related Skills
90
+ - **WebSocket & STOMP**: `skills/spring/websocket.md`
91
+ - **Performance Optimization**: `skills/spring/performance_optimization.md`
@@ -0,0 +1,42 @@
1
+ package com.example.config;
2
+
3
+ import org.springframework.context.annotation.Configuration;
4
+ import org.springframework.messaging.simp.config.ChannelRegistration;
5
+ import org.springframework.messaging.simp.config.MessageBrokerRegistry;
6
+ import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
7
+ import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
8
+ import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
9
+
10
+ /**
11
+ * Standard WebSocket Configuration using STOMP.
12
+ */
13
+ @Configuration
14
+ @EnableWebSocketMessageBroker
15
+ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
16
+
17
+ @Override
18
+ public void configureMessageBroker(MessageBrokerRegistry config) {
19
+ // /topic for Broadcast (1-to-many)
20
+ // /queue for Private (1-to-1)
21
+ config.enableSimpleBroker("/topic", "/queue");
22
+
23
+ // Prefix for messages originating from the client
24
+ config.setApplicationDestinationPrefixes("/app");
25
+
26
+ // Prefix for private messages (SendToUser)
27
+ config.setUserDestinationPrefix("/user");
28
+ }
29
+
30
+ @Override
31
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
32
+ registry.addEndpoint("/ws")
33
+ .setAllowedOrigins("*") // In production, limit this to your frontend domain
34
+ .withSockJS(); // Enables fallback options for older browsers
35
+ }
36
+
37
+ @Override
38
+ public void configureClientInboundChannel(ChannelRegistration registration) {
39
+ // Add interceptors for security (e.g., JWT validation on CONNECT frames)
40
+ // registration.interceptors(myAuthInterceptor);
41
+ }
42
+ }
@@ -0,0 +1,108 @@
1
+ # Skill: WebSocket & Real-time Communication
2
+
3
+ Guidelines for implementing robust, secure, and scalable real-time messaging using Spring Boot (STOMP) and Next.js.
4
+
5
+ ## TL;DR - Quick Reference
6
+
7
+ ### Critical Rules
8
+ 1. **Use STOMP over WebSocket**: Standard sub-protocol for messaging with built-in routing (`@MessageMapping`).
9
+ 2. **Security first**: Authenticate the initial WebSocket handshake using JWT in headers or query params.
10
+ 3. **Heartbeats**: Enable heartbeats to detect and close dead connections promptly.
11
+ 4. **Error Handling**: Use `@MessageExceptionHandler` to gracefully handle errors in message processing.
12
+ 5. **Payload Size**: Keep WebSocket messages small; for large data, send a notification and fetch via REST.
13
+
14
+ ---
15
+
16
+ ## 1. Spring Boot Configuration
17
+
18
+ ### STOMP Setup
19
+ Always separate the message broker into a "Simple Broker" (for dev/local) and a "Full Broker" (like RabbitMQ) for production scaling.
20
+
21
+ // Good: Basic STOMP Configuration
22
+ @Configuration
23
+ @EnableWebSocketMessageBroker
24
+ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
25
+ @Override
26
+ public void configureMessageBroker(MessageBrokerRegistry config) {
27
+ config.enableSimpleBroker("/topic", "/queue"); // Simple in-memory broker
28
+ config.setApplicationDestinationPrefixes("/app");
29
+ }
30
+
31
+ @Override
32
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
33
+ registry.addEndpoint("/ws")
34
+ .setAllowedOrigins("*")
35
+ .withSockJS(); // Fallback for browsers without WS support
36
+ }
37
+ }
38
+
39
+ ---
40
+
41
+ ## 2. Message Handling
42
+
43
+ ### Controller Pattern
44
+ Use `@MessageMapping` to handle incoming messages and `@SendTo` to broadcast output.
45
+
46
+ // Good: Real-time Chat Example
47
+ @Controller
48
+ public class ChatController {
49
+
50
+ @MessageMapping("/chat.send")
51
+ @SendTo("/topic/public")
52
+ public ChatMessage sendMessage(@Payload ChatMessage message) {
53
+ return message;
54
+ }
55
+
56
+ @MessageExceptionHandler
57
+ @SendToUser("/queue/errors")
58
+ public String handleException(Exception exception) {
59
+ return "Error: " + exception.getMessage();
60
+ }
61
+ }
62
+
63
+ ---
64
+
65
+ ## 3. Security (JWT & Interceptors)
66
+ Since WebSockets are long-lived, the initial handshake is the critical entry point, but STOMP frames also need individual validation.
67
+
68
+ ### Handshake vs. Interceptors
69
+ - **Handshake Interceptor**: Used for the initial HTTP upgrade request.
70
+ - **Channel Interceptor**: Required for validating tokens on every `CONNECT` or `SUBSCRIBE` frame.
71
+
72
+ // Good: Registering a STOMP Interceptor
73
+ @Override
74
+ public void configureClientInboundChannel(ChannelRegistration registration) {
75
+ registration.interceptors(new ChannelInterceptor() {
76
+ @Override
77
+ public Message<?> preSend(Message<?> message, MessageChannel channel) {
78
+ StompHeaderAccessor accessor = MessageHeaderUtils.getAccessor(message, StompHeaderAccessor.class);
79
+ if (StompCommand.CONNECT.equals(accessor.getCommand())) {
80
+ String token = accessor.getFirstNativeHeader("Authorization");
81
+ // Validate token and set SecurityContext
82
+ }
83
+ return message;
84
+ }
85
+ });
86
+ }
87
+
88
+ ---
89
+
90
+ ## 4. Frontend Integration (Next.js)
91
+ Use libraries like `@stomp/stompjs` for robust STOMP client management.
92
+
93
+ // Good: Client-side Connection
94
+ const client = new Client({
95
+ brokerURL: 'ws://localhost:8080/ws',
96
+ onConnect: () => {
97
+ client.subscribe('/topic/public', (message) => {
98
+ console.log('Received:', JSON.parse(message.body));
99
+ });
100
+ },
101
+ });
102
+ client.activate();
103
+
104
+ ---
105
+
106
+ ## Related Skills
107
+ - **Security Config**: `skills/spring/security_config.md`
108
+ - **Performance Optimization**: `skills/spring/performance_optimization.md`