This project provides the shared PostgreSQL data platform used by both the Node.js and .NET APIs, exposing a function-based SQL layer that supports filtering, paging, and CRUD operations without duplicating logic in application code.
flowchart TD
%% Layers
subgraph UI["π¨ Frontend Layer"]
ReactUI["React Movie Dashboard<br/>Filtering β’ CRUD β’ API Toggle"]
end
subgraph API["βοΈ API Layer"]
NodeAPI["NodeMovieApi<br/>TypeScript β’ Express<br/>REST + GraphQL"]
DotNetAPI["DotNetMovieApi<br/>.NET Minimal APIs β’ C#<br/>REST + GraphQL"]
end
subgraph DATA["π Data Platform Layer"]
Postgres["Postgres Movie Platform<br/>PostgreSQL β’ Docker β’ pgAdmin"]
Functions["SQL Function API<br/>Filtering β’ Paging β’ Sorting β’ CRUD"]
Tables["Relational Model<br/>movies β’ genres β’ movie_genres"]
end
ReactUI --> NodeAPI
ReactUI --> DotNetAPI
NodeAPI --> Functions
DotNetAPI --> Functions
Functions --> Tables
Tables --> Postgres
%% Styling
classDef frontend fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a;
classDef api fill:#ede9fe,stroke:#7c3aed,stroke-width:2px,color:#0f172a;
classDef data fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#0f172a;
class ReactUI frontend;
class NodeAPI,DotNetAPI api;
class Postgres,Functions,Tables data;
This platform centralizes data logic in PostgreSQL, allowing both Node.js and .NET APIs to support REST and GraphQL without duplicating filtering, paging, or CRUD logic.
A containerized PostgreSQL data platform that powers both REST and GraphQL APIs, providing a reusable function-based query layer for filtering, paging, and CRUD operations.
It is designed to give you:
- A reproducible local PostgreSQL environment
- Seeded movie and genre data
- A many-to-many relational model (
movies,genres,movie_genres) - A function-based SQL API for reads, filtering, paging, create, update, and delete flows
- A ready-to-use pgAdmin instance for exploring the database visually
This project demonstrates how complex query logic can be centralized in the database using PostgreSQL functions, enabling multiple API implementations (Node and .NET) to share a single source of truth for filtering, paging, and data manipulation.
docker-compose.ymlStarts PostgreSQL and pgAdmin.pgadmin/servers.jsonPreloads the PostgreSQL connection in pgAdmin.
db/init/01-init.sqlCreates extensions, schema, tables, seed data, and thewickers.movie_rowcomposite type.db/init/*.sqlCreates the function layer used to read and modify movie data.
db/scripts/start-db.shdb/scripts/reset-db.shdb/scripts/teardown-db.shdb/scripts/start-db.ps1db/scripts/reset-db.ps1db/scripts/teardown-db.ps1
docs/sql/function_api_smoke_test.sqldocs/sql/search_functions.sql
wickers
wickers.moviesStores movie metadata including release date and financial metrics.wickers.genresStores unique genre names.wickers.movie_genresJoins movies to genres in a many-to-many relationship.
The database is initialized with a movie dataset during first boot. Seed rows include movie_link in the table for reference data, but the current create/update API does not expose movie_link to the UI/API contract.
The project exposes a database-level API through PostgreSQL functions.
wickers.get_movies()wickers.get_movies(page, page_size)wickers.get_movies(page, page_size, sort_by, sort_direction)wickers.get_movies(...)Supports search, paging, sorting, release date filters, gross/budget filters, and genre filters.wickers.get_movies_count(...)Returns the count for the same filter set used byget_movies(...).wickers.get_movie_by_id(uuid)wickers.get_genres()wickers.get_genre_by_id(uuid)
wickers.create_movie(...)wickers.update_movie(...)wickers.delete_movie(uuid)wickers.update_graphql_movie(uuid, jsonb)
Before starting, make sure you have:
- Docker Desktop or Docker Engine with
docker compose - An available local port
55432for PostgreSQL - An available local port
58080for pgAdmin
Mac / Linux:
./db/scripts/start-db.shWindows PowerShell:
.\db\scripts\start-db.ps1If PowerShell script execution is blocked:
powershell -ExecutionPolicy Bypass -File .\db\scripts\start-db.ps1The start script:
- Starts PostgreSQL and pgAdmin with Docker Compose
- Waits for PostgreSQL to become healthy
- Waits for pgAdmin to become reachable
- Prints local connection details
| Service | Value |
|---|---|
| pgAdmin | http://localhost:58080 |
| PostgreSQL host | localhost |
| PostgreSQL port | 55432 |
| Database | wickers_db |
| Username | user |
| Password | password |
After startup, open http://localhost:58080.
Use:
- Email:
admin@example.com - Password:
password
The PostgreSQL server is preconfigured through pgadmin/servers.json.
Host: localhost
Port: 55432
Database: wickers_db
User: user
Password: password
Schema: wickers
You can use the examples in docs/sql/function_api_smoke_test.sql.
Examples:
SELECT * FROM wickers.get_movies();
SELECT * FROM wickers.get_movies(
p_search => 'avatar',
p_search_mode => 'general'
);
SELECT * FROM wickers.create_movie(
'Inception',
'2010-07-16',
839000000.00,
160000000.00,
292000000.00,
ARRAY['Action', 'Sci-Fi']
);If you want to rebuild the database from scratch and reload the seed data, use the reset script.
Mac / Linux:
./db/scripts/reset-db.shWindows PowerShell:
.\db\scripts\reset-db.ps1- Stops the current containers
- Removes this project's Docker volumes
- Recreates PostgreSQL and pgAdmin
- Re-runs all initialization SQL in
db/init - Restores the seeded movie dataset
This is the fastest way to return the project to a known-good local state.
If you want to stop and fully remove the local environment for this project:
Mac / Linux:
./db/scripts/teardown-db.shWindows PowerShell:
.\db\scripts\teardown-db.ps1- Stops the PostgreSQL and pgAdmin containers
- Removes this project's containers
- Removes this project's Docker volumes
After teardown, your seeded data and local database state are gone until you run start or reset again.
- The Docker Compose project name is
wickers_movie_demo. - The SQL API is centered around the
wickersschema. movie_linkstill exists in the base seeded table, but it is not part of the current create/update API contract.get_movies(...)andget_movies_count(...)are intended to stay aligned for paging and filter totals.
If 55432 or 58080 is already being used by another local service, stop the conflicting service or remap the ports in docker-compose.yml.
Start Docker Desktop or your local Docker daemon before running any script.
If the schema or function definitions drift during development, run the reset script to recreate the environment from scratch.
- DotNetMovieApi (.NET API implementation)
- NodeMovieApi (TypeScript API implementation)
- Provides a reusable SQL function layer for multiple APIs
- Eliminates duplicated filtering and paging logic across services
- Fully containerized with Docker and pgAdmin
- Designed for reproducible local development environments
Steven Wickers Senior / Lead Frontend Engineer React, TypeScript, Node, C#, PostgreSQL, Cloud






