diff --git a/common/preview/index.html b/common/preview/index.html
new file mode 100644
index 0000000..356f389
--- /dev/null
+++ b/common/preview/index.html
@@ -0,0 +1,43 @@
+
+
+ pelias autocomplete demo
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/south-africa/.env b/projects/south-africa/.env
new file mode 100644
index 0000000..5dab96a
--- /dev/null
+++ b/projects/south-africa/.env
@@ -0,0 +1,2 @@
+COMPOSE_PROJECT_NAME=pelias_za
+DATA_DIR=/tmp/pelias/pelias_za
diff --git a/projects/south-africa/README.md b/projects/south-africa/README.md
new file mode 100644
index 0000000..45b6dc4
--- /dev/null
+++ b/projects/south-africa/README.md
@@ -0,0 +1,33 @@
+
+# South Africa
+
+This project is configured to download/prepare/build a complete Pelias installation for South Africa.
+
+# Setup
+
+Please refer to the instructions at https://github.com/pelias/docker in order to install and configure your docker environment.
+
+The minimum configuration required in order to run this project are [installing prerequisites](https://github.com/pelias/docker#prerequisites), [install the pelias command](https://github.com/pelias/docker#installing-the-pelias-command) and [configure the environment](https://github.com/pelias/docker#configure-environment).
+
+Please ensure that's all working fine before continuing.
+
+# Run a Build
+
+To run a complete build, execute the following commands:
+
+```bash
+pelias compose pull
+pelias elastic start
+pelias elastic wait
+pelias elastic create
+pelias download all
+pelias prepare all
+pelias import all
+pelias compose up
+```
+
+# Make an Example Query
+
+You can now make queries against your new Pelias build:
+
+http://localhost:4000/v1/search?text=900 park street, tshwane, south africa
diff --git a/projects/south-africa/docker-compose.yml b/projects/south-africa/docker-compose.yml
new file mode 100644
index 0000000..141502e
--- /dev/null
+++ b/projects/south-africa/docker-compose.yml
@@ -0,0 +1,130 @@
+version: '3'
+networks:
+ default:
+ driver: bridge
+volumes:
+ libpostaldata:
+ driver: local
+services:
+ libpostal_baseimage:
+ image: pelias/libpostal_baseimage
+ container_name: pelias_libpostal_baseimage
+ libpostal:
+ image: pelias/go-whosonfirst-libpostal
+ container_name: pelias_libpostal
+ restart: always
+ ports: [ "8080:8080" ]
+ schema:
+ image: pelias/schema:master
+ container_name: pelias_schema
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "./synonyms/custom_name.txt:/code/pelias/schema/synonyms/custom_name.txt"
+ - "./synonyms/custom_street.txt:/code/pelias/schema/synonyms/custom_street.txt"
+ api:
+ image: pelias/api:master
+ container_name: pelias_api
+ restart: always
+ environment: [ "PORT=4000" ]
+ ports: [ "4000:4000" ]
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "libpostaldata:/usr/share/libpostal"
+ placeholder:
+ image: pelias/placeholder:master
+ container_name: pelias_placeholder
+ restart: always
+ environment: [ "PORT=4100" ]
+ ports: [ "4100:4100" ]
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ whosonfirst:
+ image: pelias/whosonfirst:master
+ container_name: pelias_whosonfirst
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ openstreetmap:
+ image: pelias/openstreetmap:master
+ container_name: pelias_openstreetmap
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ - "${DATA_DIR}/tmp:/tmp"
+ openaddresses:
+ image: pelias/openaddresses:master
+ container_name: pelias_openaddresses
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ transit:
+ image: pelias/transit:master
+ container_name: pelias_transit
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ polylines:
+ image: pelias/polylines:master
+ container_name: pelias_polylines
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ interpolation:
+ depends_on: [ "libpostal_baseimage" ]
+ image: pelias/interpolation:master
+ container_name: pelias_interpolation
+ restart: always
+ environment: [ "PORT=4300" ]
+ ports: [ "4300:4300" ]
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "libpostaldata:/usr/share/libpostal"
+ - "${DATA_DIR}:/data"
+ pip:
+ image: pelias/pip-service:master
+ container_name: pelias_pip-service
+ restart: always
+ environment: [ "PORT=4200" ]
+ ports: [ "4200:4200" ]
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ document-service:
+ image: pelias/document-service:master
+ container_name: pelias_document-service
+ restart: always
+ ports: [ "5000:5000" ]
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "${DATA_DIR}:/data"
+ preview:
+ image: nginx
+ container_name: pelias_preview
+ restart: always
+ ports: [ "3000:80" ]
+ volumes:
+ - "../../common/preview:/usr/share/nginx/html"
+ elasticsearch:
+ image: pelias/elasticsearch
+ container_name: pelias_elasticsearch
+ restart: always
+ ports: [ "9200:9200", "9300:9300" ]
+ volumes:
+ - "${DATA_DIR}/elasticsearch:/usr/share/elasticsearch/data"
+ ulimits:
+ memlock:
+ soft: -1
+ hard: -1
+ nofile:
+ soft: 65536
+ hard: 65536
+ cap_add: [ "IPC_LOCK" ]
+ fuzzy-tester:
+ image: pelias/fuzzy-tester:master
+ container_name: pelias_fuzzy_tester
+ restart: "no"
+ command: "--help"
+ volumes:
+ - "./pelias.json:/code/pelias.json"
+ - "./test_cases:/code/pelias/fuzzy-tester/test_cases"
diff --git a/projects/south-africa/pelias.json b/projects/south-africa/pelias.json
new file mode 100644
index 0000000..e3bd22e
--- /dev/null
+++ b/projects/south-africa/pelias.json
@@ -0,0 +1,90 @@
+{
+ "logger": {
+ "level": "info",
+ "timestamp": false
+ },
+ "esclient": {
+ "hosts": [
+ { "host": "elasticsearch" }
+ ]
+ },
+ "elasticsearch": {
+ "settings": {
+ "index": {
+ "refresh_interval": "10s",
+ "number_of_replicas": "0",
+ "number_of_shards": "3"
+ }
+ }
+ },
+ "acceptance-tests": {
+ "endpoints": {
+ "docker": "http://api:4000/v1/"
+ }
+ },
+ "api": {
+ "textAnalyzer": "libpostal",
+ "services": {
+ "pip": { "url": "http://pip-service:4200" },
+ "libpostal": { "url": "http://libpostal:8080" },
+ "placeholder": { "url": "http://placeholder:4100" },
+ "interpolation": { "url": "http://interpolation:4300" }
+ }
+ },
+ "imports": {
+ "adminLookup": {
+ "enabled": true
+ },
+ "geonames": {
+ "datapath": "/data/geonames",
+ "countryCode": "ZA"
+ },
+ "openstreetmap": {
+ "download": [
+ { "sourceURL": "http://download.geofabrik.de/africa/south-africa-latest.osm.pbf" }
+ ],
+ "leveldbpath": "/tmp",
+ "datapath": "/data/openstreetmap",
+ "import": [{
+ "filename": "south-africa-latest.osm.pbf"
+ }]
+ },
+ "openaddresses": {
+ "datapath": "/data/openaddresses",
+ "files": [
+ "za/ec/nelson_mandela_bay.csv",
+ "za/gt/ekurhuleni.csv",
+ "za/gt/tshwane.csv",
+ "za/nl/ethekwini.csv",
+ "za/wc/cape_town.csv"
+ ]
+ },
+ "polyline": {
+ "datapath": "/data/polylines",
+ "files": [ "extract.0sv" ]
+ },
+ "whosonfirst": {
+ "datapath": "/data/whosonfirst",
+ "importVenues": false,
+ "importPostalcodes": true,
+ "importPlace": [
+ "85633813"
+ ]
+ },
+ "transit": {
+ "datapath": "/data/transit",
+ "feeds": [
+ ]
+ },
+ "interpolation": {
+ "download": {
+ "tiger": {
+ "datapath": "/data/tiger",
+ "states": [
+ { "state_code": 41, "county_code": 67, "name": "Washington County, OR" }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/projects/south-africa/synonyms/custom_name.txt b/projects/south-africa/synonyms/custom_name.txt
new file mode 100644
index 0000000..65e4cf5
--- /dev/null
+++ b/projects/south-africa/synonyms/custom_name.txt
@@ -0,0 +1,12 @@
+north, N
+south, S
+east, E
+west, W
+north west => northwest
+north east => northeast
+south west => southwest
+south east => southeast
+northwest, NW
+northeast, NE
+southwest, SW
+southeast, SE
diff --git a/projects/south-africa/synonyms/custom_street.txt b/projects/south-africa/synonyms/custom_street.txt
new file mode 100644
index 0000000..3a13de9
--- /dev/null
+++ b/projects/south-africa/synonyms/custom_street.txt
@@ -0,0 +1,107 @@
+first,1st
+second,2nd
+third,3rd
+forth,4th
+fifth,5th
+sixth,6th
+seventh,7th
+eighth,8th
+nineth,9th
+tenth,10th
+eleventh,11th
+twelfth,12th
+thirteenth,13th
+fourteenth,14th
+fifteenth,15th
+sixteenth,16th
+seventeenth,17th
+eighteenth,18th
+nineteenth,19th
+twentyth,20th
+twentyfirst,21st
+twentysecond,22nd
+twentythrid,23rd
+
+# USPS Suffix Abbreviations
+# http://www.usps.com/ncsc/lookups/abbreviations.html#suffix
+st,st.,street,str
+ave,ave.,av,av.,avenue,AVNUE,AVENUE,AVENU
+dr,drive,dr.,drv,driv,drives
+BOULEVARD,BLVD,BOULEVARD,BOUL,BOULEVARD,BOULEVARD,BOULV
+BRIDGE,BRDGE,BRG
+BYPASS,BYP,BYPA,BYPAS,BYPS
+CLIFF,CLF,CLIFFS,CLFS
+CLUB,CLB
+COMMON,CMN
+CORNER,COR,CORNERS,CORS
+CENTER,CEN,CENT,CENTER,CENTR,CENTRE,CNTER,CNTR,CTR,CENTERS,CTRS
+CIR,CIRC,CIRCL,CIRCLE,CRCL,CIRCLE,CRCLE
+COURT,CRT,CT,COURTS
+CTSCK,CR,CREEK,CRK
+CROSSING,CRSSING,CRSSNG,XING
+CRECENT,CRES,CRESCENT,CRESENT,CRSCNT,CRSENT,CRSNT
+EXP,EXPR,EXPRESS,EXPRESSWAY,EXPW,EXPY
+FALL,FALLS,FLS
+FERRY,FRRY,FRY
+FIELD,FLD,FIELDS,FLDS
+FREEWAY,FREEWY,FRWAY,FRWY,FWY
+GARDEN,GARDN,GDN,GRDEN,GRDN,GARDENS,GDNS,GRDNS
+GATEWAY,GATEWY,GATWAY,GTWAY,GTWY
+GROV,GROVE,GRV,GROVES
+HARB,HARBOR,HARBR,HBR,HRBOR,HARBORS
+HEIGHT,HEIGHTS,HGTS,HT,HTS
+HIGHWAY,HIGHWY,HIWAY,HIWY,HWAY,HWY
+HILL,HL,HILLS,HLS
+IS,ISLAND,ISLND,ISLANDS,ISLNDS,ISS,ISLE,ISLES
+JCT,JCTION,JCTN,JUNCTION,JUNCTN,JUNCTON,JCTNS,JCTS,JUNCTIONS
+LAKE,LK,LAKES,LKS
+LANDING,LNDG,LNDNG
+LA,LANE,LANES,LN
+LOOP,LOOPS,LP
+MANOR,MNR,MANORS,MNRS
+MDW,MEADOW,MDWS,MEADOWS,MEDOWS
+MILL,ML,MILLS,MLS
+MNT,MOUNT,MT
+MNTAIN,MNTN,MOUNTAIN,MOUNTIN,MTIN,MTN,MNTNS,MOUNTAINS
+ORCH,ORCHARD,ORCHRD
+PARK,PK,PRK,PARKS
+PARKWAY,PARKWY,PKWAY,PKWY,PKY,PARKWAYS,PKWYS
+PLAZA,PLZ,PLZA
+PLACE,PL
+PR,PRAIRIE,PRARIE,PRR
+RANCH,RANCHES,RNCH,RNCHS
+RDG,RDGE,RIDGE,RDGS,RIDGES
+RIV,RIVER,RIVR,RVR
+RD,ROAD,RDS,ROADS
+RTESHLS,SHOALS
+SHOAR,SHORE,SHR,SHOARS,SHORES,SHRS
+SPG,SPNG,SPRING,SPRNG,SPGS,SPNGS,SPRINGS,SPRNGS
+SQ,SQR,SQRE,SQU,SQUARE,SQRS,SQUARES
+STA,STATION,STATN,STN
+STREAM,STREME,STRM
+ST,STR,STREET,STRT,STREETS
+SMT,SUMIT,SUMITT,SUMMIT
+TER,TERR,TERRACE
+TR,TRAIL,TRAILS,TRL,TRLS
+TUNEL,TUNL,TUNLS,TUNNEL,TUNNELS,TUNNL
+UN,UNION,UNIONS
+VALLEY,VALLY,VLLY,VLY,VALLEYS,VLYS
+VDCT,VIA,VIADCT,VIADUCT
+VIEW,VW,VIEWS,VWS
+VILL,VILLAG,VILLAGE,VILLG,VILLIAGE,VLG,VILLAGES,VLGS
+VILLE,VL
+VIS,VIST,VISTA,VST,VSTA
+WAY,WY,WAYS
+
+north, N
+south, S
+east, E
+west, W
+north west => northwest
+north east => northeast
+south west => southwest
+south east => southeast
+northwest, NW
+northeast, NE
+southwest, SW
+southeast, SE
diff --git a/projects/south-africa/test_cases/search_address.json b/projects/south-africa/test_cases/search_address.json
new file mode 100644
index 0000000..33e1143
--- /dev/null
+++ b/projects/south-africa/test_cases/search_address.json
@@ -0,0 +1,88 @@
+{
+ "name": "/v1/search address",
+ "description": "addresses in Portland, OR",
+ "priorityThresh": 1,
+ "normalizers": {
+ "name": [
+ "toUpperCase",
+ "removeOrdinals",
+ "stripPunctuation",
+ "abbreviateDirectionals",
+ "abbreviateStreetSuffixes"
+ ]
+ },
+ "tests": [
+ {
+ "id": 1,
+ "status": "pass",
+ "in": {
+ "text": "900 park street, tshwane, south africa"
+ },
+ "expected": {
+ "properties": [
+ {
+ "name": "900 Park Street",
+ "locality": "Tshwane",
+ "country_a": "ZAF"
+ }
+ ]
+ }
+ },
+ {
+ "id": 2,
+ "status": "pass",
+ "in": {
+ "text": "200 Smit Street, Hillbrow"
+ },
+ "expected": {
+ "properties": [
+ {
+ "match_type": "interpolated",
+ "name": "200 Smit Street",
+ "locality": "Hillbrow",
+ "region": "Gauteng",
+ "country_a": "ZAF"
+ }
+ ]
+ }
+ },
+ {
+ "id": 3,
+ "status": "fail",
+ "in": {
+ "text": "Marshall Street, Johannesburg"
+ },
+ "expected": {
+ "properties": [
+ {
+ "match_type": "exact",
+ "layer": "street",
+ "name": "Marshall Street",
+ "locality": "Johannesburg",
+ "region": "Gauteng",
+ "country_a": "ZAF"
+ }
+ ]
+ }
+ },
+ {
+ "id": 3.1,
+ "status": "fail",
+ "in": {
+ "text": "Marshall Street, Hillbrow"
+ },
+ "expected": {
+ "properties": [
+ {
+ "match_type": "exact",
+ "layer": "street",
+ "name": "Marshall Street",
+ "locality": "Hillbrow",
+ "region": "Gauteng",
+ "country_a": "ZAF"
+ }
+ ]
+ }
+ }
+ ]
+}