Speed Up Your Edge Delivery Services Development with a Simple Local Server

Why AI Struggles with Modern EDS Development
Adobe Edge Delivery Services actually offers fast development cycles. The platform itself performs brilliantly. The challenge comes from the development workflow - creating branches, writing content in Google Docs or SharePoint, then coordinating between code, repository, and documents.
This multi-system approach works well for human developers who can mentally juggle these pieces. But it creates an impossible situation for AI assistants. Ask an AI to help debug your EDS block, and it drowns in confusion. It can't see your Google Doc. It can't correlate your branch changes with your SharePoint content. It can't test your code against real data.
The result? Developers work alone, missing out on AI's ability to accelerate development, catch bugs, and suggest improvements. The very workflow that makes EDS powerful for teams makes it impenetrable for AI assistance.
There's a better way.
A Local-First Development Server Changes Everything
I built a simple Node.js server that unifies EDS development into a single, AI-friendly environment. Instead of splitting your workflow across branches, documents, and repositories, everything runs locally. AI assistants can now see your code, test changes instantly, and provide real-time feedback.
The architecture sounds simple because it is. The server checks if a requested file exists locally. If it does, it serves that file. If not, it fetches the file from your production server and passes it through. This local-first, proxy-fallback approach means you can develop individual blocks without juggling multiple systems, and you can obtain resources from EDS Staging or Production -- you choose
You still use branches for version control. You still create documents when needed. But now AI can participate meaningfully in your development process - suggesting code improvements, catching accessibility issues, and debugging problems as they happen.
Here's what makes this approach powerful:
AI-assisted development becomes real when your assistant sees everything in one place. It analyses code, tests changes, and provides intelligent suggestions without getting lost in multiple systems. Save a file and refresh your browser - changes appear immediately. No build process, no deployment wait, no document synchronisation delays. Work on code and content together, test edge cases without switching between systems, and debug with full context available. Server logs show exactly what's happening with each request. Both you and your AI assistant see which files come from local development and which get proxied from production.
Building a Real Block - The Floating Alert Example
Let's walk through building an actual EDS block to see how this workflow transforms development. We'll create a floating alert that appears when users first visit the site.
Start the development server with a simple command:
# Start the server
npm run debug
The server starts immediately, telling you exactly where to find your site:
🚀 Server running at http://localhost:3000
📁 Serving files from: /path/to/project
🔗 Proxying missing files to: https://your-site.com
📄 Main page: http://localhost:3000/server.html
Create your block structure:
blocks/floating-alert/
├── floating-alert.js
├── floating-alert.css
├── README.md
└── test.html
The JavaScript file implements the block's functionality. Modern ES modules work perfectly - no transpilation needed:
// Configuration for the floating alert block
const FLOATING_ALERT_CONFIG = {
STORAGE_KEY: 'floating-alert-dismissed',
ANIMATION_DURATION: 300,
SPARKLE_INTERVAL: 2000,
SPARKLE_DURATION: 1000,
};
// Create sparkle effect
function createSparkle() {
const sparkle = document.createElement('div');
sparkle.className = 'floating-alert-sparkle';
sparkle.style.left = `${Math.random() * 100}%`;
sparkle.style.top = `${Math.random() * 100}%`;
return sparkle;
}
// Main decorate function
export default async function decorate(block) {
if (localStorage.getItem(FLOATING_ALERT_CONFIG.STORAGE_KEY) === 'true') {
return;
}
// Create overlay
const overlay = document.createElement('div');
overlay.className = 'floating-alert-overlay';
// Create modal container
const modal = document.createElement('div');
modal.className = 'floating-alert';
modal.setAttribute('role', 'alert');
modal.setAttribute('aria-live', 'polite');
modal.tabIndex = 0;
// Move block content to modal
const contentWrapper = document.createElement('div');
contentWrapper.className = 'floating-alert-content';
while (block.firstChild) {
contentWrapper.appendChild(block.firstChild);
}
// Create close button with accessibility
const closeButton = document.createElement('button');
closeButton.className = 'floating-alert-close';
closeButton.setAttribute('aria-label', 'Dismiss alert');
closeButton.innerHTML = '×';
closeButton.addEventListener('click', () => dismissAlert(overlay));
// Assemble and display
modal.appendChild(contentWrapper);
modal.appendChild(closeButton);
overlay.appendChild(modal);
document.body.appendChild(overlay);
// Add interactive features
modal._sparkleIntervalId = addSparkleEffect(modal);
setupKeyboardHandling(modal, overlay);
setupClickOutsideHandling(overlay, modal);
}
The CSS demonstrates modern styling with glassmorphism and smooth animations:
/* Configuration variables */
:root {
--alert-bg-color: rgba(255, 165, 0, 0.15);
--alert-border-color: rgba(255, 165, 0, 0.3);
--alert-backdrop-blur: 10px;
--alert-transition-duration: 0.3s;
}
/* Glassmorphic modal */
.floating-alert {
position: relative;
z-index: 1000;
background: var(--alert-bg-color);
backdrop-filter: blur(var(--alert-backdrop-blur));
border: 1px solid var(--alert-border-color);
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
max-width: 600px;
width: 90%;
opacity: 0;
animation: floating-alert-fade-in var(--alert-transition-duration) forwards;
}
/* Smooth entrance animation */
@keyframes floating-alert-fade-in {
from {
opacity: 0;
transform: translateY(-10px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
Navigate to http://localhost:3000/blocks/floating-alert/test.html
and your block appears instantly. Make a change to the CSS, or get your AI to do it - perhaps adjust the blur effect or change the animation timing. Save the file and refresh. The change appears immediately.
The server logs tell the complete story:
Request: GET /blocks/floating-alert/test.html
Serving local file: /blocks/floating-alert/test.html
Request: GET /blocks/floating-alert/floating-alert.css
Serving local file: /blocks/floating-alert/floating-alert.css
Request: GET /blocks/floating-alert/floating-alert.js
Serving local file: /blocks/floating-alert/floating-alert.js
Every request shows whether it's served locally or proxied. When you reference a production asset that doesn't exist locally, the server fetches it automatically:
Request: GET /icons/sprites.svg
Local file not found, attempting proxy
Proxying request to: https://your-site.com/icons/sprites.svg
✅ Successfully proxied: /icons/sprites.svg
The Architecture That Makes It Work
The development server's beauty lies in its simplicity. Three core functions handle everything.
MIME type detection ensures proper content handling:
const mimeTypes = {
'.html': 'text/html',
'.js': 'application/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.svg': 'image/svg+xml',
};
Local file serving delivers your development files instantly:
async function serveLocalFile(filePath, res) {
const content = await readFile(filePath);
const ext = extname(filePath);
const contentType = mimeTypes[ext] || 'application/octet-stream';
res.writeHead(200, {
'Content-Type': contentType,
'Cache-Control': 'no-cache',
});
res.end(content);
}
Intelligent proxying fetches remote assets seamlessly:
async function proxyRequest(url, res) {
const proxyUrl = `${PROXY_HOST}${url}`;
const response = await fetch(proxyUrl);
// Handle both text and binary content
const contentType = response.headers.get('content-type');
const content = contentType.includes('text/')
? await response.text()
: await response.arrayBuffer();
res.writeHead(200, {
'Content-Type': contentType,
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*',
});
res.end(content);
}
Performance From the Start
Build performance into your development process rather than optimising later:
// Lazy load non-critical features
function initializeSparkles() {
requestIdleCallback(() => {
addSparkleEffect(modal);
});
}
// Use passive listeners for better scroll performance
document.addEventListener('scroll', handleScroll, { passive: true });
// Efficient event delegation
overlay.addEventListener('click', (event) => {
if (event.target === overlay) {
dismissAlert(overlay);
}
});
Testing Without the Overhead
Test keyboard navigation, screen readers, and focus management directly in your local environment. No need to deploy to see if your ARIA labels work correctly. Point any browser at your local server - test Safari's backdrop-filter support or Firefox's module loading without touching production. Browser DevTools show real performance metrics against your local code. Optimise animations, reduce JavaScript execution time, and eliminate layout shifts before deployment -- all with AI assist and test.
Why This Approach Transforms EDS Development
Traditional EDS development spreads across multiple tools - code in your editor, content in Google Docs or SharePoint, branches in Git. Each system works well individually, but AI assistants can't navigate this maze. They need unified context to provide meaningful help.
This development server solves that problem elegantly. It brings everything together in one place where both you and AI can work effectively. No webpack configuration files. No babel presets. No complex synchronisation between systems. Just a simple server that creates a single source of truth for development.
The benefits compound quickly. AI becomes genuinely helpful when it can see your full context. Instead of generic suggestions, it provides specific, actionable improvements based on your actual code and content. Development speed increases dramatically when every save gives instant feedback and AI can catch issues immediately, if it has a browser tool it can read logs. What used to take multiple round trips between systems now happens in seconds. Debug clarity improves when both you and your AI assistant see exactly which files come from where. Mystery behaviour becomes transparent logic that AI can help solve. Code quality rises when AI can test edge cases, suggest accessibility improvements, and spot potential issues before they reach production.
Getting Started Takes Minutes
Get the code from GitHub. Copy server.js to your EDS project root. Add script to package.json: "debug": "node server.js"
. Update PROXY_HOST to point to your production site. Run npm run debug
. Start building with AI assistance.
That's it. No complex setup. No configuration files. No dependencies to manage.
The project includes comprehensive documentation designed for AI assistance that humans find equally valuable. The docs folder contains markdown files covering everything from block architecture standards to debugging techniques:
docs/
├── for-ai/
│ ├── block-architecture-standards.md
│ ├── debug.md
│ ├── eds-appendix.md
│ ├── eds-architecture-standards.md
│ ├── eds-native-testing-standards.md
│ ├── eds.md
│ ├── json-prd.md
└── Server-README.md
These documents serve a dual purpose. AI assistants use them to understand EDS patterns, debug issues more effectively, and suggest architecture-compliant solutions. Human developers benefit from the same clear explanations and standards documentation. When you share these docs with your AI assistant, it gains deep context about EDS best practices, testing approaches, and debugging strategies - making its suggestions more relevant and valuable.
Zero Dependencies
The development server has zero external dependencies and uses only Node.js built-in modules:
http
- Creates the HTTP serverfs/promises
- File system operationspath
- Path manipulation utilitiesurl
- URL utilitiesfetch
- HTTP requests (built-in Node.js 18+)
Requirements: Node.js 18+ (for built-in fetch support)
This zero-dependency approach aligns with the project's philosophy of minimal tooling and maximum performance. The server works with any EDS project structure. It doesn't care about your Git workflow or deployment pipeline. It just serves files and proxies requests, staying out of your way while accelerating your development.
Advanced Patterns and Best Practices
The full documentation includes comprehensive guides in the docs folder. These markdown files cover error handling patterns for robust block development, configuration-driven development for maintainable code, performance optimisation techniques, testing strategies for production-ready blocks, and debug helpers specifically designed for AI assistants.
The documentation structure makes it easy to find what you need. Architecture standards guide your block development. Testing standards ensure production readiness. Debug guides help troubleshoot issues quickly. Each document works for both AI assistants and human developers - share them with your AI for better suggestions, or read them yourself for deeper understanding.
The Future of EDS Development
This approach represents more than just a development server. It bridges the gap between EDS's powerful multi-system architecture and the emerging world of AI-assisted development.
As AI tools become essential to modern development, workflows need to adapt. The traditional approach of scattered documents, branches, and deployments creates barriers that even the smartest AI can't overcome. This local server removes those barriers while preserving everything that makes EDS powerful.
Fast feedback loops lead to better code. AI assistance leads to fewer bugs. Simple architecture leads to maintainable systems. When these elements work together, development accelerates beyond what either humans or AI could achieve alone.
The next time you build an EDS block, try this approach. Experience the difference between juggling multiple systems and having everything in one place. Feel the power of AI actually understanding your full context and providing meaningful help.
Development should feel effortless. With the right tools, the right approach, and AI by your side, it can be.
Related Articles