Ascii-Core logoAscii-Core
Technology Stack

The Tools We Use — and Why

Every technology choice on a project carries consequences for maintainability, performance, security and cost. This page documents the tools we use across AI, web, mobile, backend and automation engineering — and the reasoning behind each one.

Stack

AI & Machine Learning

The models, frameworks and vector infrastructure behind our AI systems and agentic workflows.

OpenAI GPT-4o

Frontier language model with vision, function calling and structured output.

Why we use it: Our primary LLM for agentic systems. GPT-4o's function calling API and JSON mode make it the most reliable choice for multi-step AI agents that need to interact with external tools and APIs.

Caveats: API-hosted only. For data-sensitive deployments requiring on-premises processing, we evaluate alternatives or implement data filtering at the boundary.

Anthropic Claude

Constitutional AI model with 200k token context window.

Why we use it: Preferred for document analysis, long-context tasks and situations where constitutional alignment reduces guardrail complexity. The 200k context window handles entire document libraries in a single pass.

Caveats: Available via API. We use Claude 3.5 Sonnet for most workloads and Claude 3 Opus for highest-accuracy requirements.

LangGraph

Stateful multi-agent orchestration framework built on LangChain.

Why we use it: Our framework for complex AI agent pipelines. LangGraph's state machine model handles branching logic, human-in-the-loop interrupts and parallel agent execution in a way that flat chains cannot.

Caveats: Requires Python runtime. For Node.js-native projects we evaluate Vercel AI SDK agent primitives or custom orchestration.

Pinecone / pgvector

Vector databases for semantic search and retrieval-augmented generation.

Why we use it: We choose pgvector for PostgreSQL-native deployments — it keeps vectors co-located with relational data, simplifies infrastructure and avoids an external dependency. Pinecone is preferred for large-scale standalone vector search where query performance at hundreds of millions of vectors is required.

Caveats: pgvector is sufficient for most enterprise RAG systems under 10M vectors. Pinecone becomes cost-effective above that threshold.

Whisper

OpenAI's open-source speech-to-text model.

Why we use it: Used in voice AI pipelines and transcription systems. Whisper outperforms commercial alternatives on Arabic and French — both critical languages for our Morocco-focused client base — and can be self-hosted for data-sensitive deployments.

Caveats: Self-hosted requires GPU inference for real-time transcription. For lower-volume use cases, the OpenAI API is more economical.

Stack

Web & Frontend

The stack behind the web applications, SaaS platforms and internal dashboards we build.

Next.js 15 (App Router)

React framework with SSR, SSG, React Server Components and API routes.

Why we use it: Our primary web framework. One codebase handles all rendering strategies: static generation for marketing pages, server rendering for dynamic data, and React Server Components for performance. The App Router's colocation of data fetching and UI eliminates the waterfall patterns common in older architectures.

Caveats: Best deployed on Vercel for optimal edge functionality, though self-hosting on Docker or Node.js is fully supported.

React 19

Component model with hooks, concurrent features and Server Actions.

Why we use it: The most mature component ecosystem available. React 19's concurrent features and Server Actions reduce the client-side JavaScript needed for interactive applications, improving performance and simplifying data mutation patterns.

Caveats: React 19 is in stable release. Some third-party library compatibility should be verified for new projects.

TypeScript (strict)

Typed superset of JavaScript with strict mode enabled.

Why we use it: Non-negotiable on every project. Strict TypeScript catches entire categories of production bugs at compile time. It also makes codebase handovers significantly safer — every function, API response and component prop is documented by the type system.

Caveats: Requires TypeScript-literate developers. We enforce strict mode and no implicit any across all projects.

Tailwind CSS

Utility-first CSS framework with a consistent design system.

Why we use it: Utility classes eliminate style drift across large codebases. Combined with a design token system, Tailwind makes it possible to maintain visual consistency without a dedicated frontend designer on every sprint.

Caveats: Generates larger HTML attribute lists. Not suitable for projects with strict HTML byte-budget requirements, though purging keeps CSS payload minimal.

Prisma

Type-safe ORM for PostgreSQL with schema migrations and a generated client.

Why we use it: Prisma's schema-first approach generates a fully-typed database client. This means database queries have the same TypeScript safety as the rest of the application, and migrations are version-controlled alongside code.

Caveats: Not suitable for projects requiring fine-grained SQL control. For complex reporting queries we combine Prisma with raw SQL via its query engine.

Stack

Mobile

The frameworks behind the iOS and Android apps we build for clients.

React Native + Expo

Cross-platform iOS and Android apps from a single TypeScript codebase.

Why we use it: One codebase, two platforms. The Expo managed workflow handles build infrastructure, over-the-air updates and device API access without requiring macOS build machines for every developer. Shared business logic with the web frontend reduces total code volume by 30–50%.

Caveats: Near-native but not pixel-identical to pure native. For apps requiring highly custom animation or platform-specific gestures, Flutter may be more appropriate.

Flutter + Dart

Cross-platform framework with a custom rendering engine covering iOS, Android, web and desktop.

Why we use it: When pixel-perfect custom UI is a requirement, or when cross-platform coverage extending to web and desktop is needed, Flutter's custom rendering engine delivers consistent results across all targets. The Dart language is type-safe and easy to onboard for TypeScript developers.

Caveats: Dart is a smaller ecosystem than JavaScript/TypeScript. Third-party integrations may require custom platform-channel implementations.

Firebase

Google's mobile backend platform for push notifications, crash reporting and remote config.

Why we use it: Push notifications, crash reporting and remote configuration are commoditised problems. Firebase handles them reliably without requiring custom infrastructure. We use Firebase as a peripheral service, not as a primary backend.

