Vertical Slice Specification

1. Purpose

This document defines the first end-to-end vertical slice of the Foodtruck Order application.

The purpose of this slice is not to implement meaningful foodtruck functionality. Its purpose is to prove that the project's fundamental technical path works as an integrated system:

PostgreSQL
    ↓
Backend data access
    ↓
Backend application/API
    ↓
HTTP/JSON
    ↓
React frontend
    ↓
Browser

The vertical slice must also establish the foundation for:

The slice is intentionally trivial. Its value comes from proving the complete technical path with the smallest possible amount of business logic.

Once this slice is complete, future functionality can be implemented incrementally using the same vertical-slice approach.


2. Scope

2.1 Included

The first vertical slice includes:

  1. A PostgreSQL database.
  2. A minimal database schema containing a message.
  3. Backend database connectivity.
  4. Backend data-access logic.
  5. A backend API endpoint that retrieves the message.
  6. A React frontend that calls the API.
  7. A frontend view that displays the message.
  8. Automated tests at the appropriate testing levels.
  9. Docker-based local infrastructure.
  10. End-to-end verification through the real database.
  11. CI execution of the relevant automated checks.
  12. Documentation of how the system is developed and verified.

2.2 Explicitly excluded

The first vertical slice does not include:

These features may be added in later vertical slices when they provide actual value.

Do not add infrastructure merely because a future feature may eventually require it.


3. Example Feature

The first slice uses a deliberately simple Message concept.

The database contains one message.

For example:

Hello from the database!

The backend exposes an API endpoint:

GET /api/message

The endpoint retrieves the message from PostgreSQL and returns it as JSON.

The frontend calls the endpoint and displays the returned message in the browser.

The final result should therefore be observable by a developer opening the application in a browser:

Hello from the database!

The important property is that the displayed text originates from PostgreSQL.

It must not be hard-coded into the frontend.


4. End-to-End Data Flow

The completed slice must implement the following flow:

┌─────────────┐
│ PostgreSQL  │
│             │
│ Message row │
└──────┬──────┘
       │
       │ SQL / database driver
       ▼
┌─────────────────────┐
│ Backend             │
│                     │
│ Data access         │
│ Application logic   │
│ API endpoint        │
└──────────┬──────────┘
           │
           │ HTTP / JSON
           ▼
┌─────────────────────┐
│ React frontend      │
│                     │
│ API client          │
│ Page / component    │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Browser             │
│                     │
│ Hello from the      │
│ database!           │
└─────────────────────┘

The implementation should follow the architectural boundaries defined in docs/architecture.md.

In particular:


5. Database Requirements

The database must be PostgreSQL.

The slice must contain a minimal schema capable of storing the message.

A possible conceptual model is:

Message
-------
id
text

The exact column names and data types should follow the conventions established during implementation.

The database schema must be reproducible.

A fresh database must be capable of being initialized from the repository without manually creating tables.

Database initialization must therefore use the project's migration or schema-management mechanism rather than undocumented manual SQL commands.

The initial message must also be created reproducibly.

The preferred approach is to use a deterministic seed or equivalent initialization mechanism appropriate to the selected database tooling.

The application must not depend on data that exists only in one developer's local database.


6. Backend Requirements

The backend must:

  1. Start successfully.
  2. Connect to PostgreSQL using configuration rather than hard-coded credentials.
  3. Retrieve the message from the database.
  4. Expose an HTTP endpoint for the frontend.
  5. Return the message as JSON.
  6. Handle the basic failure case where the database cannot be reached.
  7. Be testable independently from the frontend.

The API should follow a simple contract.

Conceptually:

GET /api/message

Successful response:

{
  "message": "Hello from the database!"
}

The exact response structure may be adjusted during implementation if the project's API conventions require it. Once established, the contract should be documented and tested.

The backend must not return a hard-coded response merely to make the frontend work.

The successful response must ultimately originate from PostgreSQL.


7. Frontend Requirements

The frontend must:

  1. Start successfully.
  2. Render a page.
  3. Call the backend API.
  4. Read the returned JSON.
  5. Display the message returned by the backend.
  6. Provide a basic loading state where appropriate.
  7. Provide a basic error state where appropriate.

The message must not be hard-coded into the frontend as the source of the displayed value.

