Node / Express API
The backend powering the Angular Template Website is a lightweight Node.js + Express API. Its primary function is to load JSON-based content and return structured data for the Angular application.
The backend is located in the /api directory.
api/
json/
routes/
index.js
package.json
1. Server Structure
The backend follows a conventional Express structure, using a central
index.js file to initialize the server and load route handlers.
// index.js (simplified conceptual example)
const express = require('express');
const app = express();
const routes = require('./routes');
app.use(express.json());
// Mount all routes under /api
app.use('/api', routes);
app.listen(3000, () => console.log('API running on port 3000'));
2. Routes
All API routes live in:
api/routes/
The routing folder typically includes:
- Route definitions
- JSON loading / parsing logic
- Mappings between URL → JSON file
Example Route Structure
// routes/example.js
router.get('/content/:section', (req, res) => {
const file = `${__dirname}/../json/${req.params.section}.json`;
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
res.json(data);
});
The actual route names may differ depending on how your JSON files are organized, but the general logic matches the above pattern.
Advanced Route: Paginated Project API
This API endpoint powers the Library, Standards, Leadership, and Security sections by filtering, paginating, and returning category totals. The Angular services rely heavily on this structure for caching, pagination, and UI updates.
const express = require("express");
const router = express.Router();
const resource = require("../json/projects.json");
router.get("/", (req, res) => {
const results = {};
let filtered = [];
const type = req.query.type;
const page = parseInt(req.query.page);
const limit = parseInt(req.query.limit);
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
type === "all"
? (filtered = resource.data)
: (filtered = resource.data.filter((item) => {
return item.category === type;
}));
results[type] = filtered.slice(startIndex, endIndex);
results.totals = {
all: resource.data.length,
leadership: categoryAmnt("leadership"),
standards: categoryAmnt("standards"),
security: categoryAmnt("security"),
};
res.json(results);
});
const categoryAmnt = (cat) => {
const count = resource.data.filter((item) => {
return item.category === cat;
});
return count.length;
};
module.exports = router;
What This Endpoint Does
- Filters projects by
category - Calculates pagination ranges (
page+limit) - Returns totals for all categories
- Supports caching on the Angular side
- Drives the CategoryNavigation and Pagination components
Response Example
{
"standards": [ ...items ],
"totals": {
"all": 128,
"leadership": 42,
"standards": 56,
"security": 30
}
}
3. JSON Content
JSON files live in:
api/json/
These JSON files represent:
- Category data
- Page content
- Content component mappings
- Project lists
- Navigation metadata
// Example JSON structure
{
"title": "Data Privacy & Security",
"components": [
"information-security",
"records-management",
"insider-trading"
],
"rightColumn": ["fair-competition", "building-trust"]
}
The Angular application uses this JSON to determine which components to render inside
the page-content component.
4. Request Flow
Angular Component
▼
Angular Service (navigation | project-list | page loaders)
▼
HTTP request to /api/...
▼
Routes (inside api/routes)
▼
JSON Loader (api/json)
▼
Response sent back
▼
Angular renders content components based on JSON
5. Example: Angular Service Calling API
// navigation.service.ts
loadPage(section: string) {
return this.http.get(`/api/content/${section}`);
}
The service fetches a JSON content file based on the route, which
page-content then uses to render both:
- actual content components
- right-column recommendations
6. JSON-Driven Component Rendering
{
"components": [
"accurate-book-records",
"environmental-compliance",
"fair-housing"
]
}
This JSON instructs page-content to load each named content component in order.
// page-content (conceptual)
json.components.forEach(c => {
this.loadComponent(c);
});
7. Error Handling
Typical patterns include:
- Try/catch wrapping JSON file reads
- 404 for missing JSON files
- 500 for malformed JSON
- Graceful fallbacks in Angular
try {
const data = loadJson(path);
res.json(data);
} catch (e) {
res.status(500).json({ error: "Unable to load JSON" });
}
8. Summary
The backend is intentionally simple:
- index.js bootstraps Express
- routes/ defines endpoints
- json/ stores structured content
- Angular services request data dynamically
- page-content and content components render the results