Source: Articles on Smashing Magazine — For Web Designers And Developers | Read More
This article is a sponsored by Storyblok
When computers first started talking to each other, the methods were remarkably simple. In the early days of the Internet, systems exchanged files via FTP or communicated via raw TCP/IP sockets. This direct approach worked well for simple use cases but quickly showed its limitations as applications grew more complex.
# Basic socket server example
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(1)
while True:
connection, address = server_socket.accept()
data = connection.recv(1024)
# Process data
connection.send(response)
The real breakthrough in enabling complex communication between computers on a network came with the introduction of Remote Procedure Calls (RPC) in the 1980s. RPC allowed developers to call procedures on remote systems as if they were local functions, abstracting away the complexity of network communication. This pattern laid the foundation for many of the modern integration approaches we use today.
At its core, RPC implements a client-server model where the client prepares and serializes a procedure call with parameters, sends the message to a remote server, the server deserializes and executes the procedure, and then sends the response back to the client.
Here’s a simplified example using Python’s XML-RPC.
# Server
from xmlrpc.server import SimpleXMLRPCServer
def calculate_total(items):
return sum(items)
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(calculate_total)
server.serve_forever()
# Client
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
try:
result = proxy.calculate_total([1, 2, 3, 4, 5])
except ConnectionError:
print("Network error occurred")
RPC can operate in both synchronous (blocking) and asynchronous modes.
Modern implementations such as gRPC support streaming and bi-directional communication. In the example below, we define a gRPC service called Calculator
with two RPC methods, Calculate
, which takes a Numbers
message and returns a Result
message, and CalculateStream
, which sends a stream of Result
messages in response.
// protobuf
service Calculator
rpc Calculate(Numbers) returns (Result);
rpc CalculateStream(Numbers) returns (stream Result);
, [productSlug]);
And return a template with all our data:
<h1>productData.content.title</h1>
<p>productData.content.description</p>
<h2>Price: $inventory.variants[0].price</h2>
<h3>Related Products</h3>
<ul>
relatedProducts.map((product) => (
<li key=product.objectID>product.name</li>
))
</ul>
We could then use an event-driven approach and create a server that listens to our shop events and processes the checkout with Stripe (credits to Manuel Spigolon for this tutorial):
const stripe = require('stripe')
module.exports = async function plugin (app, opts)
const stripeClient = stripe(app.config.STRIPE_PRIVATE_KEY)
server.post('/create-checkout-session', async (request, reply) =>
const session = await stripeClient.checkout.sessions.create(
line_items: [...], // from request.body
mode: 'payment',
success_url: "https://your-site.com/success",
cancel_url: "https://your-site.com/cancel",
)
return reply.redirect(303, session.url)
)
// ...
And with this approach, each service is independent of the others, which helps us achieve our business goals (performance, scalability, flexibility) with a good developer experience and a smaller and simpler application that’s easier to maintain.
Conclusion
The integration between headless CMSs and modern web services represents the current and future state of high-performance web applications. By using specialized, decoupled services, developers can focus on business logic and user experience. A composable ecosystem is not only modular but also resilient to the evolving needs of the modern enterprise.
These integrations highlight the importance of mastering API-driven architectures and understanding how different tools can harmoniously fit into a larger tech stack.
In today’s digital landscape, success lies in choosing tools that offer flexibility and efficiency, adapt to evolving demands, and create applications that are future-proof against the challenges of tomorrow.
If you want to dive deeper into the integrations you can build with Storyblok and other services, check out Storyblok’s integrations page. You can also take your projects further by creating your own plugins with Storyblok’s plugin development resources.