Caveats: Google-hosted only. For projects with data residency requirements, we implement push via APNs/FCM directly or use self-hosted alternatives.

Stack

Backend & Infrastructure

The runtime, database and deployment infrastructure we build on.

Node.js

JavaScript runtime for API services, serverless functions and automation backends.

Why we use it: Sharing a language across frontend and backend reduces context switching and enables code reuse for validation schemas, types and utilities. Node.js's event loop model handles I/O-intensive API workloads efficiently.

Caveats: CPU-intensive tasks (image processing, ML inference) are better served by Python or dedicated workers. We use task queues to offload heavy computation.

PostgreSQL

Production-grade relational database with ACID compliance and a strong extension ecosystem.

Why we use it: Our default database for every project. PostgreSQL's ACID guarantees, mature query planner, JSON support and extension ecosystem (pgvector for embeddings, PostGIS for geospatial) make it the safest choice for production data. It has been in active development for 30+ years.

Caveats: Requires thoughtful schema design upfront. For unstructured event streams at very high volume, we evaluate TimescaleDB or a dedicated event store alongside PostgreSQL.

Redis

In-memory data store for caching, session management and pub/sub.

Why we use it: API response caching, session storage and real-time pub/sub messaging all benefit from Redis's sub-millisecond latency. We use Upstash for serverless Redis on Vercel and self-hosted Redis for dedicated infrastructure.

Caveats: In-memory by default. Persistence must be explicitly configured. Not appropriate as a primary data store for compliance-sensitive data.

Docker + GitHub Actions

Containerised application packaging and CI/CD pipeline automation.

Why we use it: Docker ensures the development, staging and production environments are identical. GitHub Actions provides the CI/CD pipeline for automated testing, building and deployment — integrated with the repository where code already lives.

Caveats: Container image size requires management. Multi-stage builds keep production images lean.

Vercel

Primary deployment platform for Next.js with edge network, ISR and preview deployments.

Why we use it: Vercel's edge network, Incremental Static Regeneration and automatic preview deployments for every pull request reduce deployment complexity to near zero for Next.js projects. Preview URLs enable client review before merging to production.

Caveats: Vercel is optimised for Next.js. For non-Next.js backends or self-hosted requirements, we use Docker on Railway, Render or a dedicated VPS.

Stack

Automation & Integration

The platforms behind the workflow automation and system integration work we build.

n8n (self-hosted)

Open-source workflow automation with 400+ integrations and native LLM nodes.

Why we use it: Self-hosted n8n means automation workflows run on client infrastructure — data never leaves the organisation's environment. Flat licensing (not per-execution) makes cost predictable at scale. Native LLM nodes for OpenAI and Anthropic are built in, not bolted on.

Caveats: Self-hosting requires infrastructure management. For clients without DevOps capacity, we host and manage n8n as part of the retainer.

Stripe

Payment processing API for web and mobile applications.

Why we use it: The most developer-complete payment API available. Webhooks, subscription billing, payment links and the Customer Portal handle the full commercial lifecycle without custom code. For Moroccan market requirements, we also integrate CMI (Centre Monétique Interbancaire).

Caveats: Not available for Moroccan-domiciled merchants as the primary processor. CMI handles MAD payments; Stripe handles EUR/GBP/USD for international clients.

Supabase

PostgreSQL backend-as-a-service with authentication, storage and real-time subscriptions.

Why we use it: For projects requiring rapid backend provisioning, Supabase provides a PostgreSQL database, row-level security, auth, file storage and real-time subscriptions in one platform. It eliminates backend boilerplate for data-centric applications.

Caveats: Cloud-hosted by default. Self-hosting is supported but adds operational overhead. Not recommended as the primary backend for large-scale production systems without dedicated infrastructure.

REST + GraphQL APIs

Standard integration layer documented with OpenAPI specifications.

Why we use it: REST for most integrations — its statelessness, cacheability and universal tooling support make it the safe default. GraphQL for data-graph-heavy frontends where clients need flexible querying. All APIs we build are documented with OpenAPI (REST) or GraphQL schema introspection.

Caveats: GraphQL adds query complexity and requires persisted query management at scale. We default to REST and add GraphQL only when the data graph justifies it.

Engineering Principles

The principles behind our technology choices

Rules of thumb that guide every technology decision across every project.

TypeScript everywhere

Type safety is not optional. Every project we ship uses TypeScript in strict mode across frontend, backend and shared libraries. It is the single most effective practice for reducing production defects and making codebases safe to hand over.

Open standards over vendor lock-in

Where a widely-adopted open standard exists, we use it. OpenAPI for REST documentation, PostgreSQL for relational data, standard OAuth 2.0 for auth. This makes your system portable — it does not depend on a single vendor's survival or pricing decisions.

Self-hostable where possible

n8n, PostgreSQL, Redis, Whisper and most of our toolchain can run on your own infrastructure. For Morocco and GCC clients with data residency requirements, this is not a preference — it is a requirement. We design for self-hosting from the start.

Observability from day one

Every system we ship includes logging, error tracking and performance monitoring configured before the first user arrives. Observability is not retrofitted after an incident — it is a deployment exit criterion.

Boring technology for infrastructure, exciting technology for product

PostgreSQL, Node.js, Docker and Vercel are not exciting. They are boring in the best way — proven, well-documented and predictable under pressure. We save new technology choices for product-layer differentiation where the risk-reward is justified.

Have a technology question before starting?

Book a 30-minute technical call and talk through your stack requirements with an engineer — not a salesperson.