For example, this is valid conceptually:

Frontend
    ↓
GET /api/message
    ↓
Backend
    ↓
PostgreSQL
    ↓
"Hello from the database!"

This is not sufficient:

Frontend
    ↓
"Hello from the database!"

The frontend should remain intentionally simple. The goal is to prove the integration path, not to establish a complete UI design system.


8. API Contract

The API contract must be explicit.

At minimum, the project should document:

The API contract should be covered by automated tests.

The first slice does not require a full OpenAPI specification unless the implementation establishes one naturally.

Do not introduce API-contract tooling solely for this slice unless there is a clear project-wide benefit.


9. Testing Requirements

The vertical slice must demonstrate the project's testing strategy rather than merely contain one test.

Tests should be placed at the lowest appropriate level.

9.1 Backend unit tests

Pure backend logic that contains meaningful behavior should have unit tests where appropriate.

The trivial message retrieval itself may not require extensive unit-test coverage if there is no meaningful logic to isolate.

Do not create artificial abstractions solely to make trivial code unit-testable.

9.2 Backend integration tests

Integration testing must verify the backend's interaction with the database where appropriate.

At minimum, the project should demonstrate that backend code can retrieve persisted data using the real database infrastructure or an explicitly justified test database strategy.

9.3 API tests

The API endpoint should be tested as an HTTP-facing backend interface.

The test should verify at least:

9.4 Frontend tests

The frontend should contain tests appropriate to the selected frontend testing strategy.

At minimum, the important behavior is:

API response
    ↓
frontend state
    ↓
message displayed

The test should verify user-visible behavior rather than implementation details whenever practical.

9.5 End-to-end test

The most important test for the vertical slice is an end-to-end test.

It must verify the complete path:

Browser
  ↓
React frontend
  ↓
HTTP API
  ↓
Backend
  ↓
Database

The E2E test should verify that the browser ultimately displays the message stored in the database.

A test that mocks the backend response does not prove the complete vertical slice.

A test that mocks the database does not prove the complete vertical slice.

Mocks may still be appropriate for lower-level tests, but at least one test must exercise the real integrated path.


10. Test Data

The vertical slice should use deterministic test data.

The expected message should be known and reproducible.

For example:

Hello from the database!

The E2E environment must initialize its own known database state.

Tests must not depend on whatever data happens to exist in a developer's local database.

Tests should be isolated from unrelated local state.


11. Docker Requirements

Docker must provide a reproducible local PostgreSQL environment.

The first slice should support a workflow conceptually equivalent to:

Start Docker services
        ↓
PostgreSQL starts
        ↓
Database is initialized
        ↓
Backend starts
        ↓
Frontend starts
        ↓
Application is available

Docker should be used to reduce differences between developer environments and CI.

The exact Docker architecture and commands are defined by the project's development and Docker documentation.

Do not introduce unnecessary containers.

For the first slice, PostgreSQL is the primary infrastructure requirement.

Redis is not required.


12. CI Requirements

The first vertical slice is not complete until it can be validated by CI.

CI must be able to perform the relevant automated checks from a clean checkout.

At minimum, CI should eventually verify:

The exact CI workflow should be defined in .github/workflows/ and documented in the appropriate project documentation.

CI must not depend on:


13. Local Development Verification

A developer should eventually be able to verify the complete slice locally using documented commands.

The verification flow should be conceptually:

1. Install dependencies.
2. Start the required infrastructure.
3. Initialize the database.
4. Start the backend.
5. Start the frontend.
6. Open the application.
7. Observe the database-backed message.
8. Run automated tests.
9. Run static checks.
10. Run the production build.
11. Run the E2E test.

The exact commands belong in docs/development.md and should be updated as the repository tooling is implemented.


14. Acceptance Criteria

The vertical slice is complete only when all of the following are true and the project Definition of Done is satisfied. Early allowances in this specification for deferred CI/E2E or optional API tooling do not waive the currently implemented CI, Playwright, and OpenAPI requirements.

Repository

Database

Backend

Frontend

Testing

Docker

CI

Documentation


15. Definition of Success

The strongest demonstration of success is:

  1. Start from a clean checkout.
  2. Start the documented infrastructure.
  3. Initialize a fresh PostgreSQL database.
  4. Start the application.
  5. Open the frontend in a browser.
  6. The browser displays:
Hello from the database!
  1. Change the value in the database through the project's reproducible initialization/test mechanism.
  2. Restart or reload the application as appropriate.
  3. The browser displays the new database value.
  4. Automated tests verify the same path.
  5. CI reproduces the relevant verification successfully.

This demonstrates that the displayed value is genuinely flowing through:

PostgreSQL
→ backend data access
→ backend application/API
→ HTTP
→ React
→ browser

That is the core technical proof of the first vertical slice.


16. Implementation Principles

The implementation should follow these principles.

Keep the feature intentionally trivial

The message is a technical proving ground.

Do not turn it into a user-management system, content-management system, or generalized CRUD framework.

Prefer real integration over artificial abstraction

The goal is to prove that the actual technologies work together.

Do not replace PostgreSQL with an in-memory repository merely to simplify tests.

Do not mock the entire backend in the E2E test.

Do not introduce abstractions whose only purpose is to make this trivial feature look architecturally sophisticated.

Introduce infrastructure only when justified

Every dependency and infrastructure component should have a concrete purpose.

The first slice does not need:

Keep boundaries clear

Even though the feature is tiny, it should establish the project's intended boundaries.

The implementation should make it possible to add real functionality later without immediately restructuring the application.

Make failures visible

A passing test suite must represent real verification.

Do not:

If something cannot yet be verified, document the limitation explicitly.


17. Expected Project Evolution

The first vertical slice establishes the foundation for later slices.

Future features should preferably extend the existing path rather than create unrelated parallel architectures.

For example, a future order-related slice may eventually follow:

PostgreSQL
    ↓
Order persistence
    ↓
Order application logic
    ↓
Order API
    ↓
React order UI
    ↓
Browser

A later kitchen-display slice may extend this with real-time communication:

Order state
    ↓
Backend
    ↓
Real-time mechanism
    ↓
Kitchen display

A payment slice may introduce:

Application
    ↓
Payment capability
    ↓
Payment provider adapter
    ↓
External payment service

Those capabilities are deliberately outside the first slice.

The architecture should therefore be designed to evolve toward them without requiring them prematurely.


18. Relationship to Other Documentation

This document defines what the first technical milestone must prove.

Other documents define different aspects of the project:

Document Responsibility
AGENTS.md Rules and instructions for humans and AI agents
docs/techstack.md Technology choices
docs/architecture.md Architectural structure and boundaries
docs/development.md How to develop and verify the application
docs/test-strategy.md Overall testing strategy
docs/specs/001-vertical-slice/vertical-slice.md Exact requirements for the first vertical slice
docs/current-state.md Current implementation state and next step

If these documents appear to conflict, resolve the conflict explicitly rather than silently choosing one.

Implementation-specific details should not be duplicated unnecessarily across documents.


19. AI Agent Guidance

An AI coding agent implementing this slice should work incrementally.

Before making changes:

  1. Read AGENTS.md.
  2. Read docs/architecture.md.
  3. Read docs/development.md.
  4. Read docs/test-strategy.md.
  5. Read this document.
  6. Inspect the current repository state.
  7. Check git status.
  8. Read docs/current-state.md if it exists.

Then implement the smallest coherent next step.

After each meaningful change:

  1. Run the relevant tests.
  2. Run formatting/lint/type checks as applicable.
  3. Verify the implementation against this specification.
  4. Update documentation when the actual repository behavior becomes known.
  5. Update docs/current-state.md.
  6. Leave the repository in a usable state.

Do not assume that conversation history is the project's only source of progress.

The repository itself must contain enough information for another AI agent or developer to continue the work.


20. Completion Report

When the vertical slice is considered complete, the implementation should be accompanied by a concise verification report containing:

An AI agent must distinguish between:

Verified

and:

Not verified

It must not claim successful execution of commands or tests that it did not actually run.


21. Next Step After Completion

Once this vertical slice satisfies the Definition of Done, the project should not immediately expand into a large feature set.

The next step should be selected as the smallest useful vertical slice that adds genuine application functionality while reusing the proven technical foundation.

The project should continue to grow through small, independently verifiable vertical slices rather than completing entire technical layers in isolation.